private ParseTreeNode Parse(IEnumerator<Token> lexer, NonTerminal current, ParseTreeNode parent) { Production? prod = predictiveParseTable[current][lexer.Current.Terminal]; if (!prod.HasValue) { if (current.IsNullable) { var n = new ParseTreeNode(parent, current); var c = new ParseTreeNode(n, new Token(new Terminal(""), "", lexer.Current.Line, lexer.Current.Column)); return n; } else throw new ParseException("Unable to match " + lexer.Current + " at line " + lexer.Current.Line + " column " + lexer.Current.Column); } ParseTreeNode node = new ParseTreeNode(parent, current); List<ParseTreeNode> nodes = new List<ParseTreeNode>(); for (int i = 0; i < prod.Value.Body.Length; i++) { var term = prod.Value.Body[i]; if (term is Terminal) { string match; (term as Terminal).Match(lexer.Current.Value, 0, out match); nodes.Add(new ParseTreeNode(node, lexer.Current)); if (!lexer.MoveNext()) for (int j = i + 1; j < prod.Value.Body.Length; j++) if (!prod.Value.Body[j].IsNullable) throw new ParseException("unexpected EOF"); } else if (term is NonTerminal) { nodes.Add(Parse(lexer, term as NonTerminal, node)); } else throw new Exception("wtf?"); } return node; }
protected override ParseTreeNode Parse(Lexer lexer, NonTerminal root) { IEnumerator<Token> tokens = lexer.GetEnumerator(); var eof = !tokens.MoveNext(); if (eof) { if (root.Rules.Any(r => r.IsNullable())) return new ParseTreeNode(null, new Token(new Terminal(""), "", 0, 0)); else throw new ParseException("Empty string not matched by grammar"); } Stack<ParseState> states = new Stack<ParseState>(); states.Push(MakeStateState(root, Grammar)); ParserAction action = ParserAction.Start; Stack<ParseTreeNode> nodes = new Stack<ParseTreeNode>(); do { Production reduceProduction; ParseState shiftState; action = Action(states.Peek(), eof ? null : tokens.Current, out reduceProduction, out shiftState); switch (action) { case ParserAction.Accept: break; case ParserAction.Error: throw new ParseException(tokens.Current.ToString()); case ParserAction.Start: default: throw new NotImplementedException(); case ParserAction.Shift: var newLeafNode = new ParseTreeNode(tokens.Current); nodes.Push(newLeafNode); states.Push(shiftState); eof = !tokens.MoveNext(); break; case ParserAction.Reduce: var newNode = new ParseTreeNode(reduceProduction.Head); var children = nodes.Take(reduceProduction.Body.Length).Reverse().Select((n, i) => new KeyValuePair<int, ParseTreeNode>(i, n)); foreach (var child in children) { child.Value.Parent = newNode; nodes.Pop(); var bnfTerm = reduceProduction.Body[child.Key]; var terminal = bnfTerm as Terminal; string match; if (terminal != null) { if (!terminal.Match(child.Value.Token.Value, 0, out match)) throw new ParseException("Unexpected crap"); } else if (!reduceProduction.Body[child.Key].Equals(child.Value.NonTerminal)) throw new ParseException("Unexpected crap"); } nodes.Push(newNode); for (int i = 0; i < reduceProduction.Body.Length; i++) states.Pop(); states.Push(Goto(states.Peek(), reduceProduction.Head)); break; } } while (action != ParserAction.Accept); if (nodes.Count != 1) throw new ParseException("o_0"); return nodes.Pop(); }
public ParseTree(ParseTreeNode root) { this.root = root; }
public ParseTreeNode(ParseTreeNode parent, Token token) { this.Parent = parent; this.token = token; }
public ParseTreeNode(ParseTreeNode parent, NonTerminal nonTerminal) { this.Parent = parent; this.nonTerminal = nonTerminal; }
public ParseTreeNode(ParseTreeNode parent, Token token) { this.Parent = parent; this.token = token; }
public ParseTreeNode(ParseTreeNode parent, NonTerminal nonTerminal) { this.Parent = parent; this.nonTerminal = nonTerminal; }