private Expression ParseTerm() { var left = ParseSimpleTerm(); if (left == null) { //exception unexpected something return(null); } while (true) { var operatorToken = PeekToken(); if (operatorToken == null || !MultiplyingOperators.Contains(operatorToken.Type)) { break; } NextToken(); var right = ParseSimpleTerm(); left = new MultiplyingOperator(operatorToken, left, right); } return(left); }
public AstPrinterNode Visit(MultiplyingOperator node) { var printer = new AstPrinterNode(node.ToString()); printer.AddChild(node.Left.Accept(this)); printer.AddChild(node.Right.Accept(this)); return(printer); }
public bool Visit(MultiplyingOperator node) { if (node.SymType != null) { return(true); } node.Left.Accept(this); node.Right.Accept(this); // we can use multiplication operators only with integer ('div', 'mod', 'shr', 'shl') and float ('*', '/') // and boolean ('and') if (!(node.Left.SymType.Equals(SymbolStack.SymBool) && node.Right.SymType.Equals(SymbolStack.SymBool) || (node.Left.SymType.Equals(SymbolStack.SymInt) || node.Left.SymType.Equals(SymbolStack.SymFloat)) && (node.Right.SymType.Equals(SymbolStack.SymInt) || node.Right.SymType.Equals(SymbolStack.SymFloat)))) { throw new Exception(string.Format("({0}, {1}) semantic error: incompatible types: '{2}' {3} '{4}'", node.Token.Line, node.Token.Column, node.Left.SymType, node.Token.Value, node.Right.SymType)); } //check if operator - and and operands are boolean type //give us ability to avoid this check in every case of switch if (node.Left.SymType.Equals(SymbolStack.SymBool) && node.Right.SymType.Equals(SymbolStack.SymBool) && node.Token.Type != TokenType.And) { throw new Exception(string.Format( "({0}, {1}) semantic error: incompatible types: '{2}' {3} '{4}'", node.Token.Line, node.Token.Column, node.Left.SymType, node.Token.Value, node.Right.SymType)); } switch (node.Token.Type) { case TokenType.MulOperator: { node.SymType = node.Left.SymType.Equals(SymbolStack.SymInt) && node.Right.SymType.Equals(SymbolStack.SymInt) ? SymbolStack.SymInt : SymbolStack.SymFloat; break; } case TokenType.DivOperator: { node.SymType = SymbolStack.SymFloat; break; } case TokenType.Div: case TokenType.Mod: case TokenType.Shr: case TokenType.Shl: { if (!node.Left.SymType.Equals(SymbolStack.SymInt) || !node.Right.SymType.Equals(SymbolStack.SymInt)) { throw new Exception(string.Format( "({0}, {1}) semantic error: incompatible types: '{2}' {3} '{4}'", node.Token.Line, node.Token.Column, node.Left.SymType, node.Token.Value, node.Right.SymType)); } node.SymType = SymbolStack.SymInt; break; } case TokenType.And: { if (!node.Left.SymType.Equals(SymbolStack.SymBool) || !node.Right.SymType.Equals(SymbolStack.SymBool)) { throw new Exception(string.Format( "({0}, {1}) semantic error: incompatible types: '{2}' {3} '{4}'", node.Token.Line, node.Token.Column, node.Left.SymType, node.Token.Value, node.Right.SymType)); } node.SymType = SymbolStack.SymBool; break; } default: { throw new Exception(string.Format( "({0}, {1}) semantic error: unhandled multiplying operator '{2}'", node.Token.Line, node.Token.Column, node.Token.Value)); } } node.IsLValue = false; return(true); }