/// <summary> /// Loads the specified DFA automaton /// </summary> /// <param name="automaton">An automaton</param> private void LoadDFA(Automaton automaton) { dfa = new Automata.DFA(); for (int i = 0; i != automaton.StatesCount; i++) { dfa.CreateState(); } for (int i = 0; i != automaton.StatesCount; i++) { Automata.DFAState current = dfa.States[i]; AutomatonState stateData = automaton.GetState(i); // retrieve the matched terminals for (int j = 0; j != stateData.TerminalsCount; j++) { MatchedTerminal mt = stateData.GetTerminal(j); Terminal terminal = terminals[mt.Index]; current.AddItem(terminal); if (mt.Context != 0) { terminals[mt.Index].Context = mt.Context; } } // retrieve the transitions for (int j = 0; j != 256; j++) { int next = stateData.GetCachedTransition(j); char c = Convert.ToChar(j); if (next != Automaton.DEAD_STATE) { current.AddTransition(new CharSpan(c, c), dfa.States[next]); } } for (int j = 0; j != stateData.BulkTransitionsCount; j++) { AutomatonTransition transition = stateData.GetBulkTransition(j); current.AddTransition(new CharSpan(Convert.ToChar(transition.Start), Convert.ToChar(transition.End)), dfa.States[transition.Target]); } current.RepackTransitions(); } }
/// <summary> /// Generates the given state binary data /// </summary> /// <param name="writer">The output writer</param> /// <param name="state">The state to export</param> private void GenerateDataFor(BinaryWriter writer, Automata.DFAState state) { // build the transition data ushort[] cache = new ushort[256]; for (int i = 0; i != 256; i++) { cache[i] = Automaton.DEAD_STATE; } ushort cached = 0; // the number of cached transitions ushort slow = 0; // the number of non-cached transitions foreach (CharSpan span in state.Transitions) { if (span.Begin <= 255) { cached++; int end = span.End; if (end >= 256) { end = 255; slow++; } for (int i = span.Begin; i <= end; i++) { cache[i] = (ushort)state.GetChildBy(span).ID; } } else { slow++; } } // build the matched terminals data List <ushort> contextIDs = new List <ushort>(); List <ushort> matched = new List <ushort>(); foreach (Automata.FinalItem item in state.Items) { Grammars.Terminal terminal = item as Grammars.Terminal; if (!contextIDs.Contains((ushort)terminal.Context)) { // this is the first time this context is found in the current DFA state // this is the terminal with the most priority for this context contextIDs.Add((ushort)terminal.Context); matched.Add((ushort)terminals.IndexOf(terminal)); } } // write the number of matched terminals writer.Write((ushort)matched.Count); // write the total numer of transitions writer.Write((ushort)(slow + cached)); // write the number of non-cached transitions writer.Write(slow); // write the matched terminals for (int i = 0; i != matched.Count; i++) { writer.Write(contextIDs[i]); writer.Write(matched[i]); } // write the cached transitions for (int i = 0; i != 256; i++) { writer.Write(cache[i]); } // write the non-cached transitions List <CharSpan> keys = new List <CharSpan>(state.Transitions); keys.Sort(new System.Comparison <CharSpan>(CharSpan.CompareReverse)); foreach (CharSpan span in keys) { if (span.End <= 255) { break; // the rest of the transitions are in the cache } ushort begin = span.Begin; if (begin <= 255) { begin = 256; } writer.Write(begin); writer.Write(Convert.ToUInt16(span.End)); writer.Write((ushort)state.GetChildBy(span).ID); } }