/// <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)); }
/// <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); }
/// <summary> /// Visits for loop node. /// </summary> /// <returns>An ISemanticCheckValue.</returns> /// <param name="node">Node.</param> public ISemanticCheckValue VisitForLoopNode(ForLoopNode node) { IProperty rangeFrom = node.RangeFrom.Accept(this).asProperty(); IProperty max = node.MaxValue.Accept(this).asProperty(); bool alright = true; // check that the type is accepted as the "range from" expression // basically, chack it's integer if (!SemanticAnalysisConstants.LEGIT_OPERATIONS.ContainsKey(rangeFrom.GetTokenType()) || !SemanticAnalysisConstants.LEGIT_OPERATIONS [rangeFrom.GetTokenType()].ContainsKey(TokenType.RANGE_FROM)) { analyzer.notifyError(new IllegalTypeError(node.RangeFrom)); alright = false; } // check that the type is accepted as the "range upto" expression // basically, chack it's integer if (!SemanticAnalysisConstants.LEGIT_OPERATIONS.ContainsKey(max.GetTokenType()) || !SemanticAnalysisConstants.LEGIT_OPERATIONS [max.GetTokenType()].ContainsKey(TokenType.RANGE_UPTO)) { analyzer.notifyError(new IllegalTypeError(node.MaxValue)); alright = false; } // if both evaluations weren't alright, return an error property if (!alright) { return(new ErrorProperty()); } return(rangeFrom); }
/// <summary> /// Parses for-loop's statements. /// </summary> /// <returns>The next token.</returns> /// <param name="forLoop">ForLoopNode.</param> /// <param name="token">Token.</param> private Token ParseForLoopStatements(ForLoopNode forLoop, Token token) { StatementsNode statements = nodeBuilder.CreateStatementsNode(forLoop.Token); forLoop.Statements = statements; // parse the statement's to be executed during each loop return(ParseStatements(scanner.getNextToken(token), statements)); }
public ForLoopNode CreateForLoopNode(VariableIdNode idNode, StatementsNode statementsNode, Token t) { ForLoopNode node = new ForLoopNode(idNode, symbolTable, t); statementsNode.Statement = node; return(node); }
/// <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); }
/// <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); }
/// <summary> /// Parses for loop end block. /// </summary> /// <returns>The next token.</returns> /// <param name="forLoop">For loop.</param> /// <param name="token">Token.</param> private Token ParseForLoopEndBlock(ForLoopNode forLoop, Token token) { try { // try to match the end of block match(token, TokenType.END_OF_BLOCK); token = scanner.getNextToken(token); match(token, TokenType.FOR_LOOP); return(scanner.getNextToken(token)); } catch (UnexpectedTokenException ex) { // something went wrong, need to find the actual end of the block token = FastForwardToEndOfBlock(ex); } try { // if we didn't succeed in the first try, we now found the block's end // or the end of file if the block was never finalized match(token, TokenType.FOR_LOOP); return(scanner.getNextToken(token)); } catch (UnexpectedTokenException ex) { return(FastForwardToStatementEnd(ex)); } }
/// <summary> /// Visits for loop node. /// </summary> /// <returns>An ISemanticCheckValue.</returns> /// <param name="node">Node.</param> public ISemanticCheckValue VisitForLoopNode(ForLoopNode node) { // nothing to evaluate here, it's done from the ExecutionVisitor return(voidProperty); }