private GrammarParser(Lexer lex, Func <char, T> mkExprinal) { lexer = lex; this.mkExprinal = mkExprinal; startvar = null; productions = new List <Grammars.Production>(); }
private GrammarParser(Lexer lex, Func <string, Automaton <T> > parseRegex) { lexer = lex; this.parseRegex = parseRegex; startvar = null; productions = new List <Grammars.Production>(); terminalMap = new Dictionary <string, GrammarSymbol[]>(); this.parsedRegexes = new Dictionary <Nonterminal, Automaton <T> >(); }
private void Parse() { bool done = false; Token cur = null; Token last = null; Grammars.Nonterminal curlhs = ExpectNT(); startvar = curlhs; ExpectArrow(); List <Grammars.GrammarSymbol> currhs = new List <Grammars.GrammarSymbol>(); while (!done) { last = cur; cur = lexer.Next(); switch (cur.t) { case TokenType.NT: currhs.Add(new Grammars.Nonterminal(cur.content)); break; case TokenType.T: currhs.Add(new Exprinal <T>(mkExprinal(cur.content[0]), cur.content)); break; case TokenType.OR: productions.Add(new Grammars.Production(curlhs, currhs.ToArray())); currhs.Clear(); break; case TokenType.ARR: if (currhs.Count < 1) { throw new ParseException(); } if (last.t != TokenType.NT) { throw new ParseException(); } // downcast :( Grammars.Nonterminal newlhs = (Grammars.Nonterminal)currhs[currhs.Count - 1]; currhs.RemoveAt(currhs.Count - 1); productions.Add(new Grammars.Production(curlhs, currhs.ToArray())); currhs.Clear(); curlhs = newlhs; break; case TokenType.EOS: productions.Add(new Grammars.Production(curlhs, currhs.ToArray())); currhs.Clear(); done = true; break; default: throw new ParseException(); } } }
private void Parse() { bool done = false; Token cur = null; Token last = null; Grammars.Nonterminal curlhs = ExpectNT(); startvar = curlhs; ExpectArrow(); List <Grammars.GrammarSymbol> currhs = new List <Grammars.GrammarSymbol>(); while (!done) { last = cur; cur = lexer.Next(); switch (cur.t) { case TokenType.NT: currhs.Add(Grammars.Nonterminal.CreateByParser(cur.content)); break; case TokenType.T: { GrammarSymbol[] symbs; if (!terminalMap.TryGetValue(cur.content, out symbs)) { var aut = parseRegex(cur.content); #region parse this terminal-regex as an automaton and compute symbs or set symbs to top nonterminal int seq_length = -1; if (aut.IsEpsilon) { symbs = new GrammarSymbol[] { }; } else if (aut.InitialStateIsSource && aut.HasSingleFinalSink && aut.MoveCount == 1) { //just a single terminal var move = aut.GetMoveFrom(aut.InitialState); symbs = new GrammarSymbol[] { new Terminal <T>(move.Label) }; } else if (aut.CheckIfSequence(out seq_length) && aut.HasSingleFinalSink && aut.IsEpsilonFree) { //collect all the elements and map them to individual terminals //inline the automaton as sequence of terminals symbs = new GrammarSymbol[seq_length]; int q = aut.InitialState; int i = 0; while (!aut.IsFinalState(q)) { var move = aut.GetMoveFrom(q); q = move.TargetState; symbs[i] = new Terminal <T>(move.Label); i += 1; } } else { //introduce new nonterminal for the automaton int id = __regexId++; var nt = Nonterminal.MkNonterminalForRegex(id); parsedRegexes[nt] = aut; symbs = new GrammarSymbol[] { nt }; } terminalMap[cur.content] = symbs; #endregion } currhs.AddRange(symbs); //--- break; } case TokenType.OR: productions.Add(new Grammars.Production(curlhs, currhs.ToArray())); currhs.Clear(); break; case TokenType.ARR: if (currhs.Count < 1) { throw new ParseException(); } if (last.t != TokenType.NT) { throw new ParseException(); } // downcast :( Grammars.Nonterminal newlhs = (Grammars.Nonterminal)currhs[currhs.Count - 1]; currhs.RemoveAt(currhs.Count - 1); productions.Add(new Grammars.Production(curlhs, currhs.ToArray())); currhs.Clear(); curlhs = newlhs; break; case TokenType.EOS: productions.Add(new Grammars.Production(curlhs, currhs.ToArray())); currhs.Clear(); done = true; break; default: throw new ParseException(); } } }