/** * Parse a set. * * @param token the initial token. * @return the root of the generated parse subtree. * @throws Exception if an error occurred. */ private ICodeNode parseSet(Token token) throws Exception { ICodeNode rootNode = ICodeFactory.createICodeNode(SETS); int tempInteger = 0; token = nextToken(); // consume left bracket while (token.getType() != RIGHT_BRACKET) { if (token.getType() == INTEGER) { tempInteger = (int) token.getValue(); rootNode.addChild(parseTerm(token)); token = currentToken(); } else if (token.getType() == IDENTIFIER) { ICodeNode var = parseFactor(token); rootNode.addChild(var); token = currentToken(); } if (token.getType() == COMMA) { token = nextToken(); // consume next token if (token.getType() == COMMA) { errorHandler.flag(token, EXTRA_COMMA, this); } } else if (token.getType() == RIGHT_BRACKET) { // do nothing } else if (token.getType() == SEMICOLON) { errorHandler.flag(token, MISSING_CLOSE_SQUARE_BRACKET, this); break; } else if (token.getType() == DOT_DOT) { token = nextToken(); // consume the integer. // Create a STRING_CONSTANT node as the root node. ICodeNode node = ICodeFactory.createICodeNode(SUBRANGE); // denotes the maximum value of the range. if (token.getType() != INTEGER) { errorHandler.flag(token, MISSING_MAX_VAL_SUBRANGE, this); } else { int value = (int) token.getValue(); node.setAttribute(VALUE, value); } rootNode.addChild(node); token = nextToken(); } else { errorHandler.flag(token, MISSING_COMMA, this); } } if (token.getType() != SEMICOLON) { token = nextToken(); // consume right bracket } return rootNode; }
/** * Set the current line number as a statement node attribute. * * @param node ICodeNode * @param token the initial token. */ protected void setLineNumber(ICodeNode node, Token token) { if (node != null) { node.setAttribute(LINE, token.getLineNumber()); } }
/** * 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 a set. * * @param token the initial token. * @return the root of the generated parse subtree. * @throws Exception if an error occurred. */ private ICodeNode parseSet(Token token) throws Exception { ICodeNode rootNode = ICodeFactory.createICodeNode(ICodeNodeTypeImpl.SET); HashSet<Integer> values = new HashSet<>(); rootNode.setAttribute(VALUE, new HashSet<Integer>()); boolean isFinished = false; while (token.getType() != RIGHT_BRACKET && token.getType() != ERROR && !isFinished) { ICodeNode leftNode = parseSimpleExpression(token); if (leftNode.getType() == INTEGER_CONSTANT && !values.add((Integer) leftNode.getAttribute(VALUE))) { errorHandler.flag(token, NON_UNIQUE_MEMBERS, this); } token = currentToken(); switch ((PascalTokenType) token.getType()) { case RIGHT_BRACKET: rootNode.addChild(leftNode); break; case COMMA: rootNode.addChild(leftNode); token = nextToken(); // Consume the , if (token.getType() == COMMA) { errorHandler.flag(token, EXTRA_COMMAS, this); token = nextToken(); // Consume the extra , } break; case DOT_DOT: token = nextToken(); // Consume the .. if (token.getType() == COMMA) { errorHandler.flag(token, INVALID_SUBRANGE, this); token = nextToken(); // Consume the , rootNode.addChild(leftNode); } else { ICodeNode rightNode = parseSimpleExpression(token); ICodeNode subrangeNode = ICodeFactory.createICodeNode(SUBRANGE); subrangeNode.addChild(leftNode); subrangeNode.addChild(rightNode); rootNode.addChild(subrangeNode); if (leftNode.getType() == INTEGER_CONSTANT && rightNode.getType() == INTEGER_CONSTANT) { boolean duplicateFound = false; Integer leftRange = (Integer) leftNode.getAttribute(VALUE) + 1; Integer rightRange = (Integer) rightNode.getAttribute(VALUE); while (leftRange <= rightRange) { if (!values.add(leftRange++) && !duplicateFound) { errorHandler.flag(token, NON_UNIQUE_MEMBERS, this); duplicateFound = true; } } } token = currentToken(); if (token.getType() == COMMA) { token = nextToken(); // Consume the , } else if (token.getType() != RIGHT_BRACKET) { errorHandler.flag(token, MISSING_COMMA, this); } } break; case INTEGER: errorHandler.flag(token, MISSING_COMMA, this); break; case SEMICOLON: isFinished = true; break; default: errorHandler.flag(token, UNEXPECTED_TOKEN, this); break; } } return rootNode; }