# HG changeset patch # User cin # Date 2016-02-28 23:02:17 # Node ID e227e78d72e4f792d507444f0ce56396f5873151 # Parent ec35731ae2994fd3cad658174049ec6ea9f98c7e DFA refactoring diff --git a/Implab/Automaton/DFAStateDescriptor.cs b/Implab/Automaton/DFAStateDescriptor.cs --- a/Implab/Automaton/DFAStateDescriptor.cs +++ b/Implab/Automaton/DFAStateDescriptor.cs @@ -1,7 +1,15 @@ namespace Implab.Automaton { - public struct DFAStateDescriptior { - public bool final; - public TTag[] tag; - public int[] transitions; + public struct DFAStateDescriptior { + public readonly bool final; + public readonly int[] transitions; + + + public DFAStateDescriptior(int[] transitions, bool final) { + this.transitions = transitions; + this.final = final; + } + + public DFAStateDescriptior(int[] transitions) : this(transitions, false) { + } } } diff --git a/Implab/Automaton/DFATransitionTable.cs b/Implab/Automaton/DFATransitionTable.cs --- a/Implab/Automaton/DFATransitionTable.cs +++ b/Implab/Automaton/DFATransitionTable.cs @@ -4,8 +4,8 @@ using System.Collections.Generic; using System.Linq; namespace Implab.Automaton { - public class DFATransitionTable : IDFATransitionTableBuilder { - DFAStateDescriptior[] m_dfaTable; + public class DFATransitionTable : IDFATableBuilder { + DFAStateDescriptior[] m_dfaTable; int m_stateCount; int m_symbolCount; @@ -17,7 +17,7 @@ namespace Implab.Automaton { #region IDFADefinition implementation - public DFAStateDescriptior[] GetTransitionTable() { + public DFAStateDescriptior[] GetTransitionTable() { if (m_dfaTable == null) { if (m_stateCount <= 0) throw new InvalidOperationException("Invalid automaton definition: states count = {0}", m_stateCount); @@ -108,7 +108,7 @@ namespace Implab.Automaton { #endregion protected void Optimize( - IDFATransitionTableBuilder optimalDFA, + IDFATableBuilder optimalDFA, IAlphabet inputAlphabet, IAlphabetBuilder optimalInputAlphabet, IAlphabet stateAlphabet, diff --git a/Implab/Automaton/DFAutomaton.cs b/Implab/Automaton/DFAutomaton.cs deleted file mode 100644 --- a/Implab/Automaton/DFAutomaton.cs +++ /dev/null @@ -1,61 +0,0 @@ -using Implab; -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.Automaton { - public abstract class DFAutomaton { - protected struct ContextFrame { - public DFAStateDescriptior[] states; - public int current; - public T info; - } - - public const int INITIAL_STATE = DFADefinition.INITIAL_STATE; - public const int UNREACHEBLE_STATE = DFADefinition.UNREACHEBLE_STATE; - - protected ContextFrame m_context; - Stack m_contextStack = new Stack(); - - protected int Level { - get { return m_contextStack.Count; } - } - - protected DFAutomaton(DFAStateDescriptior[] states, int startState, T info) { - Safe.ArgumentNotNull(states, "states"); - Safe.ArgumentInRange(startState, 0, states.Length - 1, "startState"); - - m_context.states = states; - m_context.current = startState; - m_context.info = info; - } - - protected void Switch(DFAStateDescriptior[] states, int current, T info) { - Debug.Assert(states != null); - Debug.Assert(current >= 0 && current < states.Length); - m_contextStack.Push(m_context); - m_context.states = states; - m_context.current = current; - m_context.info = info; - } - - protected void Restore() { - Debug.Assert(m_contextStack.Count > 0); - - m_context = m_contextStack.Pop(); - } - - protected void Move(int input) { - Debug.Assert(input > 0 && input < m_context.states[m_context.current].transitions.Length); - m_context.current = m_context.states[m_context.current].transitions[input]; - } - - protected bool CanMove(int input) { - Debug.Assert(input > 0 && input < m_context.states[m_context.current].transitions.Length); - return m_context.states[m_context.current].transitions[input] != UNREACHEBLE_STATE; - } - } -} diff --git a/Implab/Automaton/IDFATable.cs b/Implab/Automaton/IDFATable.cs new file mode 100644 --- /dev/null +++ b/Implab/Automaton/IDFATable.cs @@ -0,0 +1,59 @@ +using System.Collections.Generic; + + +namespace Implab.Automaton { + /// + /// Полностью описывает DFA автомат, его поведение, состояние и входные символы. + /// + /// + /// class MyAutomaton { + /// int m_current; + /// readonly DFAStateDescriptor[] m_automaton; + /// readonly IAlphabet m_commands; + /// + /// public MyAutomaton(IDFADefinition<MyCommands,MyStates,string> definition) { + /// m_current = definition.StateAlphabet.Translate(MyStates.Initial); + /// m_automaton = definition.GetTransitionTable(); + /// m_commands = definition.InputAlphabet; + /// } + /// + /// // defined a method which will move the automaton to the next state + /// public void Move(MyCommands cmd) { + /// // use transition map to determine the next state + /// var next = m_automaton[m_current].transitions[m_commands.Translate(cmd)]; + /// + /// // validate that we aren't in the unreachable state + /// if (next == DFAConst.UNREACHABLE_STATE) + /// throw new InvalidOperationException("The specified command is invalid"); + /// + /// // if everything is ok + /// m_current = next; + /// } + /// } + /// + public interface IDFATable { + /// + /// Таблица переходов состояний автомата + /// + /// The transition table. + DFAStateDescriptior[] GetTransitionTable(); + + int StateCount { + get; + } + + int AlphabetSize { + get; + } + + int InitialState { + get; + } + + bool IsFinalState(int s); + + IEnumerable FinalStates { + get; + } + } +} diff --git a/Implab/Automaton/IDFATableBuilder.cs b/Implab/Automaton/IDFATableBuilder.cs new file mode 100644 --- /dev/null +++ b/Implab/Automaton/IDFATableBuilder.cs @@ -0,0 +1,24 @@ +using System; + +namespace Implab.Automaton { + public interface IDFATableBuilder : IDFATable { + /// + /// Marks the state as final. + /// + /// State. + void MarkFinalState(int state); + + /// + /// Defines the transition from to + /// with input . + /// + /// S1. + /// S2. + /// Symbol. + void DefineTransition(int s1, int s2, int symbol); + + void SetInitialState(int s); + + } +} + diff --git a/Implab/Automaton/IDFATransitionTable.cs b/Implab/Automaton/IDFATransitionTable.cs deleted file mode 100644 --- a/Implab/Automaton/IDFATransitionTable.cs +++ /dev/null @@ -1,59 +0,0 @@ -using System.Collections.Generic; - - -namespace Implab.Automaton { - /// - /// Полностью описывает DFA автомат, его поведение, состояние и входные символы. - /// - /// - /// class MyAutomaton { - /// int m_current; - /// readonly DFAStateDescriptor[] m_automaton; - /// readonly IAlphabet m_commands; - /// - /// public MyAutomaton(IDFADefinition<MyCommands,MyStates,string> definition) { - /// m_current = definition.StateAlphabet.Translate(MyStates.Initial); - /// m_automaton = definition.GetTransitionTable(); - /// m_commands = definition.InputAlphabet; - /// } - /// - /// // defined a method which will move the automaton to the next state - /// public void Move(MyCommands cmd) { - /// // use transition map to determine the next state - /// var next = m_automaton[m_current].transitions[m_commands.Translate(cmd)]; - /// - /// // validate that we aren't in the unreachable state - /// if (next == DFAConst.UNREACHABLE_STATE) - /// throw new InvalidOperationException("The specified command is invalid"); - /// - /// // if everything is ok - /// m_current = next; - /// } - /// } - /// - public interface IDFATransitionTable { - /// - /// Таблица переходов состояний автомата - /// - /// The transition table. - DFAStateDescriptior[] GetTransitionTable(); - - int StateCount { - get; - } - - int AlphabetSize { - get; - } - - int InitialState { - get; - } - - bool IsFinalState(int s); - - IEnumerable> FinalStates { - get; - } - } -} diff --git a/Implab/Automaton/IDFATransitionTableBuilder.cs b/Implab/Automaton/IDFATransitionTableBuilder.cs deleted file mode 100644 --- a/Implab/Automaton/IDFATransitionTableBuilder.cs +++ /dev/null @@ -1,25 +0,0 @@ -using System; - -namespace Implab.Automaton { - public interface IDFATransitionTableBuilder : IDFATransitionTable { - /// - /// Marks the state as final and assings tags. - /// - /// State. - /// Tags. - void MarkFinalState(int state, params TTag[] tags); - - /// - /// Defines the transition from to - /// with input . - /// - /// S1. - /// S2. - /// Symbol. - void DefineTransition(int s1, int s2, int symbol); - - void SetInitialState(int s); - - } -} - diff --git a/Implab/Automaton/RegularExpressions/Grammar.cs b/Implab/Automaton/RegularExpressions/Grammar.cs --- a/Implab/Automaton/RegularExpressions/Grammar.cs +++ b/Implab/Automaton/RegularExpressions/Grammar.cs @@ -2,48 +2,46 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Implab.Automaton.RegularExpressions { /// /// Базовый абстрактный класс. Грамматика, позволяет формулировать выражения над алфавитом типа char. /// - public abstract class Grammar { + public abstract class Grammar { - public abstract IAlphabetBuilder Alphabet { + protected abstract IAlphabetBuilder AlphabetBuilder { get; } - public SymbolToken UnclassifiedToken() { + protected SymbolToken UnclassifiedToken() { return new SymbolToken(DFAConst.UNCLASSIFIED_INPUT); } - public void DefineAlphabet(IEnumerable alphabet) { + protected void DefineAlphabet(IEnumerable alphabet) { Safe.ArgumentNotNull(alphabet, "alphabet"); foreach (var ch in alphabet) - Alphabet.DefineSymbol(ch); + AlphabetBuilder.DefineSymbol(ch); } - public Token SymbolToken(TSymbol symbol) { + protected Token SymbolToken(TSymbol symbol) { return Token.New(TranslateOrAdd(symbol)); } - public Token SymbolToken(IEnumerable symbols) { + protected Token SymbolToken(IEnumerable symbols) { Safe.ArgumentNotNull(symbols, "symbols"); return Token.New(TranslateOrAdd(symbols).ToArray()); } - public Token SymbolSetToken(params TSymbol[] set) { + protected Token SymbolSetToken(params TSymbol[] set) { return SymbolToken(set); } int TranslateOrAdd(TSymbol ch) { - var t = Alphabet.Translate(ch); + var t = AlphabetBuilder.Translate(ch); if (t == DFAConst.UNCLASSIFIED_INPUT) - t = Alphabet.DefineSymbol(ch); + t = AlphabetBuilder.DefineSymbol(ch); return t; } @@ -52,7 +50,7 @@ namespace Implab.Automaton.RegularExpres } int TranslateOrDie(TSymbol ch) { - var t = Alphabet.Translate(ch); + var t = AlphabetBuilder.Translate(ch); if (t == DFAConst.UNCLASSIFIED_INPUT) throw new ApplicationException(String.Format("Symbol '{0}' is UNCLASSIFIED", ch)); return t; @@ -62,33 +60,31 @@ namespace Implab.Automaton.RegularExpres return symbols.Distinct().Select(TranslateOrDie); } - public Token SymbolTokenExcept(IEnumerable symbols) { + protected Token SymbolTokenExcept(IEnumerable symbols) { Safe.ArgumentNotNull(symbols, "symbols"); - return Token.New( Enumerable.Range(0, Alphabet.Count).Except(TranslateOrDie(symbols)).ToArray() ); + return Token.New( Enumerable.Range(0, AlphabetBuilder.Count).Except(TranslateOrDie(symbols)).ToArray() ); } - protected CDFADefinition BuildDFA(Token lang) { + protected void BuildDFA(Token lang, IDFATableBuilder dfaTable, IAlphabetBuilder dfaAlphabet) { Safe.ArgumentNotNull(lang, "lang"); + Safe.ArgumentNotNull(dfaAlphabet, "dfaAlphabet"); - var dfa = new RegularDFADefinition(Alphabet, 0); - - var table = new DFATransitionTable(); + var dfa = new RegularDFADefinition(AlphabetBuilder); var builder = new RegularDFABuilder(); lang.Accept( builder ); - var initialState = builder.BuildDFA(table); - if (table.IsFinalState(initialState)) + builder.BuildDFA(dfa); + + if (dfa.IsFinalState(dfa.InitialState)) throw new ApplicationException("The specified language contains empty token"); - return dfa.Optimize(); + dfa.Optimize(dfaTable, dfaAlphabet); + } - - - //protected abstract TGrammar CreateInstance(); } diff --git a/Implab/Automaton/RegularExpressions/RegularDFABuilder.cs b/Implab/Automaton/RegularExpressions/RegularDFABuilder.cs --- a/Implab/Automaton/RegularExpressions/RegularDFABuilder.cs +++ b/Implab/Automaton/RegularExpressions/RegularDFABuilder.cs @@ -11,7 +11,7 @@ namespace Implab.Automaton.RegularExpres /// для построения автомата. /// public class RegularDFABuilder : IVisitor { - int m_idx = 0; + int m_idx; Token m_root; HashSet m_firstpos; HashSet m_lastpos; @@ -26,18 +26,18 @@ namespace Implab.Automaton.RegularExpres public HashSet Followpos(int pos) { HashSet set; - if (m_followpos.TryGetValue(pos, out set)) - return set; - return m_followpos[pos] = new HashSet(); + return m_followpos.TryGetValue(pos, out set) ? set : m_followpos[pos] = new HashSet(); } bool Nullable(object n) { if (n is EmptyToken || n is StarToken) return true; - if (n is AltToken) - return Nullable(((AltToken)n).Left) || Nullable(((AltToken)n).Right); - if (n is CatToken) - return Nullable(((CatToken)n).Left) && Nullable(((CatToken)n).Right); + var altToken = n as AltToken; + if (altToken != null) + return Nullable(altToken.Left) || Nullable(altToken.Right); + var catToken = n as CatToken; + if (catToken != null) + return Nullable(catToken.Left) && Nullable(catToken.Right); return false; } @@ -122,7 +122,7 @@ namespace Implab.Automaton.RegularExpres m_ends.Add(m_idx, token.Tag); } - public void BuildDFA(IDFATransitionTableBuilder dfa) { + public void BuildDFA(IDFATableBuilder dfa) { Safe.ArgumentNotNull(dfa,"dfa"); var states = new MapAlphabet>(new CustomEqualityComparer>( diff --git a/Implab/Automaton/RegularExpressions/RegularDFADefinition.cs b/Implab/Automaton/RegularExpressions/RegularDFADefinition.cs --- a/Implab/Automaton/RegularExpressions/RegularDFADefinition.cs +++ b/Implab/Automaton/RegularExpressions/RegularDFADefinition.cs @@ -4,13 +4,11 @@ namespace Implab.Automaton.RegularExpres public class RegularDFADefinition : DFATransitionTable, IDFATransitionTable { readonly IAlphabet m_alphabet; - readonly int m_initialState; - public RegularDFADefinition(IAlphabet alphabet, int initialState) { + public RegularDFADefinition(IAlphabet alphabet) { Safe.ArgumentNotNull(alphabet, "aplhabet"); m_alphabet = alphabet; - m_initialState = initialState; } @@ -30,14 +28,13 @@ namespace Implab.Automaton.RegularExpres /// /// Optimize the specified alphabet. /// + /// /// Пустой алфавит, который будет зполнен в процессе оптимизации. - public RegularDFADefinition Optimize(IAlphabetBuilder alphabet) { + public void Optimize(IDFATableBuilder dfaTable, IAlphabetBuilder alphabet) { Safe.ArgumentNotNull(alphabet, "alphabet"); + Safe.ArgumentNotNull(dfaTable, "dfaTable"); - var optimalDFA = new RegularDFADefinition(alphabet, m_initialState); - - Optimize(optimalDFA, InputAlphabet, alphabet, new DummyAlphabet(StateCount), new MapAlphabet()); - + Optimize(dfaTable, InputAlphabet, alphabet, new DummyAlphabet(StateCount), new MapAlphabet()); } diff --git a/Implab/Automaton/RegularExpressions/Token.cs b/Implab/Automaton/RegularExpressions/Token.cs --- a/Implab/Automaton/RegularExpressions/Token.cs +++ b/Implab/Automaton/RegularExpressions/Token.cs @@ -10,7 +10,7 @@ namespace Implab.Automaton.RegularExpres return Cat(new EndToken()); } - public Token Tag(T tag) where T : IConvertible { + public Token Tag(TTag tag) { return Cat(new EndToken(tag)); } @@ -48,11 +48,11 @@ namespace Implab.Automaton.RegularExpres var token = Repeat(min); for (int i = min; i < max; i++) - token = token.Cat( this.Optional() ); + token = token.Cat( Optional() ); return token; } - public static Token New(params T[] set) where T : struct, IConvertible { + public static Token New(params int[] set) { Safe.ArgumentNotNull(set, "set"); Token token = null; foreach(var c in set.Distinct()) diff --git a/Implab/Automaton/Scanner.cs b/Implab/Automaton/Scanner.cs --- a/Implab/Automaton/Scanner.cs +++ b/Implab/Automaton/Scanner.cs @@ -29,7 +29,7 @@ namespace Implab.Automaton { protected DFAStateDescriptior m_currentState; int m_previewCode; - protected int m_tokenLen = 0; + protected int m_tokenLen; protected int m_tokenOffset; protected char[] m_buffer; @@ -142,18 +142,17 @@ namespace Implab.Automaton { if (nextState == DFAConst.UNREACHABLE_STATE) { if (m_currentState.final) return true; - else - throw new ParserException( - String.Format( - "Unexpected symbol '{0}', at pos {1}", - m_buffer[m_pointer], - Position - ) - ); - } else { - m_currentState = m_states[nextState]; - m_tokenLen++; + + throw new ParserException( + String.Format( + "Unexpected symbol '{0}', at pos {1}", + m_buffer[m_pointer], + Position + ) + ); } + m_currentState = m_states[nextState]; + m_tokenLen++; } while (Shift()); @@ -220,6 +219,7 @@ namespace Implab.Automaton { /// /// Таблица состояний нового ДКА /// Таблица входных символов для нового ДКА + /// protected void Switch(DFAStateDescriptior[] states, int[] alphabet, int initialState) { Safe.ArgumentNotNull(states, "dfa"); diff --git a/Implab/Formats/ByteAlphabet.cs b/Implab/Formats/ByteAlphabet.cs --- a/Implab/Formats/ByteAlphabet.cs +++ b/Implab/Formats/ByteAlphabet.cs @@ -1,8 +1,8 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; +using Implab.Automaton; -namespace Implab.Automaton { +namespace Implab.Formats { public class ByteAlphabet : IndexedAlphabetBase { public ByteAlphabet() : base(byte.MaxValue + 1){ } diff --git a/Implab/Formats/CharAlphabet.cs b/Implab/Formats/CharAlphabet.cs --- a/Implab/Formats/CharAlphabet.cs +++ b/Implab/Formats/CharAlphabet.cs @@ -1,11 +1,8 @@ -using Implab; -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Implab.Automaton; -namespace Implab.Automaton { +namespace Implab.Formats { public class CharAlphabet: IndexedAlphabetBase { public CharAlphabet() diff --git a/Implab/Formats/JSON/JSONElementContext.cs b/Implab/Formats/JSON/JSONElementContext.cs --- a/Implab/Formats/JSON/JSONElementContext.cs +++ b/Implab/Formats/JSON/JSONElementContext.cs @@ -1,14 +1,8 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.JSON { +namespace Implab.Formats.JSON { /// /// internal /// - public enum JSONElementContext { + enum JSONElementContext { None, Object, Array, diff --git a/Implab/Formats/JSON/JSONElementType.cs b/Implab/Formats/JSON/JSONElementType.cs --- a/Implab/Formats/JSON/JSONElementType.cs +++ b/Implab/Formats/JSON/JSONElementType.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.JSON { +namespace Implab.Formats.JSON { /// /// Тип элемента на котором находится парсер /// diff --git a/Implab/Formats/JSON/JSONGrammar.cs b/Implab/Formats/JSON/JSONGrammar.cs --- a/Implab/Formats/JSON/JSONGrammar.cs +++ b/Implab/Formats/JSON/JSONGrammar.cs @@ -1,8 +1,9 @@ using System.Linq; using Implab.Automaton.RegularExpressions; +using System; namespace Implab.Formats.JSON { - class JSONGrammar : Grammar { + class JSONGrammar : Grammar { public enum TokenType { None, BeginObject, @@ -28,8 +29,14 @@ namespace Implab.Formats.JSON { Exp } - readonly CDFADefinition m_jsonDFA; - readonly CDFADefinition m_stringDFA; + static Lazy _instance = new Lazy(); + + public static JSONGrammar Instance { + get { return _instance.Value; } + } + + readonly RegularCharDFADefinition m_jsonDFA; + readonly RegularCharDFADefinition m_stringDFA; public JSONGrammar() { DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x)); @@ -80,20 +87,29 @@ namespace Implab.Formats.JSON { .Or(unescaped.Closure().Tag(TokenType.UnescapedChar)); - m_jsonDFA = BuildDFA(jsonExpression); - m_stringDFA = BuildDFA(jsonStringExpression); + m_jsonDFA = new RegularCharDFADefinition(new CharAlphabet()); + BuildDFA(jsonExpression, m_jsonDFA, m_jsonDFA.InputAlphabet); + + + m_stringDFA = new RegularCharDFADefinition(new CharAlphabet()); + BuildDFA(jsonStringExpression, m_jsonDFA, m_jsonDFA.InputAlphabet); } - public CDFADefinition JsonDFA { + public RegularCharDFADefinition JsonDFA { get { return m_jsonDFA; } } - public CDFADefinition JsonStringDFA { + public RegularDFADefinition JsonStringDFA { get { return m_stringDFA; } } + + Token SymbolRangeToken(char start, char stop) { + return SymbolToken(Enumerable.Range(start,stop - start).Cast()); + } + } } diff --git a/Implab/Formats/JSON/JSONParser.cs b/Implab/Formats/JSON/JSONParser.cs --- a/Implab/Formats/JSON/JSONParser.cs +++ b/Implab/Formats/JSON/JSONParser.cs @@ -1,9 +1,12 @@ -using Implab.Parsing; -using System; +using System; using System.Diagnostics; using System.IO; +using Implab.Automaton; +using Implab.Automaton.RegularExpressions; +using System.Linq; +using Implab.Components; -namespace Implab.JSON { +namespace Implab.Formats.JSON { /// /// internal /// @@ -28,53 +31,65 @@ namespace Implab.JSON { /// } // Level = 0 /// /// - public class JSONParser : DFAutomaton, IDisposable { + public class JSONParser : Disposable { enum MemberContext { MemberName, MemberValue } + struct ParserContext { + DFAStateDescriptior + } + static readonly EnumAlphabet _alphabet = EnumAlphabet.FullAlphabet; - static readonly DFAStateDescriptior[] _jsonDFA; - static readonly DFAStateDescriptior[] _objectDFA; - static readonly DFAStateDescriptior[] _arrayDFA; + static readonly DFAStateDescriptior[] _jsonDFA; + static readonly int _jsonDFAInitialState; + static readonly DFAStateDescriptior[] _objectDFA; + static readonly int _objectDFAInitialState; + static readonly DFAStateDescriptior[] _arrayDFA; + static readonly int _arrayDFAInitialState; static JSONParser() { - var valueExpression = Token.New(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String); - var memberExpression = Token.New(JsonTokenType.String).Cat(Token.New(JsonTokenType.NameSeparator)).Cat(valueExpression); + var valueExpression = Token(JsonTokenType.BeginArray, JsonTokenType.BeginObject, JsonTokenType.Literal, JsonTokenType.Number, JsonTokenType.String); + var memberExpression = Token(JsonTokenType.String).Cat(Token(JsonTokenType.NameSeparator)).Cat(valueExpression); var objectExpression = memberExpression .Cat( - Token.New(JsonTokenType.ValueSeparator) + Token(JsonTokenType.ValueSeparator) .Cat(memberExpression) .EClosure() ) .Optional() - .Cat(Token.New(JsonTokenType.EndObject)) - .Tag(0); + .Cat(Token(JsonTokenType.EndObject)) + .Tag(null); var arrayExpression = valueExpression .Cat( - Token.New(JsonTokenType.ValueSeparator) + Token(JsonTokenType.ValueSeparator) .Cat(valueExpression) .EClosure() ) .Optional() - .Cat(Token.New(JsonTokenType.EndArray)) - .Tag(0); + .Cat(Token(JsonTokenType.EndArray)) + .Tag(null); - var jsonExpression = valueExpression.Tag(0); + var jsonExpression = valueExpression.Tag(null); - _jsonDFA = BuildDFA(jsonExpression).States; - _objectDFA = BuildDFA(objectExpression).States; - _arrayDFA = BuildDFA(arrayExpression).States; + _jsonDFA = CreateDFA(jsonExpression).GetTransitionTable(); + _objectDFA = CreateDFA(objectExpression).GetTransitionTable(); + _arrayDFA = CreateDFA(arrayExpression).GetTransitionTable(); } - static EDFADefinition BuildDFA(Token expr) { - var builder = new DFABuilder(); - var dfa = new EDFADefinition(_alphabet); + static Token Token(params JsonTokenType[] input) { + return Token.New(input.Select(t => _alphabet.Translate(t)).ToArray()); + } + + static RegularDFADefinition CreateDFA(Token expr) { + var builder = new RegularDFABuilder(); + var dfa = new RegularDFADefinition(_alphabet); + expr.Accept(builder); builder.BuildDFA(dfa); @@ -243,25 +258,13 @@ namespace Implab.JSON { } } - protected virtual void Dispose(bool disposing) { + protected override void Dispose(bool disposing) { if (disposing) { m_scanner.Dispose(); } } /// - /// Освобождает парсер и связанный с ним сканнер. - /// - public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~JSONParser() { - Dispose(false); - } - - /// /// Переходит в конец текущего объекта. /// public void SeekElementEnd() { diff --git a/Implab/Formats/JSON/JSONScanner.cs b/Implab/Formats/JSON/JSONScanner.cs --- a/Implab/Formats/JSON/JSONScanner.cs +++ b/Implab/Formats/JSON/JSONScanner.cs @@ -1,25 +1,21 @@ -using Implab.Parsing; -using System; -using System.Collections.Generic; +using System; using System.Globalization; -using System.Linq; -using System.Text; -using System.Threading.Tasks; +using Implab.Automaton; -namespace Implab.JSON { +namespace Implab.Formats.JSON { /// /// Сканнер (лексер), разбивающий поток символов на токены JSON. /// - public class JSONScanner : Scanner { + public class JSONScanner : Scanner { char[] m_stringBuffer; - DFAStateDescriptior[] m_stringDFA; + DFAStateDescriptior<>[] m_stringDFA; int[] m_stringAlphabet; /// /// Создает новый экземпляр сканнера /// public JSONScanner() - : base(JSONGrammar.Instance.JsonDFA.States, JSONGrammar.Instance.JsonDFA.Alphabet.GetTranslationMap()) { + : base(JSONGrammar.Instance.JsonDFA.GetTransitionTable(), JSONGrammar.Instance.JsonDFA.Alphabet.GetTranslationMap()) { m_stringBuffer = new char[1024]; var dfa = JSONGrammar.Instance.JsonStringDFA; m_stringAlphabet = dfa.Alphabet.GetTranslationMap(); diff --git a/Implab/Formats/JSON/JsonTokenType.cs b/Implab/Formats/JSON/JsonTokenType.cs --- a/Implab/Formats/JSON/JsonTokenType.cs +++ b/Implab/Formats/JSON/JsonTokenType.cs @@ -1,10 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; - -namespace Implab.JSON { +namespace Implab.Formats.JSON { /// /// Тип токенов, возвращаемых . /// diff --git a/Implab/Formats/RegularCharDFADefinition.cs b/Implab/Formats/RegularCharDFADefinition.cs new file mode 100644 --- /dev/null +++ b/Implab/Formats/RegularCharDFADefinition.cs @@ -0,0 +1,17 @@ +using System; +using Implab.Automaton.RegularExpressions; + +namespace Implab.Formats { + public class RegularCharDFADefinition : RegularDFADefinition { + readonly CharAlphabet m_alphabet; + + public RegularCharDFADefinition(CharAlphabet alphabet) : base(alphabet) { + m_alphabet = alphabet; + } + + public new CharAlphabet InputAlphabet { + get { return m_alphabet; } + } + } +} + diff --git a/Implab/Implab.csproj b/Implab/Implab.csproj --- a/Implab/Implab.csproj +++ b/Implab/Implab.csproj @@ -152,7 +152,6 @@ - @@ -185,11 +184,12 @@ - - + + +