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;
        }
Beispiel #2
0
        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();
        }
Beispiel #3
0
 public ParseTree(ParseTreeNode root)
 {
     this.root = root;
 }
Beispiel #4
0
 public ParseTreeNode(ParseTreeNode parent, Token token)
 {
     this.Parent = parent;
     this.token = token;
 }
Beispiel #5
0
 public ParseTreeNode(ParseTreeNode parent, NonTerminal nonTerminal)
 {
     this.Parent = parent;
     this.nonTerminal = nonTerminal;
 }
Beispiel #6
0
 public ParseTreeNode(ParseTreeNode parent, Token token)
 {
     this.Parent = parent;
     this.token  = token;
 }
Beispiel #7
0
 public ParseTreeNode(ParseTreeNode parent, NonTerminal nonTerminal)
 {
     this.Parent      = parent;
     this.nonTerminal = nonTerminal;
 }