/** * 解析标识符 * * @param token * @return 对应符号表项 * @throws Exception */ private SymTabEntry parseIdentifier(Token token) throws Exception { SymTabEntry id = null; if (token.getType() == IDENTIFIER) { String name = token.getText().toLowerCase(); id = symTabStack.lookupLocal(name); // 申明必须得没有,否则重定义了 if (id == null) { id = symTabStack.enterLocal(name); id.setDefinition(definition); id.appendLineNumber(token.getLineNumber()); } else { errorHandler.flag(token, IDENTIFIER_REDEFINED, this); } token = nextToken(); } else { errorHandler.flag(token, MISSING_IDENTIFIER, this); } return id; }
/** * 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: { // 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); if (id == null) { errorHandler.flag(token, IDENTIFIER_UNDEFINED, this); id = symTabStack.enterLocal(name); } rootNode = ICodeFactory.createICodeNode(VARIABLE); rootNode.setAttribute(ID, id); id.appendLineNumber(token.getLineNumber()); token = nextToken(); // consume the identifier break; } 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 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 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); token = nextToken(); // consume the string 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. rootNode.addChild(parseFactor(token)); break; } case LEFT_PAREN: { token = nextToken(); // consume the ( // Parse an expression and make its node the root node. rootNode = parseExpression(token); // Look for the matching ) token. token = currentToken(); if (token.getType() == RIGHT_PAREN) { token = nextToken(); // consume the ) } else { errorHandler.flag(token, MISSING_RIGHT_PAREN, this); } break; } case LEFT_BRACKET: { rootNode = parseSet(token); break; } default: { errorHandler.flag(token, UNEXPECTED_TOKEN, this); break; } } return rootNode; }
/** * Parse type definitions. * * @param token the initial token. * @throws Exception if an error occurred. */ public void parse(Token token) throws Exception { token = synchronize(IDENTIFIER_SET); // Loop to parse a sequence of type definitions // separated by semicolons. while (token.getType() == IDENTIFIER) { String name = token.getText().toLowerCase(); SymTabEntry typeId = symTabStack.lookupLocal(name); // Enter the new identifier into the symbol table // but don't set how it's defined yet. if (typeId == null) { typeId = symTabStack.enterLocal(name); typeId.appendLineNumber(token.getLineNumber()); } else { errorHandler.flag(token, IDENTIFIER_REDEFINED, this); typeId = null; } token = nextToken(); // consume the identifier token // Synchronize on the = token. token = synchronize(EQUALS_SET); if (token.getType() == EQUALS) { token = nextToken(); // consume the = } else { errorHandler.flag(token, MISSING_EQUALS, this); } // Parse the type specification. TypeSpecificationParser typeSpecificationParser = new TypeSpecificationParser(this); TypeSpec type = typeSpecificationParser.parse(token); // Set identifier to be a type and set its type specificationt. if (typeId != null) { typeId.setDefinition(TYPE); } // Cross-link the type identifier and the type specification. if (type != null && typeId != null) { if (type.getIdentifier() == null) { type.setIdentifier(typeId); } typeId.setTypeSpec(type); } else { token = synchronize(FOLLOW_SET); } token = currentToken(); TokenType tokenType = token.getType(); // Look for one or more semicolons after a definition. if (tokenType == SEMICOLON) { while (token.getType() == SEMICOLON) { token = nextToken(); // consume the ; } } // If at the start of the next definition or declaration, // then missing a semicolon. else if (NEXT_START_SET.contains(tokenType)) { errorHandler.flag(token, MISSING_SEMICOLON, this); } token = synchronize(IDENTIFIER_SET); } }