public void Iterator_Advance_Test() { var input = new List <int> { 0, 1, 2, 3 }; var mi = new MemoizedInput <int>(input); var it = mi.Begin; Assert.AreNotEqual(it, mi.End); Assert.AreEqual(it.Current, input[0]); Assert.AreEqual(mi.At(3), mi.End); Assert.AreEqual(it.Next().Current, input[1]); Assert.AreEqual(it.Next().Next().Current, input[2]); Assert.AreEqual(it.Next().Next().Next().Current, input[3]); Assert.AreEqual(it.Next().Next().Next().Next(), mi.End); var it2 = it; it2 = it2.Next().Next(); Assert.AreNotEqual(it, it2); Assert.AreEqual(it, mi.Begin); Assert.AreEqual(mi.At(2), it2); }
public void Iterator_Comparison_Test() { var input = new List <int> { 0, 1, 2, 3 }; var mi = new MemoizedInput <int>(input); var it = mi.Begin; Assert.AreEqual(it.Next().Next().Next().Next(), mi.End); Assert.IsTrue(mi.Begin < mi.End); Assert.IsTrue(mi.Begin <= mi.End); Assert.IsTrue(mi.End > mi.Begin); Assert.IsTrue(mi.End >= mi.Begin); Assert.IsTrue(mi.At(0) >= mi.Begin); Assert.IsTrue(mi.At(0) <= mi.Begin); Assert.IsTrue(mi.At(0) == mi.Begin); it = it.Next(); Assert.IsTrue(it > mi.Begin); Assert.IsTrue(it >= mi.Begin); Assert.IsTrue(it.Next() >= it); Assert.IsTrue(mi.End > it); Assert.IsTrue(mi.Begin < it); }
public ParseState(DfaState <TSymbol> state, int transitionIndex, MemoizedInput <ParseLeaf <TSymbol> > .Iterator iterator, IEnumerator <ItParseResult <TSymbol> > nextPossibleResult = null) { State = state; TransitionIndex = transitionIndex; Iterator = iterator; NextPossibleResult = nextPossibleResult; }
// 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)); }
public void Empty_Input_Test() { var input = new List <int>(); var mi = new MemoizedInput <int>(input); var it_0 = mi.Begin; Assert.AreEqual(it_0, mi.End); Assert.AreEqual(it_0.Next(), mi.End); Assert.AreEqual(it_0.Next().Next(), mi.End); Assert.AreEqual(mi.At(10), mi.End); Assert.AreEqual(mi.At(0), mi.End); Assert.AreEqual(mi.At(-1), mi.End); }
// 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); } }
private ItParseResult <TSymbol> ReturnError(TSymbol term, IList <IParseTree <TSymbol> > children, MemoizedInput <ParseLeaf <TSymbol> > .Iterator input, MemoizedInput <ParseLeaf <TSymbol> > .Iterator currentIt) { return(new ItError <TSymbol>(currentIt, term)); }
public ItError(MemoizedInput <ParseLeaf <TSymbol> > .Iterator iterator, TSymbol symbol) { Iterator = iterator; Symbol = symbol; }
public ItOK(IParseTree <TSymbol> tree, MemoizedInput <ParseLeaf <TSymbol> > .Iterator iterator) { Tree = tree; Iterator = iterator; }