public final AntlrPilarParser.extParamVariable_return extParamVariable()
      throws RecognitionException {
    AntlrPilarParser.extParamVariable_return retval = new AntlrPilarParser.extParamVariable_return();
    retval.start = input.LT(1);
    int extParamVariable_StartIndex = input.index();
    Object root_0 = null;

    Token ID208 = null;
    Token string_literal209 = null;
    AntlrPilarParser.type_return type207 = null;

    AntlrPilarParser.annotationList_return annotationList210 = null;

    Object ID208_tree = null;
    Object string_literal209_tree = null;
    RewriteRuleTokenStream stream_185 = new RewriteRuleTokenStream(adaptor,
        "token 185");
    RewriteRuleTokenStream stream_ID = new RewriteRuleTokenStream(adaptor,
        "token ID");
    RewriteRuleSubtreeStream stream_annotationList = new RewriteRuleSubtreeStream(
        adaptor, "rule annotationList");
    RewriteRuleSubtreeStream stream_type = new RewriteRuleSubtreeStream(
        adaptor, "rule type");
    try {
      if (state.backtracking > 0 && alreadyParsedRule(input, 53)) {
        return retval;
      }
      // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:439:2: ( ( type )? ( ID )? '...' annotationList -> ^( EXT_PARAM_VARIABLE ^( OPTION ( type )? ) ^( OPTION ( ID )? ) annotationList ) )
      // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:439:4: ( type )? ( ID )? '...' annotationList
      {
        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:439:4: ( type )?
        int alt63 = 2;
        int LA63_0 = input.LA(1);

        if ((LA63_0 == TYPEVARID || LA63_0 == 169 || LA63_0 == 177)) {
          alt63 = 1;
        } else if ((LA63_0 == ID)) {
          int LA63_2 = input.LA(2);

          if ((synpred75_AntlrPilar())) {
            alt63 = 1;
          }
        }
        switch (alt63) {
          case 1:
          // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:0:0: type
          {
            pushFollow(FOLLOW_type_in_extParamVariable3841);
            type207 = type();

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

          }
            break;

        }

        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:439:10: ( ID )?
        int alt64 = 2;
        int LA64_0 = input.LA(1);

        if ((LA64_0 == ID)) {
          alt64 = 1;
        }
        switch (alt64) {
          case 1:
          // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:0:0: ID
          {
            ID208 = (Token) match(input, ID, FOLLOW_ID_in_extParamVariable3844);
            if (state.failed) return retval;
            if (state.backtracking == 0) stream_ID.add(ID208);

          }
            break;

        }

        string_literal209 = (Token) match(
            input,
            185,
            FOLLOW_185_in_extParamVariable3851);
        if (state.failed) return retval;
        if (state.backtracking == 0) stream_185.add(string_literal209);

        pushFollow(FOLLOW_annotationList_in_extParamVariable3853);
        annotationList210 = annotationList();

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

        // AST REWRITE
        // elements: annotationList, type, ID
        // 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();
          // 440:41: -> ^( EXT_PARAM_VARIABLE ^( OPTION ( type )? ) ^( OPTION ( ID )? ) annotationList )
          {
            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:440:44: ^( EXT_PARAM_VARIABLE ^( OPTION ( type )? ) ^( OPTION ( ID )? ) annotationList )
            {
              Object root_1 = (Object) adaptor.nil();
              root_1 = (Object) adaptor.becomeRoot((Object) adaptor.create(
                  EXT_PARAM_VARIABLE,
                  "EXT_PARAM_VARIABLE"), root_1);

              // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:440:65: ^( OPTION ( type )? )
              {
                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:440:74: ( type )?
                if (stream_type.hasNext()) {
                  adaptor.addChild(root_2, stream_type.nextTree());

                }
                stream_type.reset();

                adaptor.addChild(root_1, root_2);
              }
              // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:440:81: ^( OPTION ( ID )? )
              {
                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:440:90: ( ID )?
                if (stream_ID.hasNext()) {
                  adaptor.addChild(root_2, stream_ID.nextNode());

                }
                stream_ID.reset();

                adaptor.addChild(root_1, root_2);
              }
              adaptor.addChild(root_1, stream_annotationList.nextTree());

              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, 53, extParamVariable_StartIndex);
      }
    }
    return retval;
  }