public override Node VisitBinaryExpression(BinaryExpressionContext context)
        {
            var expression = new ExpressionNode(context.Start, _operatorFactory.CreateBinaryOperator(context.binaryOperator().Start));

            expression.AddChild(Visit(context.expression(0)));
            expression.AddChild(Visit(context.expression(1)));
            return(expression);
        }
Example #2
0
        public override Node VisitUnaryExpression(UnaryExpressionContext context)
        {
            var expression = new ExpressionNode(context.Start, CreateUnaryOperator(context.unaryOperator().GetText()));

            expression.AddChild(Visit(context.expression()));
            return(expression);
        }
Example #3
0
        private void ParseExpression(Node subtree)
        {
            if (tokens.CurrentToken == TokenType.Delim)
                return;
            //shunting yard
            #region Init
            Stack<OperatorNode> opStack = new Stack<OperatorNode>();
            Stack<ExpressionNode> termStack = new Stack<ExpressionNode>();
            Stack<int> argStack = new Stack<int>();
            Func<ExpressionNode, bool> isConstantExpr = new Func<ExpressionNode,bool>(delegate (ExpressionNode e)
            {
                if(e.Children.Count !=1)
                    return false;
                ConstantNode con = e.Children[0] as ConstantNode;
                if(con != null)
                    return true;
                else
                    return false;
            });
            Action popAndMakeExpr = new Action(() =>
                {
                    ExpressionNode newExpr = new ExpressionNode(null);
                    if (opStack.Peek().GetType() == typeof(FunctionCallNode))
                    {
                        Stack<ExpressionNode> paramStack = new Stack<ExpressionNode>(); //since they pop backwards
                        //make a new function node
                        FunctionCallNode funcCall = (FunctionCallNode)opStack.Pop();
                        //whilst we have logged arguments for the current function
                        while (argStack.Peek() != 0)
                        {
                            //take each arg and pop it to the stack.
                            paramStack.Push(termStack.Pop());
                            int val  = argStack.Pop();
                            argStack.Push(--val);
                        }
                        //okay no more args
                        FunctionCallParamListNode paramList = new FunctionCallParamListNode(funcCall);
                        foreach (ExpressionNode expr in paramStack)
                            paramList.AddChild(expr);
                        newExpr.AddChild(funcCall);
                        //look up the function with the given arguments
                        funcCall.Function = FunctionTable.Lookup(funcCall.Ident, funcCall.Children[0].Children);
                        argStack.Pop();
                    }
                    else
                    {
                        ExpressionNode term2 = termStack.Pop();
                        ExpressionNode term1 = termStack.Pop();
                        OperatorNode tempOpNode = opStack.Pop();
                        if (term1.Type != term2.Type)
                        {
                            ErrorHandler.RaiseError(new Error(tokens.CurrentToken.LineNo,
                                "Cannot form expression with types: " + term1.Type + " and " + term2.Type));
                        }
                        newExpr.Type = term1.Type;
                        //code folding
                        if (isConstantExpr(term1) && isConstantExpr(term2))
                        {
                            newExpr.AddChild(OpTable.Calculate((ConstantNode)term1.Children[0], (ConstantNode)term2.Children[0],
                                tempOpNode.Op));
                        }
                        else
                        {
                            newExpr.AddChild(term1);
                            newExpr.AddChild(tempOpNode);
                            newExpr.AddChild(term2);
                        }
                    }
                    termStack.Push(newExpr);
                });
            #endregion
            //welp
            while (true)
            {
                if (tokens.CurrentToken == TokenType.Type && tokens.NextToken == TokenType.Ident)
                {
                    ErrorHandler.RaiseError(new Error(tokens.CurrentToken.LineNo, "likely a missing delimiter"));
                    break;
                }
                //Ident
                if (tokens.CurrentToken == TokenType.Ident)
                {
                    if (argStack.Count > 0 && argStack.Peek() == 0)
                    {
                        argStack.Pop();
                        argStack.Push(1);
                    }
                    //Ident(..), also known as a function call
                    if (tokens.NextToken == TokenType.LeftParen)
                    {
                        FunctionCallNode funcCall = new FunctionCallNode(null); //ew
                        OperatorNode paren = new OperatorNode(null);
                        paren.Op = TokenType.LeftParen;
                        funcCall.Ident = tokens.CurrentToken.Value;
                        opStack.Push(funcCall);
                        opStack.Push(paren);
                        argStack.Push(0);
                        tokens.Next();
                    }
                    else
                    {
                        ExpressionNode termNode = new ExpressionNode(null); //parentless for now
                        VariableNode var = new VariableNode(termNode);
                        var.Ident = tokens.CurrentToken.Value;
                        var = SymbolTable.Lookup(var.Ident);
                        termNode.Type = var.Type;
                        termStack.Push(termNode);
                    }
                    //op time
                }
                else if (tokens.CurrentToken == TokenType.StringLiteral || tokens.CurrentToken == TokenType.False
                    || tokens.CurrentToken == TokenType.True || tokens.CurrentToken == TokenType.Number)
                {
                    if (argStack.Count > 0 && argStack.Peek() == 0)
                    {
                        argStack.Pop();
                        argStack.Push(1);
                    }
                    ExpressionNode term = new ExpressionNode(null);
                    switch (tokens.CurrentToken.Type)
                    {
                        case TokenType.StringLiteral:
                            ConstantNode<string> stringNode = new ConstantNode<string>(term);
                            stringNode.Value = tokens.CurrentToken.Value;
                            term.Type = "String";
                            termStack.Push(term);
                            break;
                        case TokenType.False:
                        case TokenType.True:
                            ConstantNode<bool> boolNode = new ConstantNode<bool>(term);
                            boolNode.Value = (tokens.CurrentToken == TokenType.True ? true : false);
                            term.Type = "Bool";
                            termStack.Push(term);
                            break;
                        case TokenType.Number:
                            int val;
                            if (Int32.TryParse(tokens.CurrentToken.Value, out val))
                            {
                                ConstantNode<int> intNode = new ConstantNode<int>(term);
                                intNode.Value = val;
                                term.Type = "Int";
                                termStack.Push(term);
                            }
                            else
                            {
                                ConstantNode<double> doubleNode = new ConstantNode<double>(term);
                                doubleNode.Value = double.Parse(tokens.CurrentToken.Value);
                                term.Type = "Double";
                                termStack.Push(term);
                            }
                            break;

                    }
                }
                //operator
                else if (OpTable.ExpressionOperators.Contains(tokens.CurrentToken))
                {
                    OperatorNode opNode = new OperatorNode(null);
                    opNode.Op = tokens.CurrentToken.Type;
                    while (opStack.Count != 0 && OpTable.Precedence(opStack.Peek().Op)
                        >= OpTable.Precedence(opNode.Op))
                    {
                        popAndMakeExpr();
                    }
                    opStack.Push(opNode);
                }
                //right paren
                else if (tokens.CurrentToken == TokenType.RightParen)
                {
                    while (opStack.Peek().Op != TokenType.LeftParen && opStack.Count != 0)
                    {
                        popAndMakeExpr();
                    }

                    if (opStack.Count == 0)
                        ErrorHandler.RaiseError(new Error(tokens.CurrentToken.LineNo, "mismatched brackets"));
                    opStack.Pop();
                    if (opStack.Peek().GetType() == typeof(FunctionCallNode)) //function call
                    {
                        popAndMakeExpr();
                    }
                }
                //left paren
                else if (tokens.CurrentToken == TokenType.LeftParen)
                {
                    OperatorNode node = new OperatorNode(null);
                    node.Op = TokenType.LeftParen;
                    opStack.Push(node);
                }
                else if (tokens.CurrentToken == TokenType.Comma)
                {
                    if (argStack.Count == 0)
                    {
                        ErrorHandler.RaiseError(new Error(tokens.CurrentToken.LineNo,
                            "found a comma outside of a function"));
                    }
                    while (opStack.Peek().Op != TokenType.LeftParen && opStack.Count != 0)
                    {
                        popAndMakeExpr();
                    }

                    if (opStack.Count == 0)
                        ErrorHandler.RaiseError(new Error(tokens.CurrentToken.LineNo, "mismatched brackets"));
                    //opStack.Pop();
                    int args = argStack.Pop();
                    argStack.Push(++args);
                }
                else if (tokens.CurrentToken == TokenType.Delim)
                {
                    tokens.Next();
                    break;
                }
                //delim, colon, error, etc
                else
                {
                    ErrorHandler.RaiseError(new UnexpectedTokenError(tokens.CurrentToken,
                        "part of an expression or a delim", tokens.CurrentToken.LineNo));
                }
                tokens.Next();
            }

            //clean up
            while (termStack.Count > 1 && opStack.Count > 0 && opStack.Peek().Op != TokenType.LeftParen)
            {
                if (opStack.Count == 0)
                {
                    ErrorHandler.RaiseError(new Error(tokens.CurrentToken.LineNo, "Not enough operators, or missing a delim."));
                    break;
                }
                popAndMakeExpr();
            }
            if(opStack.Count > 0 && opStack.Peek().Op == TokenType.LeftParen)
            {
                ErrorHandler.RaiseError(new Error(tokens.CurrentToken.LineNo, "bracket problems, or too many ops"));
            }
            string type = ((TypedNode)termStack.Peek().Children[0]).Type;
            termStack.Peek().Type = type;
            subtree.AddChild(termStack.Pop());
            //okay we hit a delim
            return;
        }