public final AntlrPilarParser.annotationParam_return annotationParam()
      throws RecognitionException {
    AntlrPilarParser.annotationParam_return retval = new AntlrPilarParser.annotationParam_return();
    retval.start = input.LT(1);
    int annotationParam_StartIndex = input.index();
    Object root_0 = null;

    Token t = null;
    Token char_literal41 = null;
    AntlrPilarParser.annotation_return annotation42 = null;

    AntlrPilarParser.exp_return exp43 = null;

    AntlrPilarParser.annotation_return annotation44 = null;

    AntlrPilarParser.exp_return exp45 = null;

    Object t_tree = null;
    Object char_literal41_tree = null;
    RewriteRuleTokenStream stream_173 = new RewriteRuleTokenStream(adaptor,
        "token 173");
    RewriteRuleTokenStream stream_ID = new RewriteRuleTokenStream(adaptor,
        "token ID");
    RewriteRuleSubtreeStream stream_annotation = new RewriteRuleSubtreeStream(
        adaptor, "rule annotation");
    RewriteRuleSubtreeStream stream_exp = new RewriteRuleSubtreeStream(adaptor,
        "rule exp");
    try {
      if (state.backtracking > 0 && alreadyParsedRule(input, 17)) {
        return retval;
      }
      // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:238:2: (t= ID '=' ( annotation | exp ) -> ^( ANNOTATION_PARAM_IDED[$t] ^( OPTION ( ID )? ) ( annotation )? ( exp )? ) | annotation -> ^( ANNOTATION_PARAM_IDED ^( OPTION ) annotation ) | exp -> ^( ANNOTATION_PARAM_IDED ^( OPTION ) exp ) )
      int alt14 = 3;
      switch (input.LA(1)) {
        case ID: {
          int LA14_1 = input.LA(2);

          if ((LA14_1 == 173)) {
            alt14 = 1;
          } else if ((LA14_1 == EOF || (LA14_1 >= HEX_LIT && LA14_1 <= OCT_LIT)
              || LA14_1 == ID || LA14_1 == GLOBALID
              || (LA14_1 >= COND_OR_OP && LA14_1 <= MUL_OP)
              || (LA14_1 >= CHAR_LIT && LA14_1 <= RATIONAL_LIT)
              || (LA14_1 >= 167 && LA14_1 <= 170) || LA14_1 == 172
              || LA14_1 == 177 || LA14_1 == 202
              || (LA14_1 >= 213 && LA14_1 <= 221) || LA14_1 == 223 || LA14_1 == 225)) {
            alt14 = 3;
          } else {
            if (state.backtracking > 0) {
              state.failed = true;
              return retval;
            }
            NoViableAltException nvae = new NoViableAltException("", 14, 1,
                input);

            throw nvae;
          }
        }
          break;
        case 171: {
          alt14 = 2;
        }
          break;
        case HEX_LIT:
        case DEC_LIT:
        case OCT_LIT:
        case GLOBALID:
        case ADD_OP:
        case MUL_OP:
        case UN_OP:
        case CHAR_LIT:
        case STRING_LIT:
        case SYMBOL_LIT:
        case RAW_LIT:
        case BIN_LIT:
        case FLOAT_LIT:
        case RATIONAL_LIT:
        case 169:
        case 177:
        case 204:
        case 208:
        case 215:
        case 217:
        case 218:
        case 219:
        case 220:
        case 221:
        case 223: {
          alt14 = 3;
        }
          break;
        default:
          if (state.backtracking > 0) {
            state.failed = true;
            return retval;
          }
          NoViableAltException nvae = new NoViableAltException("", 14, 0, input);

          throw nvae;
      }

      switch (alt14) {
        case 1:
        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:238:4: t= ID '=' ( annotation | exp )
        {
          t = (Token) match(input, ID, FOLLOW_ID_in_annotationParam1586);
          if (state.failed) return retval;
          if (state.backtracking == 0) stream_ID.add(t);

          char_literal41 = (Token) match(
              input,
              173,
              FOLLOW_173_in_annotationParam1588);
          if (state.failed) return retval;
          if (state.backtracking == 0) stream_173.add(char_literal41);

          // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:238:13: ( annotation | exp )
          int alt13 = 2;
          int LA13_0 = input.LA(1);

          if ((LA13_0 == 171)) {
            alt13 = 1;
          } else if (((LA13_0 >= HEX_LIT && LA13_0 <= OCT_LIT) || LA13_0 == ID
              || LA13_0 == GLOBALID
              || (LA13_0 >= ADD_OP && LA13_0 <= RATIONAL_LIT) || LA13_0 == 169
              || LA13_0 == 177 || LA13_0 == 204 || LA13_0 == 208
              || LA13_0 == 215 || (LA13_0 >= 217 && LA13_0 <= 221) || LA13_0 == 223)) {
            alt13 = 2;
          } else {
            if (state.backtracking > 0) {
              state.failed = true;
              return retval;
            }
            NoViableAltException nvae = new NoViableAltException("", 13, 0,
                input);

            throw nvae;
          }
          switch (alt13) {
            case 1:
            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:238:15: annotation
            {
              pushFollow(FOLLOW_annotation_in_annotationParam1592);
              annotation42 = annotation();

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

            }
              break;
            case 2:
            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:238:28: exp
            {
              pushFollow(FOLLOW_exp_in_annotationParam1596);
              exp43 = exp();

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

            }
              break;

          }

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

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

                  }
                  stream_ID.reset();

                  adaptor.addChild(root_1, root_2);
                }
                // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:238:86: ( annotation )?
                if (stream_annotation.hasNext()) {
                  adaptor.addChild(root_1, stream_annotation.nextTree());

                }
                stream_annotation.reset();
                // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:238:98: ( exp )?
                if (stream_exp.hasNext()) {
                  adaptor.addChild(root_1, stream_exp.nextTree());

                }
                stream_exp.reset();

                adaptor.addChild(root_0, root_1);
              }

            }

            retval.tree = root_0;
          }
        }
          break;
        case 2:
        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:239:4: annotation
        {
          pushFollow(FOLLOW_annotation_in_annotationParam1630);
          annotation44 = annotation();

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

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

                // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:239:68: ^( OPTION )
                {
                  Object root_2 = (Object) adaptor.nil();
                  root_2 = (Object) adaptor.becomeRoot(
                      (Object) adaptor.create(OPTION, "OPTION"),
                      root_2);

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

                adaptor.addChild(root_0, root_1);
              }

            }

            retval.tree = root_0;
          }
        }
          break;
        case 3:
        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:240:4: exp
        {
          pushFollow(FOLLOW_exp_in_annotationParam1673);
          exp45 = exp();

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

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

                // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:240:68: ^( OPTION )
                {
                  Object root_2 = (Object) adaptor.nil();
                  root_2 = (Object) adaptor.becomeRoot(
                      (Object) adaptor.create(OPTION, "OPTION"),
                      root_2);

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

                adaptor.addChild(root_0, root_1);
              }

            }

            retval.tree = root_0;
          }
        }
          break;

      }
      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, 17, annotationParam_StartIndex);
      }
    }
    return retval;
  }