Mercurial > pub > ImplabNet
changeset 165:e227e78d72e4 ref20160224
DFA refactoring
line wrap: on
line diff
--- a/Implab/Automaton/DFAStateDescriptor.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Automaton/DFAStateDescriptor.cs Mon Feb 29 02:02:17 2016 +0300 @@ -1,7 +1,15 @@ namespace Implab.Automaton { - public struct DFAStateDescriptior<TTag> { - 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) { + } } }
--- a/Implab/Automaton/DFATransitionTable.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Automaton/DFATransitionTable.cs Mon Feb 29 02:02:17 2016 +0300 @@ -4,8 +4,8 @@ using System.Linq; namespace Implab.Automaton { - public class DFATransitionTable<TTag> : IDFATransitionTableBuilder<TTag> { - DFAStateDescriptior<TTag>[] m_dfaTable; + public class DFATransitionTable<TTag> : IDFATableBuilder { + DFAStateDescriptior[] m_dfaTable; int m_stateCount; int m_symbolCount; @@ -17,7 +17,7 @@ #region IDFADefinition implementation - public DFAStateDescriptior<TTag>[] 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 @@ #endregion protected void Optimize<TInput, TState>( - IDFATransitionTableBuilder<TTag> optimalDFA, + IDFATableBuilder<TTag> optimalDFA, IAlphabet<TInput> inputAlphabet, IAlphabetBuilder<TInput> optimalInputAlphabet, IAlphabet<TState> stateAlphabet,
--- a/Implab/Automaton/DFAutomaton.cs Thu Feb 25 02:11:13 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -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<T> { - 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<ContextFrame> m_contextStack = new Stack<ContextFrame>(); - - 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; - } - } -}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/IDFATable.cs Mon Feb 29 02:02:17 2016 +0300 @@ -0,0 +1,59 @@ +using System.Collections.Generic; + + +namespace Implab.Automaton { + /// <summary> + /// Полностью описывает DFA автомат, его поведение, состояние и входные символы. + /// </summary> + /// <example> + /// class MyAutomaton { + /// int m_current; + /// readonly DFAStateDescriptor<string>[] m_automaton; + /// readonly IAlphabet<MyCommands> 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; + /// } + /// } + /// </example> + public interface IDFATable { + /// <summary> + /// Таблица переходов состояний автомата + /// </summary> + /// <returns>The transition table.</returns> + DFAStateDescriptior[] GetTransitionTable(); + + int StateCount { + get; + } + + int AlphabetSize { + get; + } + + int InitialState { + get; + } + + bool IsFinalState(int s); + + IEnumerable<int> FinalStates { + get; + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Automaton/IDFATableBuilder.cs Mon Feb 29 02:02:17 2016 +0300 @@ -0,0 +1,24 @@ +using System; + +namespace Implab.Automaton { + public interface IDFATableBuilder : IDFATable { + /// <summary> + /// Marks the state as final. + /// </summary> + /// <param name="state">State.</param> + void MarkFinalState(int state); + + /// <summary> + /// Defines the transition from <paramref name="s1"/> to + /// <paramref name="s2"/> with input <paramref name="symbol"/>. + /// </summary> + /// <param name="s1">S1.</param> + /// <param name="s2">S2.</param> + /// <param name="symbol">Symbol.</param> + void DefineTransition(int s1, int s2, int symbol); + + void SetInitialState(int s); + + } +} +
--- a/Implab/Automaton/IDFATransitionTable.cs Thu Feb 25 02:11:13 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -using System.Collections.Generic; - - -namespace Implab.Automaton { - /// <summary> - /// Полностью описывает DFA автомат, его поведение, состояние и входные символы. - /// </summary> - /// <example> - /// class MyAutomaton { - /// int m_current; - /// readonly DFAStateDescriptor<string>[] m_automaton; - /// readonly IAlphabet<MyCommands> 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; - /// } - /// } - /// </example> - public interface IDFATransitionTable<TTag> { - /// <summary> - /// Таблица переходов состояний автомата - /// </summary> - /// <returns>The transition table.</returns> - DFAStateDescriptior<TTag>[] GetTransitionTable(); - - int StateCount { - get; - } - - int AlphabetSize { - get; - } - - int InitialState { - get; - } - - bool IsFinalState(int s); - - IEnumerable<KeyValuePair<int,TTag[]>> FinalStates { - get; - } - } -}
--- a/Implab/Automaton/IDFATransitionTableBuilder.cs Thu Feb 25 02:11:13 2016 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -using System; - -namespace Implab.Automaton { - public interface IDFATransitionTableBuilder<TTag> : IDFATransitionTable<TTag> { - /// <summary> - /// Marks the state as final and assings tags. - /// </summary> - /// <param name="state">State.</param> - /// <param name="tags">Tags.</param> - void MarkFinalState(int state, params TTag[] tags); - - /// <summary> - /// Defines the transition from <paramref name="s1"/> to - /// <paramref name="s2"/> with input <paramref name="symbol"/>. - /// </summary> - /// <param name="s1">S1.</param> - /// <param name="s2">S2.</param> - /// <param name="symbol">Symbol.</param> - void DefineTransition(int s1, int s2, int symbol); - - void SetInitialState(int s); - - } -} -
--- a/Implab/Automaton/RegularExpressions/Grammar.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Automaton/RegularExpressions/Grammar.cs Mon Feb 29 02:02:17 2016 +0300 @@ -2,48 +2,46 @@ using System; using System.Collections.Generic; using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Implab.Automaton.RegularExpressions { /// <summary> /// Базовый абстрактный класс. Грамматика, позволяет формулировать выражения над алфавитом типа <c>char</c>. /// </summary> - public abstract class Grammar<TSymbol, TTag> { + public abstract class Grammar<TSymbol, TTag> { - public abstract IAlphabetBuilder<TSymbol> Alphabet { + protected abstract IAlphabetBuilder<TSymbol> AlphabetBuilder { get; } - public SymbolToken<TTag> UnclassifiedToken() { + protected SymbolToken<TTag> UnclassifiedToken() { return new SymbolToken<TTag>(DFAConst.UNCLASSIFIED_INPUT); } - public void DefineAlphabet(IEnumerable<TSymbol> alphabet) { + protected void DefineAlphabet(IEnumerable<TSymbol> alphabet) { Safe.ArgumentNotNull(alphabet, "alphabet"); foreach (var ch in alphabet) - Alphabet.DefineSymbol(ch); + AlphabetBuilder.DefineSymbol(ch); } - public Token<TTag> SymbolToken(TSymbol symbol) { + protected Token<TTag> SymbolToken(TSymbol symbol) { return Token<TTag>.New(TranslateOrAdd(symbol)); } - public Token<TTag> SymbolToken(IEnumerable<TSymbol> symbols) { + protected Token<TTag> SymbolToken(IEnumerable<TSymbol> symbols) { Safe.ArgumentNotNull(symbols, "symbols"); return Token<TTag>.New(TranslateOrAdd(symbols).ToArray()); } - public Token<TTag> SymbolSetToken(params TSymbol[] set) { + protected Token<TTag> 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 @@ } 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 @@ return symbols.Distinct().Select(TranslateOrDie); } - public Token<TTag> SymbolTokenExcept(IEnumerable<TSymbol> symbols) { + protected Token<TTag> SymbolTokenExcept(IEnumerable<TSymbol> symbols) { Safe.ArgumentNotNull(symbols, "symbols"); - return Token<TTag>.New( Enumerable.Range(0, Alphabet.Count).Except(TranslateOrDie(symbols)).ToArray() ); + return Token<TTag>.New( Enumerable.Range(0, AlphabetBuilder.Count).Except(TranslateOrDie(symbols)).ToArray() ); } - protected CDFADefinition BuildDFA(Token<TTag> lang) { + protected void BuildDFA(Token<TTag> lang, IDFATableBuilder<TTag> dfaTable, IAlphabetBuilder<TSymbol> dfaAlphabet) { Safe.ArgumentNotNull(lang, "lang"); + Safe.ArgumentNotNull(dfaAlphabet, "dfaAlphabet"); - var dfa = new RegularDFADefinition<TSymbol, TTag>(Alphabet, 0); - - var table = new DFATransitionTable<TTag>(); + var dfa = new RegularDFADefinition<TSymbol, TTag>(AlphabetBuilder); var builder = new RegularDFABuilder<TTag>(); 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(); }
--- a/Implab/Automaton/RegularExpressions/RegularDFABuilder.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Automaton/RegularExpressions/RegularDFABuilder.cs Mon Feb 29 02:02:17 2016 +0300 @@ -11,7 +11,7 @@ /// <see cref="BuildDFA(IDFADefinition)"/> для построения автомата. /// </summary> public class RegularDFABuilder<TTag> : IVisitor<TTag> { - int m_idx = 0; + int m_idx; Token<TTag> m_root; HashSet<int> m_firstpos; HashSet<int> m_lastpos; @@ -26,18 +26,18 @@ public HashSet<int> Followpos(int pos) { HashSet<int> set; - if (m_followpos.TryGetValue(pos, out set)) - return set; - return m_followpos[pos] = new HashSet<int>(); + return m_followpos.TryGetValue(pos, out set) ? set : m_followpos[pos] = new HashSet<int>(); } bool Nullable(object n) { if (n is EmptyToken<TTag> || n is StarToken<TTag>) return true; - if (n is AltToken<TTag>) - return Nullable(((AltToken<TTag>)n).Left) || Nullable(((AltToken<TTag>)n).Right); - if (n is CatToken<TTag>) - return Nullable(((CatToken<TTag>)n).Left) && Nullable(((CatToken<TTag>)n).Right); + var altToken = n as AltToken<TTag>; + if (altToken != null) + return Nullable(altToken.Left) || Nullable(altToken.Right); + var catToken = n as CatToken<TTag>; + if (catToken != null) + return Nullable(catToken.Left) && Nullable(catToken.Right); return false; } @@ -122,7 +122,7 @@ m_ends.Add(m_idx, token.Tag); } - public void BuildDFA(IDFATransitionTableBuilder<TTag> dfa) { + public void BuildDFA(IDFATableBuilder<TTag> dfa) { Safe.ArgumentNotNull(dfa,"dfa"); var states = new MapAlphabet<HashSet<int>>(new CustomEqualityComparer<HashSet<int>>(
--- a/Implab/Automaton/RegularExpressions/RegularDFADefinition.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Automaton/RegularExpressions/RegularDFADefinition.cs Mon Feb 29 02:02:17 2016 +0300 @@ -4,13 +4,11 @@ public class RegularDFADefinition<TInput, TTag> : DFATransitionTable<TTag>, IDFATransitionTable<TTag> { readonly IAlphabet<TInput> m_alphabet; - readonly int m_initialState; - public RegularDFADefinition(IAlphabet<TInput> alphabet, int initialState) { + public RegularDFADefinition(IAlphabet<TInput> alphabet) { Safe.ArgumentNotNull(alphabet, "aplhabet"); m_alphabet = alphabet; - m_initialState = initialState; } @@ -30,14 +28,13 @@ /// <summary> /// Optimize the specified alphabet. /// </summary> + /// <param name = "dfaTable"></param> /// <param name="alphabet">Пустой алфавит, который будет зполнен в процессе оптимизации.</param> - public RegularDFADefinition<TInput, TTag> Optimize(IAlphabetBuilder<TInput> alphabet) { + public void Optimize(IDFATableBuilder<TTag> dfaTable, IAlphabetBuilder<TInput> alphabet) { Safe.ArgumentNotNull(alphabet, "alphabet"); + Safe.ArgumentNotNull(dfaTable, "dfaTable"); - var optimalDFA = new RegularDFADefinition<TInput,TTag>(alphabet, m_initialState); - - Optimize(optimalDFA, InputAlphabet, alphabet, new DummyAlphabet(StateCount), new MapAlphabet<int>()); - + Optimize(dfaTable, InputAlphabet, alphabet, new DummyAlphabet(StateCount), new MapAlphabet<int>()); }
--- a/Implab/Automaton/RegularExpressions/Token.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Automaton/RegularExpressions/Token.cs Mon Feb 29 02:02:17 2016 +0300 @@ -10,7 +10,7 @@ return Cat(new EndToken<TTag>()); } - public Token<TTag> Tag<T>(T tag) where T : IConvertible { + public Token<TTag> Tag(TTag tag) { return Cat(new EndToken<TTag>(tag)); } @@ -48,11 +48,11 @@ 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<TTag> New<T>(params T[] set) where T : struct, IConvertible { + public static Token<TTag> New(params int[] set) { Safe.ArgumentNotNull(set, "set"); Token<TTag> token = null; foreach(var c in set.Distinct())
--- a/Implab/Automaton/Scanner.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Automaton/Scanner.cs Mon Feb 29 02:02:17 2016 +0300 @@ -29,7 +29,7 @@ protected DFAStateDescriptior<TTag> 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 @@ 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 @@ /// </summary> /// <param name="states">Таблица состояний нового ДКА</param> /// <param name="alphabet">Таблица входных символов для нового ДКА</param> + /// <param name = "initialState"></param> protected void Switch(DFAStateDescriptior<TTag>[] states, int[] alphabet, int initialState) { Safe.ArgumentNotNull(states, "dfa");
--- a/Implab/Formats/ByteAlphabet.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Formats/ByteAlphabet.cs Mon Feb 29 02:02:17 2016 +0300 @@ -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<byte> { public ByteAlphabet() : base(byte.MaxValue + 1){ }
--- a/Implab/Formats/CharAlphabet.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Formats/CharAlphabet.cs Mon Feb 29 02:02:17 2016 +0300 @@ -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<char> { public CharAlphabet()
--- a/Implab/Formats/JSON/JSONElementContext.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Formats/JSON/JSONElementContext.cs Mon Feb 29 02:02:17 2016 +0300 @@ -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 { /// <summary> /// internal /// </summary> - public enum JSONElementContext { + enum JSONElementContext { None, Object, Array,
--- a/Implab/Formats/JSON/JSONElementType.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Formats/JSON/JSONElementType.cs Mon Feb 29 02:02:17 2016 +0300 @@ -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 { /// <summary> /// Тип элемента на котором находится парсер /// </summary>
--- a/Implab/Formats/JSON/JSONGrammar.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Formats/JSON/JSONGrammar.cs Mon Feb 29 02:02:17 2016 +0300 @@ -1,8 +1,9 @@ using System.Linq; using Implab.Automaton.RegularExpressions; +using System; namespace Implab.Formats.JSON { - class JSONGrammar : Grammar<JSONGrammar> { + class JSONGrammar : Grammar<char,JSONGrammar.TokenType> { public enum TokenType { None, BeginObject, @@ -28,8 +29,14 @@ Exp } - readonly CDFADefinition m_jsonDFA; - readonly CDFADefinition m_stringDFA; + static Lazy<JSONGrammar> _instance = new Lazy<JSONGrammar>(); + + public static JSONGrammar Instance { + get { return _instance.Value; } + } + + readonly RegularCharDFADefinition<TokenType> m_jsonDFA; + readonly RegularCharDFADefinition<TokenType> m_stringDFA; public JSONGrammar() { DefineAlphabet(Enumerable.Range(0, 0x20).Select(x => (char)x)); @@ -80,20 +87,29 @@ .Or(unescaped.Closure().Tag(TokenType.UnescapedChar)); - m_jsonDFA = BuildDFA(jsonExpression); - m_stringDFA = BuildDFA(jsonStringExpression); + m_jsonDFA = new RegularCharDFADefinition<TokenType>(new CharAlphabet()); + BuildDFA(jsonExpression, m_jsonDFA, m_jsonDFA.InputAlphabet); + + + m_stringDFA = new RegularCharDFADefinition<TokenType>(new CharAlphabet()); + BuildDFA(jsonStringExpression, m_jsonDFA, m_jsonDFA.InputAlphabet); } - public CDFADefinition JsonDFA { + public RegularCharDFADefinition<TokenType> JsonDFA { get { return m_jsonDFA; } } - public CDFADefinition JsonStringDFA { + public RegularDFADefinition<char,TokenType> JsonStringDFA { get { return m_stringDFA; } } + + Token<TokenType> SymbolRangeToken(char start, char stop) { + return SymbolToken(Enumerable.Range(start,stop - start).Cast<char>()); + } + } }
--- a/Implab/Formats/JSON/JSONParser.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Formats/JSON/JSONParser.cs Mon Feb 29 02:02:17 2016 +0300 @@ -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 { /// <summary> /// internal /// </summary> @@ -28,53 +31,65 @@ /// } // Level = 0 /// </code> /// </remarks> - public class JSONParser : DFAutomaton<JSONParserContext>, IDisposable { + public class JSONParser : Disposable { enum MemberContext { MemberName, MemberValue } + struct ParserContext { + DFAStateDescriptior<object> + } + static readonly EnumAlphabet<JsonTokenType> _alphabet = EnumAlphabet<JsonTokenType>.FullAlphabet; - static readonly DFAStateDescriptior[] _jsonDFA; - static readonly DFAStateDescriptior[] _objectDFA; - static readonly DFAStateDescriptior[] _arrayDFA; + static readonly DFAStateDescriptior<object>[] _jsonDFA; + static readonly int _jsonDFAInitialState; + static readonly DFAStateDescriptior<object>[] _objectDFA; + static readonly int _objectDFAInitialState; + static readonly DFAStateDescriptior<object>[] _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<JsonTokenType> BuildDFA(Token expr) { - var builder = new DFABuilder(); - var dfa = new EDFADefinition<JsonTokenType>(_alphabet); + static Token<object> Token(params JsonTokenType[] input) { + return Token<object>.New(input.Select(t => _alphabet.Translate(t)).ToArray()); + } + + static RegularDFADefinition<JsonTokenType,object> CreateDFA(Token<object> expr) { + var builder = new RegularDFABuilder<object>(); + var dfa = new RegularDFADefinition<JsonTokenType,object>(_alphabet); + expr.Accept(builder); builder.BuildDFA(dfa); @@ -243,25 +258,13 @@ } } - protected virtual void Dispose(bool disposing) { + protected override void Dispose(bool disposing) { if (disposing) { m_scanner.Dispose(); } } /// <summary> - /// Освобождает парсер и связанный с ним сканнер. - /// </summary> - public void Dispose() { - Dispose(true); - GC.SuppressFinalize(this); - } - - ~JSONParser() { - Dispose(false); - } - - /// <summary> /// Переходит в конец текущего объекта. /// </summary> public void SeekElementEnd() {
--- a/Implab/Formats/JSON/JSONScanner.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Formats/JSON/JSONScanner.cs Mon Feb 29 02:02:17 2016 +0300 @@ -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 { /// <summary> /// Сканнер (лексер), разбивающий поток символов на токены JSON. /// </summary> - public class JSONScanner : Scanner { + public class JSONScanner : Scanner<object> { char[] m_stringBuffer; - DFAStateDescriptior[] m_stringDFA; + DFAStateDescriptior<>[] m_stringDFA; int[] m_stringAlphabet; /// <summary> /// Создает новый экземпляр сканнера /// </summary> 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();
--- a/Implab/Formats/JSON/JsonTokenType.cs Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Formats/JSON/JsonTokenType.cs Mon Feb 29 02:02:17 2016 +0300 @@ -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 { /// <summary> /// Тип токенов, возвращаемых <see cref="JSONScanner"/>. /// </summary>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Implab/Formats/RegularCharDFADefinition.cs Mon Feb 29 02:02:17 2016 +0300 @@ -0,0 +1,17 @@ +using System; +using Implab.Automaton.RegularExpressions; + +namespace Implab.Formats { + public class RegularCharDFADefinition<TTag> : RegularDFADefinition<char,TTag> { + readonly CharAlphabet m_alphabet; + + public RegularCharDFADefinition(CharAlphabet alphabet) : base(alphabet) { + m_alphabet = alphabet; + } + + public new CharAlphabet InputAlphabet { + get { return m_alphabet; } + } + } +} +
--- a/Implab/Implab.csproj Thu Feb 25 02:11:13 2016 +0300 +++ b/Implab/Implab.csproj Mon Feb 29 02:02:17 2016 +0300 @@ -152,7 +152,6 @@ <Compile Include="Components\RunnableComponent.cs" /> <Compile Include="Components\IFactory.cs" /> <Compile Include="Automaton\DFAStateDescriptor.cs" /> - <Compile Include="Automaton\DFAutomaton.cs" /> <Compile Include="Automaton\EnumAlphabet.cs" /> <Compile Include="Automaton\IAlphabet.cs" /> <Compile Include="Automaton\ParserException.cs" /> @@ -185,11 +184,12 @@ <Compile Include="Automaton\MapAlphabet.cs" /> <Compile Include="Automaton\DummyAlphabet.cs" /> <Compile Include="Automaton\DFATransitionTable.cs" /> - <Compile Include="Automaton\IDFATransitionTableBuilder.cs" /> - <Compile Include="Automaton\IDFATransitionTable.cs" /> <Compile Include="Automaton\RegularExpressions\RegularDFADefinition.cs" /> <Compile Include="Formats\CharAlphabet.cs" /> <Compile Include="Formats\ByteAlphabet.cs" /> + <Compile Include="Formats\RegularCharDFADefinition.cs" /> + <Compile Include="Automaton\IDFATable.cs" /> + <Compile Include="Automaton\IDFATableBuilder.cs" /> </ItemGroup> <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" /> <ItemGroup />