/** * Parse a term. * * @param token the initial token. * @return the root of the generated parse subtree. * @throws Exception if an error occurred. */ private ICodeNode parseTerm(Token token) throws Exception { // Parse a factor and makes its node the root node. ICodeNode rootNode = parseFactor(token); TypeSpec resultType = rootNode != null ? rootNode.getTypeSpec() : Predefined.undefinedType; token = currentToken(); TokenType tokenType = token.getType(); // Loop over multiplicative operators. while (MULT_OPS.contains(tokenType)) { TokenType operator = tokenType; // Create a new operator node and adopt the current tree as its first child. ICodeNodeType nodeType = MULT_OPS_OPS_MAP.get(operator); ICodeNode opNode = ICodeFactory.createICodeNode(nodeType); opNode.addChild(rootNode); token = nextToken(); // consume the operator // Parse another factor. // The operator node adopts the term's tree as its secomd child. ICodeNode factorNode = parseFactor(token); opNode.addChild(factorNode); TypeSpec factorType = factorNode != null ? factorNode.getTypeSpec() : Predefined.undefinedType; // The operator node becomes the new root node. rootNode = opNode; // Determine the result type. switch ((PascalTokenType) operator) { case STAR: { // Both operands integer ==> integer result. if (TypeChecker.areBothInteger(resultType, factorType)) { resultType = Predefined.integerType; } // Both real operands or one real and one integer operand // ==> real result. else if (TypeChecker.isAtLeastOneReal(resultType, factorType)) { resultType = Predefined.realType; } else { errorHandler.flag(token, INCOMPATIBLE_TYPES, this); } break; } case SLASH: { // All integer and real operand combinations // ==> real result. if (TypeChecker.areBothInteger(resultType, factorType) || TypeChecker.isAtLeastOneReal(resultType, factorType)) { resultType = Predefined.realType; } else { errorHandler.flag(token, INCOMPATIBLE_TYPES, this); } break; } case DIV: case MOD: { // Both operands integer ==> integer result. if (TypeChecker.areBothInteger(resultType, factorType)) { resultType = Predefined.integerType; } else { errorHandler.flag(token, INCOMPATIBLE_TYPES, this); } break; } case AND: { // Both operands boolean ==> boolean result. if (TypeChecker.areBothBoolean(resultType, factorType)) { resultType = Predefined.booleanType; } else { errorHandler.flag(token, INCOMPATIBLE_TYPES, this); } break; } } // The operator node becomes the new root node. rootNode.setTypeSpec(resultType); token = currentToken(); tokenType = token.getType(); } return rootNode; }
/** * Parse a simple expression. * * @param token the initial token. * @return the root of the generated parse subtree. * @throws Exception if an error occurred. */ private ICodeNode parseSimpleExpression(Token token) throws Exception { Token signToken = null; TokenType signType = null; // type of leading sign (if any) // Look for a leading + or - sign TokenType tokenType = token.getType(); if ((tokenType == PLUS) || (tokenType == MINUS)) { signType = tokenType; signToken = token; token = nextToken(); // consume the + or - } // Parse a term and make the root of its tree the root node. ICodeNode rootNode = parseTerm(token); TypeSpec resultType = rootNode != null ? rootNode.getTypeSpec() : Predefined.undefinedType; // Type check: Leading sign. if ((signType != null) && (!TypeChecker.isIntegerOrReal(resultType))) errorHandler.flag(signToken, INCOMPATIBLE_TYPES, this); // Was there a leading - sign? if (signType == MINUS) { // Create a NEGATE node and adopt the current tree as its child. // The NEGATE node becomes the new root node. ICodeNode negateNode = ICodeFactory.createICodeNode(NEGATE); negateNode.addChild(rootNode); negateNode.setTypeSpec(rootNode.getTypeSpec()); rootNode = negateNode; } token = currentToken(); tokenType = token.getType(); // Loop over additive operators. while (ADD_OPS.contains(tokenType)) { TokenType operator = tokenType; // Create a new operator node and adopt the current tree as its first child. ICodeNodeType nodeType = ADD_OPS_OPS_MAP.get(operator); ICodeNode opNode = ICodeFactory.createICodeNode(nodeType); opNode.addChild(rootNode); token = nextToken(); // consume the operator // Parse another term. // The operator node adopts the term's tree as its second child. ICodeNode termNode = parseTerm(token); opNode.addChild(termNode); TypeSpec termType = termNode != null ? termNode.getTypeSpec() : Predefined.undefinedType; // The operator node becomes the new root node. rootNode = opNode; switch ((PascalTokenType) operator) { case PLUS: case MINUS: { // Both operands integer => integer result. if (TypeChecker.areBothInteger(resultType, termType)) resultType = Predefined.integerType; // Both real operands or one real and one integer operand => real result. else if (TypeChecker.isAtLeastOneReal(resultType, termType)) resultType = Predefined.realType; else errorHandler.flag(token, INCOMPATIBLE_TYPES, this); break; } case OR: { // Both operands boolean ==> boolean result. if (TypeChecker.areBothBoolean(resultType, termType)) resultType = Predefined.booleanType; else errorHandler.flag(token, INCOMPATIBLE_TYPES, this); break; } } rootNode.setTypeSpec(resultType); token = currentToken(); tokenType = token.getType(); } return rootNode; }