Пример #1
0
        // Woops.  This is left-associative.  I wanted a right-associative tree.
        public static Expression fromString(String s, PrecedenceRule rule)
        {
            List <Token> tokens = tokenize(s);

            // dumpTokens(tokens);
            // tokens.Reverse();
            return(fromTokens(tokens, rule));
        }
Пример #2
0
        public static Expression fromTokens(List <Token> tokens, PrecedenceRule rule)
        {
            Stack <TokenOrExpression> stack = new Stack <TokenOrExpression>();

            while (true)
            {
                if (tokens.Count == 0 && stack.Count == 1 && stack.Peek()?.Expression != null)
                {
                    return(stack.Pop().Expression);
                }

                if (stack.Count == 0)
                {
                    stack.Push(new TokenOrExpression(tokens[0]));
                    tokens.RemoveAt(0);
                }
                else if (stack.Peek()?.Token is LiteralToken)
                {
                    ulong val = (stack.Pop().Token as LiteralToken).Value;
                    stack.Push(new TokenOrExpression(new Literal(val)));
                }
                else if (stack.Peek()?.Token is RparenToken)
                {
                    stack.Pop();  // Rparen
                    Expression g = new Group(stack.Pop().Expression);
                    stack.Pop();  // Lparen
                    stack.Push(new TokenOrExpression(g));
                }
                else if (stack.Peek()?.Expression != null)
                {
                    bool reduce = true;
                    if (rule == PrecedenceRule.PlusFirst)
                    {
                        int open = 0;
                        int seen = 0;
                        foreach (var t in tokens)
                        {
                            if (t is LparenToken)
                            {
                                open++;
                                continue;
                            }
                            else if (t is RparenToken)
                            {
                                if (--open > 0)
                                {
                                    continue;
                                }
                                else if (open < 0)
                                {
                                    break;
                                }
                            }

                            if (open == 0 && ++seen > 1)
                            {
                                break;
                            }

                            if (t is BinopToken)
                            {
                                BinopToken tok = t as BinopToken;
                                if (tok.Kind == BinopKind.Plus)
                                {
                                    reduce = false;
                                    break;
                                }
                            }
                        }
                    }
                    Expression e1 = stack.Pop().Expression;
                    if (reduce && stack.TryPeek(out TokenOrExpression top) && top.Token is BinopToken)
                    {
                        BinopToken binop = stack.Pop().Token as BinopToken;
                        Expression e2    = stack.Pop().Expression;
                        stack.Push(new TokenOrExpression(new Binop(e1, binop.Kind, e2)));
                    }
                    else  // Probably Lparen
                    {
                        stack.Push(new TokenOrExpression(e1));
                        stack.Push(new TokenOrExpression(tokens[0]));
                        tokens.RemoveAt(0);
                    }
                }