// At this moment return null when parsing fails public ParseResult <TSymbol> Parse(IEnumerable <ParseLeaf <TSymbol> > word) { var memoizedWord = new MemoizedInput <ParseLeaf <TSymbol> >(word); var result = ParseTerm(_grammar.Start, memoizedWord, memoizedWord.Begin).First(); // whole input has to be eaten if (result && (result as ItOK <TSymbol>).Iterator != memoizedWord.End) { result = new ItError <TSymbol>((result as ItOK <TSymbol>).Iterator, _grammar.Start); } return(ParserUtils <TSymbol> .Convert(result)); }
// 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)); } }