public final AntlrPilarParser.typeExtension_return typeExtension()
      throws RecognitionException {
    AntlrPilarParser.typeExtension_return retval = new AntlrPilarParser.typeExtension_return();
    retval.start = input.LT(1);
    int typeExtension_StartIndex = input.index();
    Object root_0 = null;

    Token t = null;
    Token ID162 = null;
    Token char_literal164 = null;
    Token char_literal166 = null;
    Token char_literal168 = null;
    AntlrPilarParser.typeVarTuple_return typeVarTuple161 = null;

    AntlrPilarParser.annotationList_return annotationList163 = null;

    AntlrPilarParser.extendClause_return extendClause165 = null;

    AntlrPilarParser.typeExtensionMember_return typeExtensionMember167 = null;

    Object t_tree = null;
    Object ID162_tree = null;
    Object char_literal164_tree = null;
    Object char_literal166_tree = null;
    Object char_literal168_tree = null;
    RewriteRuleTokenStream stream_175 = new RewriteRuleTokenStream(adaptor,
        "token 175");
    RewriteRuleTokenStream stream_ID = new RewriteRuleTokenStream(adaptor,
        "token ID");
    RewriteRuleTokenStream stream_178 = new RewriteRuleTokenStream(adaptor,
        "token 178");
    RewriteRuleTokenStream stream_177 = new RewriteRuleTokenStream(adaptor,
        "token 177");
    RewriteRuleTokenStream stream_189 = new RewriteRuleTokenStream(adaptor,
        "token 189");
    RewriteRuleSubtreeStream stream_typeExtensionMember = new RewriteRuleSubtreeStream(
        adaptor, "rule typeExtensionMember");
    RewriteRuleSubtreeStream stream_extendClause = new RewriteRuleSubtreeStream(
        adaptor, "rule extendClause");
    RewriteRuleSubtreeStream stream_annotationList = new RewriteRuleSubtreeStream(
        adaptor, "rule annotationList");
    RewriteRuleSubtreeStream stream_typeVarTuple = new RewriteRuleSubtreeStream(
        adaptor, "rule typeVarTuple");
    try {
      if (state.backtracking > 0 && alreadyParsedRule(input, 45)) {
        return retval;
      }
      // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:391:2: (t= 'typedef' ( typeVarTuple )? ID annotationList ( ';' | ( extendClause )? '{' ( typeExtensionMember )* '}' ) -> ^( TYPE_EXT[$t] ^( OPTION ( typeVarTuple )? ) ID annotationList ^( OPTION ( extendClause )? ) ^( LIST ( typeExtensionMember )* ) ) )
      // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:391:4: t= 'typedef' ( typeVarTuple )? ID annotationList ( ';' | ( extendClause )? '{' ( typeExtensionMember )* '}' )
      {
        t = (Token) match(input, 189, FOLLOW_189_in_typeExtension3258);
        if (state.failed) return retval;
        if (state.backtracking == 0) stream_189.add(t);

        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:391:16: ( typeVarTuple )?
        int alt45 = 2;
        int LA45_0 = input.LA(1);

        if ((LA45_0 == 167)) {
          alt45 = 1;
        }
        switch (alt45) {
          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_typeExtension3260);
            typeVarTuple161 = typeVarTuple();

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

          }
            break;

        }

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

        pushFollow(FOLLOW_annotationList_in_typeExtension3268);
        annotationList163 = annotationList();

        state._fsp--;
        if (state.failed) return retval;
        if (state.backtracking == 0)
          stream_annotationList.add(annotationList163.getTree());
        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:393:4: ( ';' | ( extendClause )? '{' ( typeExtensionMember )* '}' )
        int alt48 = 2;
        int LA48_0 = input.LA(1);

        if ((LA48_0 == 175)) {
          alt48 = 1;
        } else if ((LA48_0 == 177 || LA48_0 == 182)) {
          alt48 = 2;
        } else {
          if (state.backtracking > 0) {
            state.failed = true;
            return retval;
          }
          NoViableAltException nvae = new NoViableAltException("", 48, 0, input);

          throw nvae;
        }
        switch (alt48) {
          case 1:
          // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:393:6: ';'
          {
            char_literal164 = (Token) match(
                input,
                175,
                FOLLOW_175_in_typeExtension3275);
            if (state.failed) return retval;
            if (state.backtracking == 0) stream_175.add(char_literal164);

          }
            break;
          case 2:
          // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:394:6: ( extendClause )? '{' ( typeExtensionMember )* '}'
          {
            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:394:6: ( extendClause )?
            int alt46 = 2;
            int LA46_0 = input.LA(1);

            if ((LA46_0 == 182)) {
              alt46 = 1;
            }
            switch (alt46) {
              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_typeExtension3282);
                extendClause165 = extendClause();

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

              }
                break;

            }

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

            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:395:10: ( typeExtensionMember )*
            loop47: do {
              int alt47 = 2;
              int LA47_0 = input.LA(1);

              if ((LA47_0 == ID || (LA47_0 >= 190 && LA47_0 <= 192))) {
                alt47 = 1;
              }

              switch (alt47) {
                case 1:
                // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:0:0: typeExtensionMember
                {
                  pushFollow(FOLLOW_typeExtensionMember_in_typeExtension3292);
                  typeExtensionMember167 = typeExtensionMember();

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

                }
                  break;

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

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

          }
            break;

        }

        // AST REWRITE
        // elements: extendClause, ID, typeVarTuple, typeExtensionMember, annotationList
        // 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();
          // 395:41: -> ^( TYPE_EXT[$t] ^( OPTION ( typeVarTuple )? ) ID annotationList ^( OPTION ( extendClause )? ) ^( LIST ( typeExtensionMember )* ) )
          {
            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:395:44: ^( TYPE_EXT[$t] ^( OPTION ( typeVarTuple )? ) ID annotationList ^( OPTION ( extendClause )? ) ^( LIST ( typeExtensionMember )* ) )
            {
              Object root_1 = (Object) adaptor.nil();
              root_1 = (Object) adaptor.becomeRoot(
                  (Object) adaptor.create(TYPE_EXT, t),
                  root_1);

              // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:395:59: ^( 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:395:68: ( 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_ID.nextNode());
              adaptor.addChild(root_1, stream_annotationList.nextTree());
              // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:395:101: ^( 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:395:110: ( 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:395:126: ^( LIST ( typeExtensionMember )* )
              {
                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:395:133: ( typeExtensionMember )*
                while (stream_typeExtensionMember.hasNext()) {
                  adaptor.addChild(
                      root_2,
                      stream_typeExtensionMember.nextTree());

                }
                stream_typeExtensionMember.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, 45, typeExtension_StartIndex);
      }
    }
    return retval;
  }