Пример #1
0
        /// <summary>
        /// Gets expression AST if operation is plus, minus, equal, less_than or logical_and
        /// If not, then return term
        /// </summary>
        /// <returns></returns>
        private AST Expression()
        {
            AST node = this.Term();

            while (this.currentToken.type == TokenType.PLUS || this.currentToken.type == TokenType.MINUS || this.currentToken.type == TokenType.EQUAL || this.currentToken.type == TokenType.LESS_THAN || this.currentToken.type == TokenType.LOGICAL_AND)
            {
                Token token = this.currentToken;
                if (token.type == TokenType.PLUS)
                {
                    this.ConsumeToken(TokenType.PLUS);
                }
                else if (token.type == TokenType.MINUS)
                {
                    this.ConsumeToken(TokenType.MINUS);
                }
                else if (token.type == TokenType.EQUAL)
                {
                    this.ConsumeToken(TokenType.EQUAL);
                }
                else if (token.type == TokenType.LESS_THAN)
                {
                    this.ConsumeToken(TokenType.LESS_THAN);
                }
                else if (token.type == TokenType.LOGICAL_AND)
                {
                    this.ConsumeToken(TokenType.LOGICAL_AND);
                }
                node = new BinaryOperationAST(node, token, this.Term());
            }
            return(node);
        }
Пример #2
0
        /// <summary>
        /// Returns a binary operation AST if operation is multiply or divide, if not, then return factor
        /// </summary>
        /// <returns>AST</returns>
        private AST Term()
        {
            AST node = this.Factor();

            while (this.currentToken.type == TokenType.MUL || this.currentToken.type == TokenType.DIV)
            {
                Token token = this.currentToken;
                if (token.type == TokenType.MUL)
                {
                    this.ConsumeToken(TokenType.MUL);
                }
                else if (token.type == TokenType.DIV)
                {
                    this.ConsumeToken(TokenType.DIV);
                }
                node = new BinaryOperationAST(node, token, this.Factor());
            }
            return(node);
        }
Пример #3
0
        /// <summary>
        /// Checks semantic errors of a binary operation
        /// If the types don't match, then add error
        /// </summary>
        /// <param name="ast">AST</param>
        /// <returns>Result</returns>
        private object VisitBinaryOperationAST(BinaryOperationAST ast)
        {
            object component1 = this.VisitNode(ast.left);
            object component2 = this.VisitNode(ast.right);

            if (component1 is string && component2 is string)
            {
                string c1 = component1 as string;
                string c2 = component2 as string;

                if (ast.token.type == TokenType.PLUS)
                {
                    return(c1 + c2);
                }
                else if (ast.token.type == TokenType.EQUAL)
                {
                    return(c1.Equals(c2));
                }
                else if (ast.token.type == TokenType.LESS_THAN)
                {
                    return(c1.Length < c2.Length);
                }
                else
                {
                    errors.Add(new UnsupportedOperationError(ast.token, "string"));
                }
            }
            else if (component1 is int && component2 is int)
            {
                // I have classified the division by zero as a runtime error
                // So in the semantic analysis it is ignored and reported at the runtime
                // This is to make the division of the two phases more clear
                try
                {
                    if (ast.token.type == TokenType.PLUS)
                    {
                        return((int)component1 + (int)component2);
                    }
                    else if (ast.token.type == TokenType.MINUS)
                    {
                        return((int)component1 - (int)component2);
                    }
                    else if (ast.token.type == TokenType.MUL)
                    {
                        return((int)component1 * (int)component2);
                    }
                    else if (ast.token.type == TokenType.DIV)
                    {
                        return((int)component1 / (int)component2);
                    }
                    else if (ast.token.type == TokenType.EQUAL)
                    {
                        return((int)component1 == (int)component2);
                    }
                    else if (ast.token.type == TokenType.LESS_THAN)
                    {
                        return((int)component1 < (int)component2);
                    }
                    else
                    {
                        errors.Add(new UnsupportedOperationError(ast.token, "int"));
                    }
                }
                catch (DivideByZeroException) { return(0); }
                catch (OverflowException) { return(0); }
            }
            else if (component1 is bool && component2 is bool)
            {
                if (ast.token.type == TokenType.EQUAL)
                {
                    return((bool)component1 == (bool)component2);
                }
                else if (ast.token.type == TokenType.LOGICAL_AND)
                {
                    return((bool)component1 & (bool)component2);
                }
                else if (ast.token.type == TokenType.LESS_THAN)
                {
                    if ((bool)component1 == false && (bool)component2 == true)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
                else
                {
                    errors.Add(new UnsupportedOperationError(ast.token, "bool"));
                }
            }
            else if (component1 is null || component2 is null)
            {
            }
Пример #4
0
        /// <summary>
        /// Traverses BinaryOperationAST
        /// </summary>
        /// <param name="ast"></param>
        /// <returns>BinaryOperationAST</returns>
        private object VisitBinaryOperationAST(BinaryOperationAST ast)
        {
            object component1 = this.VisitNode(ast.left);
            object component2 = this.VisitNode(ast.right);

            if (component1 is string && component2 is string)
            {
                string c1 = component1 as string;
                string c2 = component2 as string;

                if (ast.token.type == TokenType.EQUAL)
                {
                    return(c1.Equals(c2));
                }
                else if (ast.token.type == TokenType.LESS_THAN)
                {
                    return(c1.Length < c2.Length);
                }
                else
                {
                    return(c1 + c2);
                }
            }
            else if (component1 is bool && component2 is bool)
            {
                if (ast.token.type == TokenType.EQUAL)
                {
                    return((bool)component1 == (bool)component2);
                }
                else if (ast.token.type == TokenType.LOGICAL_AND)
                {
                    return((bool)component1 & (bool)component2);
                }
                else // less than
                {
                    if ((bool)component1 == false && (bool)component2 == true)
                    {
                        return(true);
                    }
                    else
                    {
                        return(false);
                    }
                }
            }
            else
            {
                try
                {
                    if (ast.token.type == TokenType.PLUS)
                    {
                        return((int)component1 + (int)component2);
                    }
                    else if (ast.token.type == TokenType.MINUS)
                    {
                        return((int)component1 - (int)component2);
                    }
                    else if (ast.token.type == TokenType.MUL)
                    {
                        return((int)component1 * (int)component2);
                    }
                    else if (ast.token.type == TokenType.EQUAL)
                    {
                        return((int)component1 == (int)component2);
                    }
                    else if (ast.token.type == TokenType.LESS_THAN)
                    {
                        return((int)component1 < (int)component2);
                    }
                    else
                    {
                        return((int)component1 / (int)component2);
                    }
                }
                catch (DivideByZeroException) { throw new RuntimeError(ast.token, "Attempted to divide by zero").Exception(); }
                catch (OverflowException) { throw new RuntimeError(ast.token, "Integer overflow").Exception(); }
            }
        }