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;
  }