private SymTabEntry parseRoutineName(Token token, String dummyName) throws Exception {
    SymTabEntry routineId = null;

    // Parse the routine name identifier.
    if (token.getType() == IDENTIFIER) {
      String routineName = token.getText().toLowerCase();
      routineId = symTabStack.lookupLocal(routineName);

      // Not already defined locally: Enter into the local symbol table.
      if (routineId == null) {
        routineId = symTabStack.enterLocal(routineName);
        routineId.appendLineNumber(token.getLineNumber());
      }

      // If already defined, it should be a forward definition.
      else {
        routineId = null;
        errorHandler.flag(token, IDENTIFIER_REDEFINED, this);
      }

      token = nextToken(); // consume routine name identifier

    } else {
      errorHandler.flag(token, MISSING_IDENTIFIER, this);
    }

    // If necessary, create a dummy routine name symbol table entry.
    if (routineId == null) {
      routineId = symTabStack.enterLocal(dummyName);
    }

    return routineId;
  }
  protected void parseFormalParameters(Token token, SymTabEntry routineId) throws Exception {
    // Parse the formal parameters if there is an opening left parenthesis.
    token = synchronize(LEFT_PAREN_SET);
    if (token.getType() == LEFT_PAREN) {
      token = nextToken(); // consume (
      TokenType tokenType1 = token.getType();

      ArrayList<SymTabEntry> parms = new ArrayList<SymTabEntry>();
      while (tokenType1 != RIGHT_PAREN) {

        parms.addAll(parseParmSublist(token, routineId));

        token = currentToken();

        tokenType1 = token.getType();
      }

      // This sync needs to check for Int or Char
      token = synchronize(PARAMETER_SET);

      // Closing right parenthesis.
      if (token.getType() == RIGHT_PAREN) {
        token = nextToken(); // consume )
      } else {
        errorHandler.flag(token, MISSING_RIGHT_PAREN, this);
      }

      routineId.setAttribute(ROUTINE_PARMS, parms);
    }
  }
Exemple #3
0
  /**
   * Compile or interpret a Pascal source program.
   *
   * @param operation either "compile" or "execute".
   * @param filePath the source file path.
   * @param flags the command line flags.
   */
  public Pascal(String operation, String sourcePath, String inputPath, String flags) {
    try {
      intermediate = flags.indexOf('i') > -1;
      xref = flags.indexOf('x') > -1;

      source = new Source(new BufferedReader(new FileReader(sourcePath)));
      source.addMessageListener(new SourceMessageListener());

      parser = FrontendFactory.createParser("Pascal", "top-down", source);
      parser.addMessageListener(new ParserMessageListener());

      backend = BackendFactory.createBackend(operation, inputPath);
      backend.addMessageListener(new BackendMessageListener());

      parser.parse();
      source.close();

      if (parser.getErrorCount() == 0) {
        symTabStack = parser.getSymTabStack();

        SymTabEntry programId = symTabStack.getProgramId();
        iCode = (ICode) programId.getAttribute(ROUTINE_ICODE);

        if (xref) {
          CrossReferencer crossReferencer = new CrossReferencer();
          crossReferencer.print(symTabStack);
        }

        if (intermediate) {
          ParseTreePrinter treePrinter = new ParseTreePrinter(System.out);
          treePrinter.print(symTabStack);
        }
        backend.process(iCode, symTabStack);
      }
    } catch (Exception ex) {
      System.out.println("***** Internal translator error. *****");
      ex.printStackTrace();
    }
  }
  /**
   * 解析标识符
   *
   * @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;
  }
  /**
   * 解析标识符子表及类型说明
   *
   * @param token the current token.
   * @return 一个申明中的子表标识符列表
   * @throws Exception
   */
  protected ArrayList<SymTabEntry> parseIdentifierSublist(Token token) throws Exception {
    ArrayList<SymTabEntry> sublist = new ArrayList<SymTabEntry>();

    do {
      token = synchronize(IDENTIFIER_START_SET);
      SymTabEntry id = parseIdentifier(token);

      if (id != null) {
        sublist.add(id);
      }

      token = synchronize(COMMA_SET);
      TokenType tokenType = token.getType();

      // 找逗号
      if (tokenType == COMMA) {
        token = nextToken(); // 有逗号吞掉以便下一个

        if (IDENTIFIER_FOLLOW_SET.contains(token.getType())) {
          errorHandler.flag(token, MISSING_IDENTIFIER, this);
        }
      } else if (IDENTIFIER_START_SET.contains(tokenType)) {
        errorHandler.flag(token, MISSING_COMMA, this);
      }
    } while (!IDENTIFIER_FOLLOW_SET.contains(token.getType()));

    // 冒号后面的类型
    TypeSpec type = parseTypeSpec(token);

    // 将子表中的每个变量的类型设置上,比如a,b,c:int,先解析了a,b,c,然后解析了int类型
    // 那么这儿就会给a,b,c设置上int类型
    for (SymTabEntry variableId : sublist) {
      variableId.setTypeSpec(type);
    }

    return sublist;
  }
  private ArrayList<SymTabEntry> parseParmSublist(Token token, SymTabEntry routineId)
      throws Exception {

    // name = main, definition == function

    Definition parmDefn = null;
    TokenType tokenType = token.getType();
    parmDefn = VALUE_PARM;
    SymTabEntry sublist = null;

    if (tokenType == INT) {
      IntDeclarationsParser intDeclarationsParser = new IntDeclarationsParser(this);
      intDeclarationsParser.setDefinition(parmDefn);
      token = nextToken();
      sublist = intDeclarationsParser.parseIdentifier(token);
      sublist.setTypeSpec(integerType);

    } else if (tokenType == CHAR) {
      IntDeclarationsParser intDeclarationsParser = new IntDeclarationsParser(this);
      intDeclarationsParser.setDefinition(parmDefn);
      token = nextToken();
      sublist = intDeclarationsParser.parseIdentifier(token);
      sublist.setTypeSpec(charType);
    }
    token = nextToken();
    token = currentToken();
    if (token.getType() == COMMA) {
      token = nextToken();
    }

    tokenType = token.getType();
    token = synchronize(PARAMETER_SET);
    ArrayList<SymTabEntry> SC = new ArrayList<SymTabEntry>();
    SC.add(sublist);
    return SC;
  }
  /**
   * Parse a Triangle SingleDeclarationParser.
   *
   * <p>Single-Declaration ::= const Identifier ~ Expression | var Identifier : Type-Denoter | proc
   * Identifier (Formal-Parameter-Sequence) ~ Single-Command | func Identifier
   * (Formal-Parameter-Sequence) : Type-Denoter ~ Expression | Type Identifier ~ Type-Denoter
   *
   * <p>To be overridden by the specialized command parse subclasses.
   *
   * @param token the initial token.
   * @return the root node of the generated parse tree.
   * @throws Exception if an error occurred.
   */
  public void parse(Token token) throws Exception {
    SingleCommandParser singleCommand = null;
    ExpressionParser expression = null;
    FormalParameterSequenceParser formalParameterSequence = null;
    TypeDenoterParser typeDenoter = null;
    EnumSet<TriangleTokenType> syncSet = null;
    TypeSpec identifierType = TrianglePredefined.undefinedType;
    Token identifierToken = null;
    ICode routineICode = null;

    token = currentToken();

    switch ((TriangleTokenType) token.getType()) {
      case CONST:
        identifierToken = nextToken();
        syncSet = EnumSet.of(TILDE);
        syncSet.addAll(ExpressionParser.FIRST_FOLLOW_SET);
        synchronize(IDENTIFIER, MISSING_IDENTIFIER, syncSet);
        syncSet.remove(TILDE);
        token = synchronize(TILDE, MISSING_TILDE, syncSet);
        expression = new ExpressionParser(this);
        ICodeNode expressionNode = expression.parse(token);

        SymTabEntry constantId = symTabStack.lookupLocal(identifierToken.getText().toLowerCase());
        // Enter the new identifier into the symbol table
        // but don't set how it's defined yet.
        if (constantId == null) {
          constantId = symTabStack.enterLocal(identifierToken.getText().toLowerCase());
          constantId.setDefinition(DefinitionImpl.CONSTANT);
          constantId.setAttribute(CONSTANT_VALUE, expressionNode);
          constantId.appendLineNumber(identifierToken.getLineNumber());
          constantId.setTypeSpec(expressionNode.getTypeSpec());
        } else {
          errorHandler.flag(identifierToken, IDENTIFIER_REDEFINED, this);
        }
        break;
      case VAR:
        identifierToken = nextToken();
        syncSet = EnumSet.of(COLON);
        syncSet.addAll(TypeDenoterParser.FIRST_FOLLOW_SET);
        synchronize(IDENTIFIER, MISSING_IDENTIFIER, syncSet);

        syncSet.remove(COLON);
        token = synchronize(COLON, MISSING_COLON, syncSet);

        typeDenoter = new TypeDenoterParser(this);
        identifierType = typeDenoter.parse(token);

        SymTabEntry variableId = symTabStack.lookupLocal(identifierToken.getText().toLowerCase());
        // Enter the new identifier into the symbol table
        // but don't set how it's defined yet.
        if (variableId == null) {
          variableId = symTabStack.enterLocal(identifierToken.getText().toLowerCase());
          variableId.setDefinition(DefinitionImpl.VARIABLE);
          variableId.appendLineNumber(identifierToken.getLineNumber());
          variableId.setTypeSpec(identifierType);
        } else {
          errorHandler.flag(identifierToken, IDENTIFIER_REDEFINED, this);
        }
        break;
      case PROC:
        identifierToken = nextToken();
        routineICode = ICodeFactory.createICode();
        syncSet = EnumSet.of(LEFT_PAREN);
        syncSet.addAll(FormalParameterSequenceParser.FIRST_FOLLOW_SET);
        token = synchronize(IDENTIFIER, MISSING_IDENTIFIER, syncSet);
        syncSet.remove(LEFT_PAREN);
        token = synchronize(LEFT_PAREN, MISSING_LEFT_PAREN, syncSet);
        SymTabEntry procId = symTabStack.lookupLocal(identifierToken.getText().toLowerCase());
        // Enter the new identifier into the symbol table
        // but don't set how it's defined yet.
        if (procId == null) {
          procId = symTabStack.enterLocal(identifierToken.getText().toLowerCase());
          procId.setTypeSpec(TrianglePredefined.undefinedType);
          procId.setDefinition(DefinitionImpl.PROCEDURE);
          procId.appendLineNumber(identifierToken.getLineNumber());
          procId.setAttribute(ROUTINE_SYMTAB, symTabStack.push());
          procId.setAttribute(ROUTINE_ICODE, routineICode);
        } else {
          errorHandler.flag(identifierToken, IDENTIFIER_REDEFINED, this);
          procId = null;
        }

        formalParameterSequence = new FormalParameterSequenceParser(this);
        ArrayList<SymTabEntry> procParamList = formalParameterSequence.parse(token);
        syncSet = EnumSet.of(TILDE);
        syncSet.addAll(SingleCommandParser.FIRST_FOLLOW_SET);
        token = synchronize(RIGHT_PAREN, MISSING_RIGHT_PAREN, syncSet);
        syncSet.remove(TILDE);
        token = synchronize(TILDE, MISSING_TILDE, syncSet);
        singleCommand = new SingleCommandParser(this);
        routineICode.setRoot(singleCommand.parse(token));
        if (procId != null) {
          procId.setAttribute(ROUTINE_PARMS, procParamList);
        }
        symTabStack.pop();
        break;
      case FUNC:
        identifierToken = nextToken();
        routineICode = ICodeFactory.createICode();
        SymTabEntry funcId = symTabStack.lookupLocal(identifierToken.getText().toLowerCase());
        // Enter the new identifier into the symbol table
        // but don't set how it's defined yet.
        if (funcId == null) {
          funcId = symTabStack.enterLocal(identifierToken.getText().toLowerCase());
          funcId.setDefinition(DefinitionImpl.FUNCTION);
          funcId.appendLineNumber(identifierToken.getLineNumber());
          funcId.setTypeSpec(TrianglePredefined.undefinedType);
          funcId.setAttribute(ROUTINE_SYMTAB, symTabStack.push());
          funcId.setAttribute(ROUTINE_ICODE, routineICode);
        } else {
          errorHandler.flag(identifierToken, IDENTIFIER_REDEFINED, this);
          funcId = null;
        }
        syncSet = EnumSet.of(LEFT_PAREN);
        syncSet.addAll(FormalParameterSequenceParser.FIRST_FOLLOW_SET);
        token = synchronize(IDENTIFIER, MISSING_IDENTIFIER, syncSet);
        syncSet.remove(LEFT_PAREN);
        token = synchronize(LEFT_PAREN, MISSING_LEFT_PAREN, syncSet);
        formalParameterSequence = new FormalParameterSequenceParser(this);
        ArrayList<SymTabEntry> funcParamList = formalParameterSequence.parse(token);
        syncSet = EnumSet.of(COLON);
        syncSet.addAll(TypeDenoterParser.FIRST_FOLLOW_SET);
        synchronize(RIGHT_PAREN, MISSING_RIGHT_PAREN, syncSet);
        syncSet.remove(COLON);
        token = synchronize(COLON, MISSING_COLON, syncSet);
        Token typeToken = currentToken();
        typeDenoter = new TypeDenoterParser(this);
        TypeSpec funcType = typeDenoter.parse(token);
        syncSet = ExpressionParser.FIRST_FOLLOW_SET.clone();
        token = synchronize(TILDE, MISSING_TILDE, syncSet);
        expression = new ExpressionParser(this);
        routineICode.setRoot(expression.parse(token));
        if (funcId != null) {
          funcId.setTypeSpec(funcType);
          funcId.setAttribute(ROUTINE_PARMS, funcParamList);
          if (!routineICode.getRoot().getTypeSpec().equals(funcType)) {
            errorHandler.flag(typeToken, RETURN_TYPE_MISMATCH, this);
          }
        }
        symTabStack.pop();
        break;
      case TYPE:
        identifierToken = nextToken();
        syncSet = EnumSet.of(TILDE);
        syncSet.addAll(TypeDenoterParser.FIRST_FOLLOW_SET);
        synchronize(IDENTIFIER, MISSING_IDENTIFIER, syncSet);
        syncSet.remove(TILDE);
        token = synchronize(TILDE, MISSING_TILDE, syncSet);
        typeDenoter = new TypeDenoterParser(this);
        TypeSpec typeType = typeDenoter.parse(token);
        SymTabEntry typeId = symTabStack.lookupLocal(identifierToken.getText().toLowerCase());
        // Enter the new identifier into the symbol table
        // but don't set how it's defined yet.
        if (typeId == null) {
          typeId = symTabStack.enterLocal(identifierToken.getText().toLowerCase());
          typeId.setDefinition(DefinitionImpl.TYPE);
          typeId.appendLineNumber(identifierToken.getLineNumber());
          typeId.setTypeSpec(typeType);
        } else {
          errorHandler.flag(token, IDENTIFIER_REDEFINED, this);
        }
        break;
      default:
        errorHandler.flag(token, MISSING_DECLARATION, this);
        break;
    }
  }
  /**
   * 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);
    }
  }
  public SymTabEntry parse(Token token, SymTabEntry parentId) throws Exception {

    Token FunctionReturnToken = token;

    Definition routineDefn = null;
    String dummyName = null;
    SymTabEntry routineId = null;
    TokenType routineType = token.getType();

    // Initialize.
    switch ((WookieTokenType) routineType) {
      case INT:
        {
          // save the int data type for use later
          FunctionReturnToken = token;
          token = nextToken(); // consume Int		
          routineDefn = DefinitionImpl.FUNCTION;
          dummyName = "DummyProgramName".toLowerCase() + String.format("%03d", ++dummyCounter);
          break;
        }

      case CHAR:
        {
          // save the char data type for use later
          FunctionReturnToken = token;
          token = nextToken(); // consume Char
          routineDefn = DefinitionImpl.FUNCTION;
          dummyName = "DummyProgramName".toLowerCase() + String.format("%03d", ++dummyCounter);
          break;
        }

      case VOID:
        {
          // save the void data type for use later
          FunctionReturnToken = token;
          token = nextToken(); // consume PROGRAM
          routineDefn = DefinitionImpl.PROCEDURE;
          dummyName = "DummyProgramName".toLowerCase() + String.format("%03d", ++dummyCounter);
          break;
        }

      default:
        {
          routineDefn = DefinitionImpl.PROGRAM;
          dummyName = "DummyProgramName".toLowerCase();
          break;
        }
    }

    // Parse the routine name.
    routineId = parseRoutineName(token, dummyName);

    routineId.setDefinition(routineDefn);
    token = currentToken();

    // Create new intermediate code for the routine.
    ICode iCode = ICodeFactory.createICode();
    routineId.setAttribute(ROUTINE_ICODE, iCode);
    routineId.setAttribute(ROUTINE_ROUTINES, new ArrayList<SymTabEntry>());

    SymTab symTab = symTabStack.push();

    routineId.setAttribute(ROUTINE_SYMTAB, symTab);

    ((SymTabImpl) symTab).setfuncName(routineId.getName());

    parseFormalParameters(token, routineId);
    token = currentToken();

    if (FunctionReturnToken.getType() == INT) {
      routineId.setTypeSpec(integerType);
    } else if (FunctionReturnToken.getType() == CHAR) {
      routineId.setTypeSpec(charType);
    }

    // Parse the routine's block  declaration.
    if (token.getType() == LEFT_BRACE) {

      routineId.setAttribute(ROUTINE_CODE, DECLARED);
      BlockParser blockParser = new BlockParser(this);

      ICodeNode rootNode = blockParser.parse(token, routineId);
      iCode.setRoot(rootNode);
    }
    ArrayList<SymTabEntry> subroutines =
        (ArrayList<SymTabEntry>) parentId.getAttribute(ROUTINE_ROUTINES);
    subroutines.add(routineId);
    // Pop the routine's symbol table off the stack.

    symTabStack.pop();

    return routineId;
  }
Exemple #11
0
  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;
  }