public final AntlrPilarParser.body_return body() throws RecognitionException {
    AntlrPilarParser.body_return retval = new AntlrPilarParser.body_return();
    retval.start = input.LT(1);
    int body_StartIndex = input.index();
    Object root_0 = null;

    Token t = null;
    Token char_literal214 = null;
    AntlrPilarParser.localVarsDeclaration_return localVarsDeclaration211 = null;

    AntlrPilarParser.location_return location212 = null;

    AntlrPilarParser.catchClause_return catchClause213 = null;

    Object t_tree = null;
    Object char_literal214_tree = null;
    RewriteRuleTokenStream stream_178 = new RewriteRuleTokenStream(adaptor,
        "token 178");
    RewriteRuleTokenStream stream_177 = new RewriteRuleTokenStream(adaptor,
        "token 177");
    RewriteRuleSubtreeStream stream_localVarsDeclaration = new RewriteRuleSubtreeStream(
        adaptor, "rule localVarsDeclaration");
    RewriteRuleSubtreeStream stream_catchClause = new RewriteRuleSubtreeStream(
        adaptor, "rule catchClause");
    RewriteRuleSubtreeStream stream_location = new RewriteRuleSubtreeStream(
        adaptor, "rule location");
    try {
      if (state.backtracking > 0 && alreadyParsedRule(input, 54)) {
        return retval;
      }
      // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:444:2: (t= '{' ( localVarsDeclaration )? ( location )+ ( catchClause )* '}' -> ^( BODY[$t] ^( OPTION ( localVarsDeclaration )? ) ^( LIST ( location )+ ) ^( LIST ( catchClause )* ) ) )
      // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:444:4: t= '{' ( localVarsDeclaration )? ( location )+ ( catchClause )* '}'
      {
        t = (Token) match(input, 177, FOLLOW_177_in_body3905);
        if (state.failed) return retval;
        if (state.backtracking == 0) stream_177.add(t);

        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:444:10: ( localVarsDeclaration )?
        int alt65 = 2;
        int LA65_0 = input.LA(1);

        if (((LA65_0 >= ID && LA65_0 <= TYPEVARID) || LA65_0 == 169
            || LA65_0 == 177 || LA65_0 == 193)) {
          alt65 = 1;
        }
        switch (alt65) {
          case 1:
          // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:0:0: localVarsDeclaration
          {
            pushFollow(FOLLOW_localVarsDeclaration_in_body3907);
            localVarsDeclaration211 = localVarsDeclaration();

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

          }
            break;

        }

        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:445:4: ( location )+
        int cnt66 = 0;
        loop66: do {
          int alt66 = 2;
          int LA66_0 = input.LA(1);

          if ((LA66_0 == LOCID)) {
            alt66 = 1;
          }

          switch (alt66) {
            case 1:
            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:0:0: location
            {
              pushFollow(FOLLOW_location_in_body3914);
              location212 = location();

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

            }
              break;

            default:
              if (cnt66 >= 1) break loop66;
              if (state.backtracking > 0) {
                state.failed = true;
                return retval;
              }
              EarlyExitException eee = new EarlyExitException(66, input);
              throw eee;
          }
          cnt66++;
        } while (true);

        // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:446:4: ( catchClause )*
        loop67: do {
          int alt67 = 2;
          int LA67_0 = input.LA(1);

          if ((LA67_0 == 211)) {
            alt67 = 1;
          }

          switch (alt67) {
            case 1:
            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:0:0: catchClause
            {
              pushFollow(FOLLOW_catchClause_in_body3921);
              catchClause213 = catchClause();

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

            }
              break;

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

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

        // AST REWRITE
        // elements: catchClause, location, localVarsDeclaration
        // 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();
          // 446:41: -> ^( BODY[$t] ^( OPTION ( localVarsDeclaration )? ) ^( LIST ( location )+ ) ^( LIST ( catchClause )* ) )
          {
            // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:446:44: ^( BODY[$t] ^( OPTION ( localVarsDeclaration )? ) ^( LIST ( location )+ ) ^( LIST ( catchClause )* ) )
            {
              Object root_1 = (Object) adaptor.nil();
              root_1 = (Object) adaptor.becomeRoot(
                  (Object) adaptor.create(BODY, t),
                  root_1);

              // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:446:55: ^( OPTION ( localVarsDeclaration )? )
              {
                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:446:64: ( localVarsDeclaration )?
                if (stream_localVarsDeclaration.hasNext()) {
                  adaptor.addChild(
                      root_2,
                      stream_localVarsDeclaration.nextTree());

                }
                stream_localVarsDeclaration.reset();

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

                if (!(stream_location.hasNext())) {
                  throw new RewriteEarlyExitException();
                }
                while (stream_location.hasNext()) {
                  adaptor.addChild(root_2, stream_location.nextTree());

                }
                stream_location.reset();

                adaptor.addChild(root_1, root_2);
              }
              // /Users/robby/Repositories/sireum-parser/sireum-parser/src/main/java/org/sireum/pilar/parser/AntlrPilar.g:446:105: ^( LIST ( catchClause )* )
              {
                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:446:112: ( catchClause )*
                while (stream_catchClause.hasNext()) {
                  adaptor.addChild(root_2, stream_catchClause.nextTree());

                }
                stream_catchClause.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, 54, body_StartIndex);
      }
    }
    return retval;
  }