示例#1
0
        /// <summary>
        /// Checks the static semantic constraints of a BinOpNode.
        /// </summary>
        ///
        /// <returns>An ISemanticCheckValue.</returns>
        /// <param name="node">Node.</param>
        public ISemanticCheckValue VisitDeclarationNode(DeclarationNode node)
        {
            // check that the id property is ok
            IProperty property = getVariableProperty(node);

            if (property == voidProperty)
            {
                return(voidProperty);
            }

            VariableIdNode idNode = node.IDNode;

            // if the property is declared already, it's an error
            if (property.Declared)
            {
                analyzer.notifyError(new DeclarationError(idNode));
            }
            else
            {
                // if it wasn't declared, now it is.
                property.Declared = true;
                // check the AssignNode
                node.AssignNode.Accept(this);
            }

            return(voidProperty);
        }
示例#2
0
        /// <summary>
        /// Parses a for-loop block.
        /// </summary>
        /// <returns>The next token.</returns>
        /// <param name="token">Token.</param>
        /// <param name="statementsNode">Statements node.</param>
        private Token ParseForLoop(Token token, StatementsNode statementsNode)
        {
            // first we prepare the ForLoopNode
            VariableIdNode idNode  = nodeBuilder.CreateIdNode();
            ForLoopNode    forLoop = nodeBuilder.CreateForLoopNode(idNode, statementsNode, token);
            Token          next    = null;

            try {
                // then we try to parse the control variables that handle the accumulation and
                // condition checking every time at the beginning of every loop
                next = ParseForLoopControl(forLoop, token);
            } catch (UnexpectedTokenException ex) {
                // fastforward to a safe spot
                if (ex.Token.Type == TokenType.END_OF_BLOCK)
                {
                    return(FastForwardToStatementEnd(ex));
                }
                notifyError(new SyntaxError(ex.Token, ex.ExpectedType, ex.ExpectationSet));
                next = FastForwardTo(ParserConstants.BLOCK_DEF_FASTFORWARD_TO, ex.Token);
            }

            try {
                // now we parse the statements that are executed during each loop
                next = ParseForLoopStatements(forLoop, next);
            } catch (UnexpectedTokenException ex) {
                return(FastForwardToStatementEnd(ex));
            }

            // finally, parse the loop finalization
            return(ParseForLoopEndBlock(forLoop, next));
        }
示例#3
0
        /// <summary>
        /// Parses a variable's type into a VariableIdNode and adds the variable to the symbol table.
        /// </summary>
        /// <returns>The next token.</returns>
        /// <param name="token">Token.</param>
        /// <param name="idNode">Identifier node.</param>
        private Token ParseType(Token token, VariableIdNode idNode)
        {
            // In case the symbol table already contains the variable, we don't try ro add it twice.
            // This would of course be an error since it means the declaration for this variable
            // has already been made earlier, but this will be handled during the semantic analysis.
            if (!symbolTable.ContainsKey(idNode.ID))
            {
                switch (token.Type)
                {
                case TokenType.INT_VAR:
                    // set the id node's type
                    idNode.VariableType = TokenType.INT_VAL;
                    // add the id to the symbol table, with its value set to default value
                    symbolTable.Add(idNode.ID, (new IntegerProperty(SemanticAnalysisConstants.DEFAULT_INTEGER_VALUE)));
                    break;

                case TokenType.STR_VAR:
                    idNode.VariableType = TokenType.STR_VAL;
                    symbolTable.Add(idNode.ID, new StringProperty(SemanticAnalysisConstants.DEFAULT_STRING_VALUE));
                    break;

                case TokenType.BOOL_VAR:
                    idNode.VariableType = TokenType.BOOL_VAL;
                    symbolTable.Add(idNode.ID, new BooleanProperty(SemanticAnalysisConstants.DEFAULT_BOOL_VALUE));
                    break;

                default:
                    throw new UnexpectedTokenException(token, TokenType.UNDEFINED, ParserConstants.EXPECTATION_SET_DECLARATION_TYPE);
                }
            }

            return(scanner.getNextToken(token));
        }
示例#4
0
        public ForLoopNode(VariableIdNode idNode, Dictionary <string, IProperty> symbolTable, Token token)
        {
            this.idNode = idNode;
            this.token  = token;

            this.indexAccumulator = createIndexAccumulator(idNode, symbolTable, token);
        }
示例#5
0
        /// <summary>
        /// Checks the static semantic constraints of an AssignNode.
        /// </summary>
        /// <returns>An ISemanticCheckValue.</returns>
        /// <param name="node">Node.</param>
        public ISemanticCheckValue VisitAssignNode(AssignNode node)
        {
            // Check that the id property in this AssignNode is ok.
            IProperty property = getVariableProperty(node);

            // if the property was voidProperty, return at this point,
            // an error has been reported already
            if (property == voidProperty)
            {
                return(voidProperty);
            }

            VariableIdNode idNode = node.IDNode;

            // check that the id variable is declared
            checkPropertyDeclared(idNode, property, true);

            // check that the id property we should be assigning to is not constant
            // at this point of its lifecycle (i.e. not a current block's control variable)
            if (property.Constant)
            {
                analyzer.notifyError(new IllegalAssignmentError(node));
            }

            // evaluate the type of this property
            IProperty evaluated = node.Accept(this.typeChecker).asProperty();

            // check the type of the expression in the assign node matches the one in the symbol table
            if (!checkPropertyType(property, evaluated.GetTokenType()))
            {
                analyzer.notifyError(new IllegalTypeError(idNode));
            }

            return(voidProperty);
        }
示例#6
0
        /// <summary>
        /// Checks the static semantic constraints of a ForLoopNode.
        /// </summary>
        /// <returns>An ISemanticCheckValue.</returns>
        /// <param name="node">Node.</param>
        public ISemanticCheckValue VisitForLoopNode(ForLoopNode node)
        {
            // check that the id property is ok
            IProperty property = getVariableProperty(node);

            if (property == voidProperty)
            {
                return(voidProperty);
            }

            VariableIdNode controlVariable = node.IDNode;

            // check that the control variable is declared
            checkPropertyDeclared(node, property, true);

            // check that the control variable's type is integer
            if (property.GetTokenType() != TokenType.INT_VAL)
            {
                analyzer.notifyError(new IllegalTypeError(controlVariable));
            }

            // set the control variable as static so any attempts to assign new value
            // to it inside the loop reports an error
            analyzer.SymbolicTable [controlVariable.ID].Constant = true;

            IExpressionNode max = node.MaxValue;

            // check that the expression that defines the maximum value of the control variable
            // exists and evaluates to an integer
            if (max == null)
            {
                analyzer.notifyError(new NullPointerError(node));
            }
            else
            {
                IProperty maxProperty = max.Accept(this.typeChecker).asProperty();

                if (!checkPropertyType(maxProperty, TokenType.INT_VAL))
                {
                    analyzer.notifyError(new IllegalTypeError(max));
                }
            }

            // check that the assingment that sets the control variables initial value
            // evaluates to an integer
            IProperty rangeFromProperty = node.RangeFrom.Accept(this.typeChecker).asProperty();

            if (!checkPropertyType(rangeFromProperty, TokenType.INT_VAL))
            {
                analyzer.notifyError(new IllegalTypeError(node.RangeFrom));
            }

            // check the statements of this for loop
            node.Statements.Accept(this);

            // the control variable needs not to ba constant any more
            analyzer.SymbolicTable [controlVariable.ID].Constant = false;

            return(voidProperty);
        }
示例#7
0
        public IOReadNode CreateIOReadNode(VariableIdNode idNode, StatementsNode statementsNode, Token t)
        {
            IOReadNode ioReadNode = new IOReadNode(idNode, symbolTable, t);

            statementsNode.Statement = ioReadNode;

            return(ioReadNode);
        }
示例#8
0
        public ForLoopNode CreateForLoopNode(VariableIdNode idNode, StatementsNode statementsNode, Token t)
        {
            ForLoopNode node = new ForLoopNode(idNode, symbolTable, t);

            statementsNode.Statement = node;

            return(node);
        }
示例#9
0
        public AssignNode CreateAssignNode(VariableIdNode idNode, StatementsNode statementsNode, Token t)
        {
            AssignNode assignNode = new AssignNode(idNode, symbolTable, t);

            statementsNode.Statement = assignNode;

            return(assignNode);
        }
示例#10
0
 public AssignNode CreateAssignNode(VariableIdNode idNode, Token t)
 {
     if (idNode.Token == null)
     {
         idNode.Token = t;
     }
     return(new AssignNode(idNode, symbolTable, t));
 }
示例#11
0
        public IExpressionNode CreateIdNode(Token t, IExpressionContainer parent)
        {
            VariableIdNode node = new VariableIdNode(t.Value, symbolTable, t);

            parent.AddExpression(node);

            return(node);
        }
示例#12
0
        public DeclarationNode CreateDeclarationNode(VariableIdNode idNode, StatementsNode statementsNode, Token t)
        {
            DeclarationNode declarationNode = new DeclarationNode(idNode, symbolTable, t);

            declarationNode.AssignNode = CreateAssignNode(idNode, t);
            statementsNode.Statement   = declarationNode;

            return(declarationNode);
        }
示例#13
0
        /// <summary>
        /// Visits the assign node.
        /// </summary>
        /// <returns>An ISemanticCheckValue.</returns>
        /// <param name="node">Node.</param>
        public ISemanticCheckValue VisitAssignNode(AssignNode node)
        {
            // assign the idNode's value to the one in the expression node
            VariableIdNode idNode      = node.IDNode;
            IProperty      assignValue = node.ExprNode.Accept(this).asProperty();

            symbolTable [idNode.ID] = assignValue;

            return(voidProperty);
        }
示例#14
0
 /// <summary>
 /// Parses a read statement into an IOReadNode.
 /// </summary>
 /// <returns>The next token</returns>
 /// <param name="token">Token.</param>
 /// <param name="statementsNode">A StatementsNode.</param>
 private Token ParseRead(Token token, StatementsNode statementsNode)
 {
     try {
         VariableIdNode varId = nodeBuilder.CreateIdNode();
         // create the IOReadNode and affiliate it with the statementsNode
         nodeBuilder.CreateIOReadNode(varId, statementsNode, token);
         // parses the variable id that the read operation's value is saved to
         return(ParseVarId(scanner.getNextToken(token), varId));
     } catch (UnexpectedTokenException ex) {
         return(FastForwardToStatementEnd(ex));
     }
 }
示例#15
0
        private AssignNode createIndexAccumulator(VariableIdNode idNode, Dictionary <string, IProperty> symbolTable, Token token)
        {
            AssignNode accumulator = new AssignNode(idNode, symbolTable, token);

            BinOpNode accumulationOperation = new BinOpNode(token);

            accumulationOperation.Operation = TokenType.BINARY_OP_ADD;
            accumulationOperation.AddExpression(idNode);
            accumulationOperation.AddExpression(new IntValueNode(1, token));

            accumulator.ExprNode = accumulationOperation;

            return(accumulator);
        }
示例#16
0
        /// <summary>
        /// Parses a variable id into a VariableIdNode
        /// </summary>
        /// <returns>The next token.</returns>
        /// <param name="token">Token.</param>
        /// <param name="idNode">An IdentifierNode.</param>
        private Token ParseVarId(Token token, VariableIdNode idNode)
        {
            switch (token.Type)
            {
            case TokenType.ID:
                idNode.ID    = token.Value;
                idNode.Token = token;

                return(scanner.getNextToken(token));

            default:
                throw new UnexpectedTokenException(token, TokenType.ID, null);
            }
        }
示例#17
0
        /// <summary>
        /// Visits the variable identifier node.
        /// </summary>
        /// <returns>An ISemanticCheckValue.</returns>
        /// <param name="node">Node.</param>
        public ISemanticCheckValue VisitVariableIdNode(VariableIdNode node)
        {
            // The IProperty interface that all the different Property classes
            // implement implements itself the ISemanticValue interface and can
            // returned themselves.
            // Primarily, return the property found in the symbolic table
            if (analyzer.SymbolicTable.ContainsKey(node.ID))
            {
                return(analyzer.SymbolicTable[node.ID]);
            }

            // otherwise, return an error property
            analyzer.notifyError(new UninitializedVariableError(node));
            return(new ErrorProperty());
        }
示例#18
0
        /// <summary>
        /// Parses an assign statement.
        /// </summary>
        /// <returns>The next token.</returns>
        /// <param name="token">Token.</param>
        /// <param name="statementsNode">Statements node.</param>
        private Token ParseVariableAssign(Token token, StatementsNode statementsNode)
        {
            try {
                VariableIdNode idNode = nodeBuilder.CreateIdNode();
                // parse the target id
                Token next = ParseVarId(token, idNode);

                match(next, TokenType.ASSIGN);
                AssignNode assignNode = nodeBuilder.CreateAssignNode(idNode, statementsNode, token);

                // parses the expression of the assignment
                return(ParseExpression(scanner.getNextToken(next), assignNode));
            } catch (UnexpectedTokenException ex) {
                return(FastForwardToStatementEnd(ex));
            }
        }
示例#19
0
        /// <summary>
        /// Parses for-loop control block.
        /// </summary>
        /// <returns>The next token.</returns>
        /// <param name="forLoop">ForLoopNode.</param>
        /// <param name="token">Token.</param>
        private Token ParseForLoopControl(ForLoopNode forLoop, Token token)
        {
            VariableIdNode idNode = forLoop.IDNode;
            // first, parse the id that holds the accumulator value
            Token next = ParseVarId(scanner.getNextToken(token), idNode);

            match(next, TokenType.RANGE_FROM);
            // second, parse the start index as an assignment for the accumulator id
            forLoop.RangeFrom = nodeBuilder.CreateAssignNode(idNode, next);
            next = ParseExpression(scanner.getNextToken(next), forLoop.RangeFrom);

            match(next, TokenType.RANGE_UPTO);
            // third, parse the maximum value of the index
            next = ParseExpression(scanner.getNextToken(next), forLoop);

            match(next, TokenType.START_BLOCK);
            return(next);
        }
示例#20
0
        /// <summary>
        /// Visits for loop node.
        /// </summary>
        /// <returns>An ISemanticCheckValue.</returns>
        /// <param name="node">Node.</param>
        public ISemanticCheckValue VisitForLoopNode(ForLoopNode node)
        {
            // evaluate the maximum value of the loop's control id
            int max = node.MaxValue.Accept(this).asProperty().asInteger();

            // set the control variable's value to the start index
            node.RangeFrom.Accept(this);
            VariableIdNode idNode = node.IDNode;

            // while the max index value is not reached
            while (idNode.Accept(this).asProperty().asInteger() <= max)
            {
                // execute the statements
                node.Statements.Accept(this);
                // call for the accumulator to accumulate the control variable's value
                node.Accumulator.Accept(this);
            }

            return(voidProperty);
        }
示例#21
0
        /// <summary>
        /// Visits the variable identifier node.
        /// </summary>
        /// <returns>An ISemanticCheckValue.</returns>
        /// <param name="node">Node.</param>
        public ISemanticCheckValue VisitVariableIdNode(VariableIdNode node)
        {
            // return a copy of the variable's current value in the symbol table
            IProperty idProperty = symbolTable [node.ID];

            switch (idProperty.GetTokenType())
            {
            case TokenType.INT_VAL:
                return(new IntegerProperty(idProperty.asInteger()));

            case TokenType.STR_VAL:
                return(new StringProperty(idProperty.asString()));

            case TokenType.BOOL_VAL:
                return(new BooleanProperty(idProperty.asBoolean()));

            default:
                throw new ArgumentException();
            }
        }
示例#22
0
        /// <summary>
        /// Parses a declaration statement.
        /// </summary>
        /// <returns>The next token.</returns>
        /// <param name="token">Token.</param>
        /// <param name="statementsNode">A StatementsNode.</param>
        private Token ParseDeclaration(Token token, StatementsNode statementsNode)
        {
            // Try to parse all the pieces that a DeclarationNode needs to be evaluated.
            try {
                VariableIdNode idNode = nodeBuilder.CreateIdNode();
                // parse the target id
                Token next = ParseVarId(scanner.getNextToken(token), idNode);

                match(next, TokenType.SET_TYPE);
                // parse the id's type
                next = ParseType(scanner.getNextToken(next), idNode);

                // create the actual DeclarationNode
                DeclarationNode declarationNode = nodeBuilder.CreateDeclarationNode(idNode, statementsNode, token);
                // parse the assign for the DeclarationNode
                return(ParseAssign(next, declarationNode.AssignNode));
            } catch (UnexpectedTokenException ex) {
                return(FastForwardToStatementEnd(ex));
            }
        }
示例#23
0
        /// <summary>
        /// Adds a new identifier to the symbol table.
        /// </summary>
        /// <param name="idNode">Identifier node.</param>
        private void addNewId(VariableIdNode idNode)
        {
            // add the id to the symbol table and set its value to default
            switch (idNode.VariableType)
            {
            case TokenType.INT_VAL:
                symbolTable [idNode.ID] = new IntegerProperty(SemanticAnalysisConstants.DEFAULT_INTEGER_VALUE);
                break;

            case TokenType.STR_VAL:
                symbolTable [idNode.ID] = new StringProperty(SemanticAnalysisConstants.DEFAULT_STRING_VALUE);
                break;

            case TokenType.BOOL_VAL:
                symbolTable [idNode.ID] = new BooleanProperty(SemanticAnalysisConstants.DEFAULT_BOOL_VALUE);
                break;

            default:
                throw new RuntimeException(ErrorConstants.RUNTIME_ERROR_MESSAGE, idNode.Token);
            }
        }
示例#24
0
        /// <summary>
        /// Checks the static semantic constraints of an IOReadNode.
        /// </summary>
        /// <returns>An ISemanticCheckValue.</returns>
        /// <param name="node">Node.</param>
        public ISemanticCheckValue VisitIOReadNode(IOReadNode node)
        {
            // check that the id property is ok
            IProperty property = getVariableProperty(node);

            if (property == voidProperty)
            {
                return(voidProperty);
            }

            VariableIdNode idNode = node.IDNode;

            // check that the variable we're about to read into is declared
            checkPropertyDeclared(node, property, true);

            // check that we don't try to read a boolean value
            if (checkPropertyType(property, TokenType.BOOL_VAL))
            {
                analyzer.notifyError(new IllegalTypeError(idNode));
            }

            return(voidProperty);
        }
示例#25
0
        /// <summary>
        /// A private helper method to check for an IIdentifierContainer's
        /// VariableIdNode.
        /// </summary>
        /// <returns>An IProperty.</returns>
        /// <param name="node">Node.</param>
        private IProperty getVariableProperty(IIdentifierContainer node)
        {
            // if the variable node is not set, report an error and return
            // a VoidProperty to signal this one doesn't evaluate
            if (node.IDNode == null)
            {
                analyzer.notifyError(new UninitializedVariableError(node));
                return(voidProperty);
            }

            VariableIdNode idNode = node.IDNode;

            // check the evaluation type of the id node
            IProperty property = idNode.Accept(this.typeChecker).asProperty();

            // if it wasn't declared, report an error
            if (property.GetTokenType() == TokenType.ERROR)
            {
                analyzer.notifyError(new UninitializedVariableError(node));
                return(voidProperty);
            }

            return(property);
        }
示例#26
0
 public AssignNode(VariableIdNode idNode, Dictionary <string, IProperty> symbolTable, Token token)
 {
     this.idNode   = idNode;
     this.exprNode = null;
     this.token    = token;
 }
示例#27
0
 public AssignNode(VariableIdNode idNode, Dictionary <string, IProperty> symbolTable)
     : this(idNode, symbolTable, null)
 {
 }
示例#28
0
 /// <summary>
 /// Visits the variable identifier node.
 /// </summary>
 /// <returns>An ISemanticCheckValue.</returns>
 /// <param name="node">Node.</param>
 public ISemanticCheckValue VisitVariableIdNode(VariableIdNode node)
 {
     // let the evaluator evaluate this node
     return(node.Accept(evaluator));
 }
示例#29
0
 /// <summary>
 /// Checks the static semantic constraints of a VariableIdNode.
 /// </summary>
 /// <returns>The variable identifier node.</returns>
 /// <param name="node">An ISemanticCheckValue.</param>
 public ISemanticCheckValue VisitVariableIdNode(VariableIdNode node)
 {
     // This is not a statement so it needs not to be actually checked here.
     // So, we pass it to the TypeCheckerVisitor instead.
     return(voidProperty);
 }
示例#30
0
 public IOReadNode(VariableIdNode idNode, Dictionary <string, IProperty> symbolTable, Token t)
 {
     this.idNode     = idNode;
     this.assignNode = new AssignNode(this.idNode, symbolTable, t);
     this.token      = t;
 }