// returns either a list of successfull parsed results or a singleton list with failure private IEnumerable <ItParseResult <TSymbol> > ParseTerm(TSymbol term, MemoizedInput <ParseLeaf <TSymbol> > word, MemoizedInput <ParseLeaf <TSymbol> > .Iterator iterator) { var dfa = _grammar.Automatons[term]; // stack for backtracking - <position in word, current state of appropriate DFA> var st = new Stack <ParseState>(); var children = new Stack <IParseTree <TSymbol> >(); bool accepted = false; var eof = ParserUtils <TSymbol> .GetEOF(); ItError <TSymbol> furthest = null; st.Push(new ParseState(dfa.Start, 0, iterator)); while (st.Any()) { var parseState = st.Peek(); var node = parseState.State; var it = parseState.Iterator; TSymbol currentSymbol = (it != word.End) ? it.Current.Symbol : eof; if (node.Accepting > 0 && (currentSymbol.Equals(eof) || _grammar.Follow[term].Contains(currentSymbol))) { accepted = true; var parsedChildren = children.ToList(); parsedChildren.Reverse(); var parsedTree = new ParseBranch <TSymbol>( iterator != word.End ? GetFragmentRange( iterator.Current.Fragment, (children.Any() ? children.Peek().Fragment : iterator.Current.Fragment)) : null, term, _grammar.WhichProduction[node.Accepting], parsedChildren); yield return(new ItOK <TSymbol>(parsedTree, it)); } var trans = node.Transitions; var ind = parseState.TransitionIndex; for (; ind < trans.Count; ind++) { if (GrammarUtils <TSymbol> .IsDead(trans[ind].Value)) { continue; } if (_grammar.InFirstPlus(trans[ind].Key, currentSymbol)) { if (trans[ind].Key.IsTerminal) { children.Push(new ParseLeaf <TSymbol>(it != word.End ? it.Current.Fragment : null, currentSymbol)); // TODO It would be better to have special END fragment st.Push(new ParseState(trans[ind].Value, 0, it != word.End ? it.Next() : word.End)); break; } else { IEnumerator <ItParseResult <TSymbol> > resultIt = ParseTerm(trans[ind].Key, word, it).GetEnumerator(); resultIt.MoveNext(); if (resultIt.Current) { var res = resultIt.Current as ItOK <TSymbol>; children.Push(res.Tree); st.Push(new ParseState(trans[ind].Value, 0, res.Iterator, resultIt)); break; } else { var res = resultIt.Current as ItError <TSymbol>; if (furthest == null || res.Iterator > furthest.Iterator) { furthest = res; } } } } } parseState.TransitionIndex = ind; // could not find next parsing transition if (ind >= trans.Count) { if (furthest == null || it > furthest.Iterator) { furthest = new ItError <TSymbol>(it, term); } Backtrack(st, children); } } if (accepted) { yield break; } else { yield return(furthest ?? new ItError <TSymbol>(iterator, term)); } }
private ItParseResult <TSymbol> ParseTerm(TSymbol term, MemoizedInput <ParseLeaf <TSymbol> > word, MemoizedInput <ParseLeaf <TSymbol> > .Iterator input) { var dfa = _grammar.Automatons[term]; var children = new List <IParseTree <TSymbol> >(); var it = input; var state = dfa.Start; var eof = ParserUtils <TSymbol> .GetEOF(); var builder = new LookaheadDfaBuilder <TSymbol>(); while (true) { LookaheadDfa <TSymbol> lookeaheadDfa = builder.Build(_grammar, it.Current.Symbol /* ? */, state); var lookState = lookeaheadDfa.Start; TSymbol currentSymbol = (it != word.End) ? it.Current.Symbol : eof; if (state.Accepting > 0 && _grammar.Follow[term].Contains(currentSymbol)) { var parsedTree = new ParseBranch <TSymbol>( GetFragmentRange(input.Current.Fragment, children.Last().Fragment), term, _grammar.WhichProduction[state.Accepting], children); return(new ItOK <TSymbol>(parsedTree, it)); } var lookIt = it; while (lookState.Accepting == 0) { TSymbol lookSym = (lookIt != word.End) ? lookIt.Current.Symbol : eof; lookState = FindTransition(lookState.Transitions, lookSym); lookIt = lookIt.Next(); } var decisions = lookeaheadDfa.Decisions[lookState.Accepting]; if (decisions.Count() > 1) { throw new NotImplementedException("Backtracking not implemented"); } else if (!decisions.Any()) { return(ReturnError(term, children, input, it)); } TSymbol transSymbol = (TSymbol)decisions.ElementAt(0); if (_grammar.IsTerminal(transSymbol)) { children.Add(new ParseLeaf <TSymbol>(it.Current.Fragment, currentSymbol)); it = it.Next(); } else { var result = ParseTerm(transSymbol, word, it); if (!result) { return(ReturnError(term, children, input, it)); } var okRes = result as ItOK <TSymbol>; children.Add(okRes.Tree); it = okRes.Iterator; } state = FindTransition(state.Transitions, transSymbol); } }