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); }
public override Node VisitUnaryExpression(UnaryExpressionContext context) { var expression = new ExpressionNode(context.Start, CreateUnaryOperator(context.unaryOperator().GetText())); expression.AddChild(Visit(context.expression())); return(expression); }
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; }