public final AntlrPilarParser.recordDeclaration_return recordDeclaration()
      throws RecognitionException {
    AntlrPilarParser.recordDeclaration_return retval = new AntlrPilarParser.recordDeclaration_return();
    retval.start = input.LT(1);
    int recordDeclaration_StartIndex = input.index();
    Object root_0 = null;

    Token t = null;
    Token ID80 = null;
    Token char_literal84 = null;
    Token char_literal86 = null;
    AntlrPilarParser.typeVarTuple_return typeVarTuple81 = null;

    AntlrPilarParser.annotationList_return annotationList82 = null;

    AntlrPilarParser.extendClause_return extendClause83 = null;

    AntlrPilarParser.attribute_return attribute85 = null;

    Object t_tree = null;
    Object ID80_tree = null;
    Object char_literal84_tree = null;
    Object char_literal86_tree = null;
    RewriteRuleTokenStream stream_181 = new RewriteRuleTokenStream(adaptor,
        "token 181");
    RewriteRuleTokenStream stream_ID = new RewriteRuleTokenStream(adaptor,
        "token ID");
    RewriteRuleTokenStream stream_178 = new RewriteRuleTokenStream(adaptor,
        "token 178");
    RewriteRuleTokenStream stream_177 = new RewriteRuleTokenStream(adaptor,
        "token 177");
    RewriteRuleSubtreeStream stream_extendClause = new RewriteRuleSubtreeStream(
        adaptor, "rule extendClause");
    RewriteRuleSubtreeStream stream_annotationList = new RewriteRuleSubtreeStream(
        adaptor, "rule annotationList");
    RewriteRuleSubtreeStream stream_attribute = new RewriteRuleSubtreeStream(
        adaptor, "rule attribute");
    RewriteRuleSubtreeStream stream_typeVarTuple = new RewriteRuleSubtreeStream(
        adaptor, "rule typeVarTuple");
    try {
      if (state.backtracking > 0 && alreadyParsedRule(input, 25)) {
        return retval;
      }
      // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:286:2: (t= 'record' ID ( typeVarTuple )? annotationList ( extendClause )? '{' ( attribute )* '}' -> ^( RECORD[$t] ID ^( OPTION ( typeVarTuple )? ) annotationList ^( OPTION ( extendClause )? ) ^( LIST ( attribute )* ) ) )
      // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:286:4: t= 'record' ID ( typeVarTuple )? annotationList ( extendClause )? '{' ( attribute )* '}'
      {
        t = (Token) match(input, 181, FOLLOW_181_in_recordDeclaration2127);
        if (state.failed) return retval;
        if (state.backtracking == 0) stream_181.add(t);

        ID80 = (Token) match(input, ID, FOLLOW_ID_in_recordDeclaration2132);
        if (state.failed) return retval;
        if (state.backtracking == 0) stream_ID.add(ID80);

        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:287:7: ( typeVarTuple )?
        int alt19 = 2;
        int LA19_0 = input.LA(1);

        if ((LA19_0 == 167)) {
          alt19 = 1;
        }
        switch (alt19) {
          case 1:
          // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:0:0: typeVarTuple
          {
            pushFollow(FOLLOW_typeVarTuple_in_recordDeclaration2134);
            typeVarTuple81 = typeVarTuple();

            state._fsp--;
            if (state.failed) return retval;
            if (state.backtracking == 0)
              stream_typeVarTuple.add(typeVarTuple81.getTree());

          }
            break;

        }

        pushFollow(FOLLOW_annotationList_in_recordDeclaration2137);
        annotationList82 = annotationList();

        state._fsp--;
        if (state.failed) return retval;
        if (state.backtracking == 0)
          stream_annotationList.add(annotationList82.getTree());
        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:288:4: ( extendClause )?
        int alt20 = 2;
        int LA20_0 = input.LA(1);

        if ((LA20_0 == 182)) {
          alt20 = 1;
        }
        switch (alt20) {
          case 1:
          // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:0:0: extendClause
          {
            pushFollow(FOLLOW_extendClause_in_recordDeclaration2142);
            extendClause83 = extendClause();

            state._fsp--;
            if (state.failed) return retval;
            if (state.backtracking == 0)
              stream_extendClause.add(extendClause83.getTree());

          }
            break;

        }

        char_literal84 = (Token) match(
            input,
            177,
            FOLLOW_177_in_recordDeclaration2148);
        if (state.failed) return retval;
        if (state.backtracking == 0) stream_177.add(char_literal84);

        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:289:8: ( attribute )*
        loop21: do {
          int alt21 = 2;
          int LA21_0 = input.LA(1);

          if (((LA21_0 >= ID && LA21_0 <= TYPEVARID) || LA21_0 == 169 || LA21_0 == 177)) {
            alt21 = 1;
          }

          switch (alt21) {
            case 1:
            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:0:0: attribute
            {
              pushFollow(FOLLOW_attribute_in_recordDeclaration2150);
              attribute85 = attribute();

              state._fsp--;
              if (state.failed) return retval;
              if (state.backtracking == 0)
                stream_attribute.add(attribute85.getTree());

            }
              break;

            default:
              break loop21;
          }
        } while (true);

        char_literal86 = (Token) match(
            input,
            178,
            FOLLOW_178_in_recordDeclaration2153);
        if (state.failed) return retval;
        if (state.backtracking == 0) stream_178.add(char_literal86);

        // AST REWRITE
        // elements: typeVarTuple, ID, annotationList, extendClause, attribute
        // token labels: 
        // rule labels: retval
        // token list labels: 
        // rule list labels: 
        // wildcard labels: 
        if (state.backtracking == 0) {
          retval.tree = root_0;
          RewriteRuleSubtreeStream stream_retval = new RewriteRuleSubtreeStream(
              adaptor, "rule retval", retval != null ? retval.tree : null);

          root_0 = (Object) adaptor.nil();
          // 289:41: -> ^( RECORD[$t] ID ^( OPTION ( typeVarTuple )? ) annotationList ^( OPTION ( extendClause )? ) ^( LIST ( attribute )* ) )
          {
            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:289:44: ^( RECORD[$t] ID ^( OPTION ( typeVarTuple )? ) annotationList ^( OPTION ( extendClause )? ) ^( LIST ( attribute )* ) )
            {
              Object root_1 = (Object) adaptor.nil();
              root_1 = (Object) adaptor.becomeRoot(
                  (Object) adaptor.create(RECORD, t),
                  root_1);

              adaptor.addChild(root_1, stream_ID.nextNode());
              // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:289:60: ^( OPTION ( typeVarTuple )? )
              {
                Object root_2 = (Object) adaptor.nil();
                root_2 = (Object) adaptor.becomeRoot(
                    (Object) adaptor.create(OPTION, "OPTION"),
                    root_2);

                // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:289:69: ( typeVarTuple )?
                if (stream_typeVarTuple.hasNext()) {
                  adaptor.addChild(root_2, stream_typeVarTuple.nextTree());

                }
                stream_typeVarTuple.reset();

                adaptor.addChild(root_1, root_2);
              }
              adaptor.addChild(root_1, stream_annotationList.nextTree());
              // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:289:99: ^( OPTION ( extendClause )? )
              {
                Object root_2 = (Object) adaptor.nil();
                root_2 = (Object) adaptor.becomeRoot(
                    (Object) adaptor.create(OPTION, "OPTION"),
                    root_2);

                // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:289:108: ( extendClause )?
                if (stream_extendClause.hasNext()) {
                  adaptor.addChild(root_2, stream_extendClause.nextTree());

                }
                stream_extendClause.reset();

                adaptor.addChild(root_1, root_2);
              }
              // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:289:123: ^( LIST ( attribute )* )
              {
                Object root_2 = (Object) adaptor.nil();
                root_2 = (Object) adaptor.becomeRoot(
                    (Object) adaptor.create(LIST, "LIST"),
                    root_2);

                // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:289:130: ( attribute )*
                while (stream_attribute.hasNext()) {
                  adaptor.addChild(root_2, stream_attribute.nextTree());

                }
                stream_attribute.reset();

                adaptor.addChild(root_1, root_2);
              }

              adaptor.addChild(root_0, root_1);
            }

          }

          retval.tree = root_0;
        }
      }

      retval.stop = input.LT(-1);

      if (state.backtracking == 0) {

        retval.tree = (Object) adaptor.rulePostProcessing(root_0);
        adaptor.setTokenBoundaries(retval.tree, retval.start, retval.stop);
      }
    } catch (RecognitionException re) {
      reportError(re);
      recover(input, re);
      retval.tree = (Object) adaptor.errorNode(
          input,
          retval.start,
          input.LT(-1),
          re);

    } finally {
      if (state.backtracking > 0) {
        memoize(input, 25, recordDeclaration_StartIndex);
      }
    }
    return retval;
  }