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);
        }
Beispiel #2
0
        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);
        }