private ICodeNode parseIdentifier(Token token) throws Exception { ICodeNode rootNode = null; // Look up the identifier in the symbol table stack. // Flag the identifier as undefined if it's not found. String name = token.getText().toLowerCase(); SymTabEntry id = symTabStack.lookup(name); // Undefined. if (id == null) { errorHandler.flag(token, IDENTIFIER_UNDEFINED, this); id = symTabStack.enterLocal(name); id.setDefinition(UNDEFINED); id.setTypeSpec(Predefined.undefinedType); } Definition defnCode = id.getDefinition(); switch ((DefinitionImpl) defnCode) { case CONSTANT: { Object value = id.getAttribute(CONSTANT_VALUE); TypeSpec type = id.getTypeSpec(); if (value instanceof Integer) { rootNode = ICodeFactory.createICodeNode(INTEGER_CONSTANT); rootNode.setAttribute(VALUE, value); } else if (value instanceof Float) { rootNode = ICodeFactory.createICodeNode(REAL_CONSTANT); rootNode.setAttribute(VALUE, value); } else if (value instanceof String) { rootNode = ICodeFactory.createICodeNode(STRING_CONSTANT); rootNode.setAttribute(VALUE, value); } id.appendLineNumber(token.getLineNumber()); token = nextToken(); // consume the constant identifier if (rootNode != null) { rootNode.setTypeSpec(type); } break; } case ENUMERATION_CONSTANT: { Object value = id.getAttribute(CONSTANT_VALUE); TypeSpec type = id.getTypeSpec(); rootNode = ICodeFactory.createICodeNode(INTEGER_CONSTANT); rootNode.setAttribute(VALUE, value); id.appendLineNumber(token.getLineNumber()); token = nextToken(); // consume the enum constant identifier rootNode.setTypeSpec(type); break; } case FUNCTION: { CallParser callParser = new CallParser(this); rootNode = callParser.parse(token); break; } default: { VariableParser variableParser = new VariableParser(this); rootNode = variableParser.parse(token, id); break; } } return rootNode; }
/** * Parse a factor. * * @param token the initial token. * @return the root of the generated parse subtree. * @throws Exception if an error occurred. */ private ICodeNode parseFactor(Token token) throws Exception { TokenType tokenType = token.getType(); ICodeNode rootNode = null; switch ((PascalTokenType) tokenType) { case IDENTIFIER: { return parseIdentifier(token); } case INTEGER: { // Create an INTEGER_CONSTANT node as the root node rootNode = ICodeFactory.createICodeNode(INTEGER_CONSTANT); rootNode.setAttribute(VALUE, token.getValue()); token = nextToken(); // consume the number rootNode.setTypeSpec(Predefined.integerType); break; } case REAL: { // Create an REAL_CONSTANT node as the root node. rootNode = ICodeFactory.createICodeNode(REAL_CONSTANT); rootNode.setAttribute(VALUE, token.getValue()); token = nextToken(); // consume the number rootNode.setTypeSpec(Predefined.realType); break; } case STRING: { String value = (String) token.getValue(); // Create a STRING_CONSTANT node as the root node. rootNode = ICodeFactory.createICodeNode(STRING_CONSTANT); rootNode.setAttribute(VALUE, value); TypeSpec resultType = value.length() == 1 ? Predefined.charType : TypeFactory.createStringType(value); token = nextToken(); // consume the string rootNode.setTypeSpec(resultType); break; } case NOT: { token = nextToken(); // consume the NOT // Create a NOT node as the root node. rootNode = ICodeFactory.createICodeNode(ICodeNodeTypeImpl.NOT); // Parse the factor. The NOT node adopts the factor node as its child. ICodeNode factorNode = parseFactor(token); rootNode.addChild(factorNode); // Type check: the factor must be boolean. TypeSpec factorType = factorNode != null ? factorNode.getTypeSpec() : Predefined.undefinedType; if (!TypeChecker.isBoolean(factorType)) errorHandler.flag(token, INCOMPATIBLE_TYPES, this); rootNode.setTypeSpec(Predefined.booleanType); break; } case LEFT_PAREN: { token = nextToken(); // consume the ( // Parse an expression and make its node the root node. rootNode = parseExpression(token); TypeSpec resultType = rootNode != null ? rootNode.getTypeSpec() : Predefined.undefinedType; // Look for the matching ) token. token = currentToken(); if (token.getType() == RIGHT_PAREN) token = nextToken(); // consume the ) else errorHandler.flag(token, MISSING_RIGHT_PAREN, this); rootNode.setTypeSpec(resultType); break; } default: { errorHandler.flag(token, UNEXPECTED_TOKEN, this); break; } } return rootNode; }