c.c

    //\\ B<char> = 0;
    //\\ B<internal-identifier> = 1;
    //\\ B<integer-constant> = 2;
    //\\ # <character-constant> temporarily replaced by <sqstring>
    //\\ # and <string> temporarily replaced by <dqstring>
    //\\ # because parser.c TEMPORARILY assumes these exist in all parsers :-(
    //\\ B<sqstring> = 3;
    //\\ B<floating-constant> = 4;
    //\\ B<dqstring> = 5;
    //\\ B<keyword> = 6;
    //\\ B<pp> = 7;
    //\\ B<mm> = 8;
    //\\ B<andand> = 9;
    //\\ B<oror> = 10;
    //\\ B<eqeq> = 11;
    //\\ # char, NL, and EOF are required by all parsers
    //\\ B<NL> = 12;
    //\\ B<EOF> = 13;

    //\\ C<immediate> = {
    //\\ // WARNING: currently parse-time phrases are not being handled properly
    //\\ //          by compile(). Are they set to -1 or skipped completely?
    //\\ extern int *A; // remove as much of this as possible as soon as things start working again...
    //\\ extern int cp;                     // code pointer.  Has to be global state.
    //\\ extern int ap;                     // Analysis record pointer.
    //\\ int kw(int AST_op, int kw_idx, int ap)  // kw(AST__KW, KW_void, A[ap+0]);
    //\\
    //\\ {
    //\\   int data[3];
    //\\
    //\\   data[1] =  kw_idx;
    //\\
    //\\   data[2] =  ap;
    //\\
    //\\   return mktuple(B_keyword, 1, 2, data);
    //\\
    //\\ }
    //\\ int check(int Aval, int *table);
    //\\
    //\\ // variables used in line_reconstruction() moved here so they are available to semantic code in grammar.
    //\\ int saved = TRUE;
    //\\
    //\\ int at_startofline = TRUE;
    //\\
    //\\ };

    //\\ # top-level statement

    //\\ P<identifier> =
    //\\    <!keyword-not-allowed-in-context-of-an-identifier> <internal-identifier>;

    case P_identifier:
      T[1] = -1; // <!keyword-not-allowed-in-context-of-an-identifier>
      T[2] = bip(AST_internal_identifier, A[ap+1]);
      return mktuple(AST_identifier, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ # want to use keyword[] array from parser.h, but this will have to do for now
    //\\ # until I can work out a clean mechanism using <immediate:...>

    //\\ P<keyword-not-allowed-in-context-of-an-identifier> =
    //\\    "if",
    //\\    "const",
    //\\    "struct",
    //\\    "union",
    //\\    "sizeof",
    //\\    "typeof",
    //\\    "double",
    //\\    "long",
    //\\    "char",
    //\\    "float",
    //\\    "void",
    //\\    "enum",
    //\\    "short",
    //\\    "int",
    //\\    "signed",
    //\\    "unsigned",
    //\\    "volatile",
    //\\    "auto",
    //\\    "register",
    //\\    "static",
    //\\    "extern",
    //\\    "goto",
    //\\    "continue",
    //\\    "break",
    //\\    "return",
    //\\    "while",
    //\\    "do",
    //\\    "for",
    //\\    "switch",
    //\\    "else",
    //\\    "case",
    //\\    "default",
    //\\    "typedef";

    case P_keyword_not_allowed_in_context_of_an_identifier:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_if, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = kw(AST__KW, KW_const, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = kw(AST__KW, KW_struct, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 3) {
        T[1] = kw(AST__KW, KW_union, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 4) {
        T[1] = kw(AST__KW, KW_sizeof, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 5) {
        T[1] = kw(AST__KW, KW_typeof, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 6) {
        T[1] = kw(AST__KW, KW_double, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*6*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 7) {
        T[1] = kw(AST__KW, KW_long, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*7*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 8) {
        T[1] = kw(AST__KW, KW_char, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*8*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 9) {
        T[1] = kw(AST__KW, KW_float, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*9*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 10) {
        T[1] = kw(AST__KW, KW_void, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*10*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 11) {
        T[1] = kw(AST__KW, KW_enum, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*11*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 12) {
        T[1] = kw(AST__KW, KW_short, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*12*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 13) {
        T[1] = kw(AST__KW, KW_int, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*13*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 14) {
        T[1] = kw(AST__KW, KW_signed, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*14*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 15) {
        T[1] = kw(AST__KW, KW_unsigned, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*15*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 16) {
        T[1] = kw(AST__KW, KW_volatile, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*16*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 17) {
        T[1] = kw(AST__KW, KW_auto, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*17*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 18) {
        T[1] = kw(AST__KW, KW_register, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*18*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 19) {
        T[1] = kw(AST__KW, KW_static, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*19*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 20) {
        T[1] = kw(AST__KW, KW_extern, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*20*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 21) {
        T[1] = kw(AST__KW, KW_goto, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*21*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 22) {
        T[1] = kw(AST__KW, KW_continue, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*22*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 23) {
        T[1] = kw(AST__KW, KW_break, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*23*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 24) {
        T[1] = kw(AST__KW, KW_return, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*24*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 25) {
        T[1] = kw(AST__KW, KW_while, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*25*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 26) {
        T[1] = kw(AST__KW, KW_do, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*26*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 27) {
        T[1] = kw(AST__KW, KW_for, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*27*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 28) {
        T[1] = kw(AST__KW, KW_switch, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*28*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 29) {
        T[1] = kw(AST__KW, KW_else, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*29*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 30) {
        T[1] = kw(AST__KW, KW_case, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*30*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 31) {
        T[1] = kw(AST__KW, KW_default, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*31*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = kw(AST__KW, KW_typedef, A[ap+0]);
        T[0] = mktuple(AST_keyword_not_allowed_in_context_of_an_identifier, alt /*32*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<ignored> =
    //\\    <immediate:return FALSE;> ';';

    case P_ignored:
      T[1] = -1; // successful semantic call
      T[2] = lit(AST__LIT, ';', A[ap+1]);
      return mktuple(AST_ignored, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<SS> =
    //\\    <opt-external-declaration-list>;

    case P_SS:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-external-declaration-list>
      return mktuple(AST_SS, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

    //\\ P<opt-external-declaration-list> =
    //\\    <external-declaration> <opt-external-declaration-list>,
    //\\    <EOF>;

    case P_opt_external_declaration_list:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <external-declaration>
        T[2] = build_ast(A[ap+1], depth+1); // <opt-external-declaration-list>
        T[0] = mktuple(AST_opt_external_declaration_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = bip(AST_EOF, A[ap+0]);
        T[0] = mktuple(AST_opt_external_declaration_list, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<external-declaration> =
    //\\    <typedef-declaration> ';',
    //\\    <proc-fn-decl>,
    //\\    <possibly-initialised-scalar-or-array-decl>,
    //\\    <enum-specifier>,
    //\\    <struct-or-union-specifier>,
    //\\    ';';

    case P_external_declaration:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <typedef-declaration>
        T[2] = lit(AST__LIT, ';', A[ap+1]);
        T[0] = mktuple(AST_external_declaration, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <proc-fn-decl>
        T[0] = mktuple(AST_external_declaration, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = build_ast(A[ap+0], depth+1); // <possibly-initialised-scalar-or-array-decl>
        T[0] = mktuple(AST_external_declaration, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 3) {
        T[1] = build_ast(A[ap+0], depth+1); // <enum-specifier>
        T[0] = mktuple(AST_external_declaration, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 4) {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-or-union-specifier>
        T[0] = mktuple(AST_external_declaration, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit(AST__LIT, ';', A[ap+0]);
        T[0] = mktuple(AST_external_declaration, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ # Oops - these can be initialised.  Not yet done so.
    //\\ #

    //\\ P<struct-or-union-specifier> =
    //\\    <struct-or-union> <identifier> '{' <struct-field-declarations> '}',
    //\\    <struct-or-union> '{' <struct-field-declarations> '}',
    //\\    <struct-or-union> <identifier>;

    case P_struct_or_union_specifier:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-or-union>
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[3] = lit(AST__LIT, '{', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <struct-field-declarations>
        T[5] = lit(AST__LIT, '}', A[ap+4]);
        T[0] = mktuple(AST_struct_or_union_specifier, alt /*0*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-or-union>
        T[2] = lit(AST__LIT, '{', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <struct-field-declarations>
        T[4] = lit(AST__LIT, '}', A[ap+3]);
        T[0] = mktuple(AST_struct_or_union_specifier, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-or-union>
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[0] = mktuple(AST_struct_or_union_specifier, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      }
      return T[0];

    //\\ P<struct-or-union> =
    //\\    "struct",
    //\\    "union";

    case P_struct_or_union:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_struct, A[ap+0]);
        T[0] = mktuple(AST_struct_or_union, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = kw(AST__KW, KW_union, A[ap+0]);
        T[0] = mktuple(AST_struct_or_union, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<struct-field-declarations> =
    //\\    <struct-field-declaration> <rest-of-struct-field-declarations>;

    case P_struct_field_declarations:
      T[1] = build_ast(A[ap+0], depth+1); // <struct-field-declaration>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-struct-field-declarations>
      return mktuple(AST_struct_field_declarations, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-struct-field-declarations> =
    //\\    <struct-field-declaration> <rest-of-struct-field-declarations>,
    //\\   ;

    case P_rest_of_struct_field_declarations:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-field-declaration>
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-struct-field-declarations>
        T[0] = mktuple(AST_rest_of_struct_field_declarations, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_struct_field_declarations, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<struct-field-declaration> =
    //\\    <possibly-initialised-scalar-or-array-decl>;

    case P_struct_field_declaration:
      T[1] = build_ast(A[ap+0], depth+1); // <possibly-initialised-scalar-or-array-decl>
      return mktuple(AST_struct_field_declaration, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

    //\\ # I originally thought you could only initialise an array after a declaration
    //\\ # that had '[]' in it.  But not the case - a typedef'd declaration may have
    //\\ # the array part in the typedef rather than the instance.  Ugly language.
    //\\ #
    //\\ # Also we can have initialised structs :-/
    //\\ #

    //\\ P<possibly-initialised-scalar-or-array-decl> =
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <type> <rest-of-scalar-or-array-decl> ';';

    case P_possibly_initialised_scalar_or_array_decl:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-auto-reg-static-ext>
      T[2] = build_ast(A[ap+1], depth+1); // <opt-const-or-volatile-type-qualifier>
      T[3] = build_ast(A[ap+2], depth+1); // <type>
      T[4] = build_ast(A[ap+3], depth+1); // <rest-of-scalar-or-array-decl>
      T[5] = lit(AST__LIT, ';', A[ap+4]);
      return mktuple(AST_possibly_initialised_scalar_or_array_decl, alt /*0*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);

    //\\ # The <opt-scalar-init> part of function pointers is usually going to be "= &procname"... any other type of scalar is dubious...

    //\\ P<rest-of-scalar-or-array-decl> =
    //\\    <opt-indirection-decl> <identifier> <array-bounds> <opt-array-init> <opt-rest-of-scalar-or-array-decl>,
    //\\    <opt-indirection-decl> '(' <opt-indirection-decl> <identifier> ')' '(' <opt-param-list> ')' <opt-scalar-init> <opt-rest-of-scalar-or-array-decl>,
    //\\    <opt-indirection-decl> <identifier> <opt-scalar-init> <opt-rest-of-scalar-or-array-decl>;

    case P_rest_of_scalar_or_array_decl:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-indirection-decl>
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[3] = build_ast(A[ap+2], depth+1); // <array-bounds>
        T[4] = build_ast(A[ap+3], depth+1); // <opt-array-init>
        T[5] = build_ast(A[ap+4], depth+1); // <opt-rest-of-scalar-or-array-decl>
        T[0] = mktuple(AST_rest_of_scalar_or_array_decl, alt /*0*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-indirection-decl>
        T[2] = lit(AST__LIT, '(', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <opt-indirection-decl>
        T[4] = build_ast(A[ap+3], depth+1); // <identifier>
        T[5] = lit(AST__LIT, ')', A[ap+4]);
        T[6] = lit(AST__LIT, '(', A[ap+5]);
        T[7] = build_ast(A[ap+6], depth+1); // <opt-param-list>
        T[8] = lit(AST__LIT, ')', A[ap+7]);
        T[9] = build_ast(A[ap+8], depth+1); // <opt-scalar-init>
        T[10] = build_ast(A[ap+9], depth+1); // <opt-rest-of-scalar-or-array-decl>
        T[0] = mktuple(AST_rest_of_scalar_or_array_decl, alt /*1*/, /*phrases*/ 10, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-indirection-decl>
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[3] = build_ast(A[ap+2], depth+1); // <opt-scalar-init>
        T[4] = build_ast(A[ap+3], depth+1); // <opt-rest-of-scalar-or-array-decl>
        T[0] = mktuple(AST_rest_of_scalar_or_array_decl, alt /*2*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      }
      return T[0];

    //\\ P<opt-rest-of-scalar-or-array-decl> =
    //\\    ',' <rest-of-scalar-or-array-decl>,
    //\\   ;

    case P_opt_rest_of_scalar_or_array_decl:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-scalar-or-array-decl>
        T[0] = mktuple(AST_opt_rest_of_scalar_or_array_decl, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_opt_rest_of_scalar_or_array_decl, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<opt-scalar-init> =
    //\\    '=' <assignment-expression>,
    //\\   ;

    case P_opt_scalar_init:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '=', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <assignment-expression>
        T[0] = mktuple(AST_opt_scalar_init, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_opt_scalar_init, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<assignment-expression> =
    //\\    <opt-lvalue-assign> <conditional-expression> <opt-rest-of-assignment-expression>;

    case P_assignment_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-lvalue-assign>
      T[2] = build_ast(A[ap+1], depth+1); // <conditional-expression>
      T[3] = build_ast(A[ap+2], depth+1); // <opt-rest-of-assignment-expression>
      return mktuple(AST_assignment_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);

    //\\ P<opt-rest-of-assignment-expression> =
    //\\    <assignment-operator> <conditional-expression> <opt-rest-of-assignment-expression>,
    //\\   ;

    case P_opt_rest_of_assignment_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <assignment-operator>
        T[2] = build_ast(A[ap+1], depth+1); // <conditional-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <opt-rest-of-assignment-expression>
        T[0] = mktuple(AST_opt_rest_of_assignment_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_opt_rest_of_assignment_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<conditional-expression> =
    //\\    <logical-or-expression> <rest-of-conditional-expression>;

    case P_conditional_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <logical-or-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-conditional-expression>
      return mktuple(AST_conditional_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-conditional-expression> =
    //\\    '?' <expression> ':' <conditional-expression>,
    //\\   ;

    case P_rest_of_conditional_expression:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '?', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <expression>
        T[3] = lit(AST__LIT, ':', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <conditional-expression>
        T[0] = mktuple(AST_rest_of_conditional_expression, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_conditional_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<expression> =
    //\\    <comma-statement>;

    case P_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <comma-statement>
      return mktuple(AST_expression, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

    //\\ P<comma-statement> =
    //\\    <assignment-expression> <rest-of-comma-statement>;

    case P_comma_statement:
      T[1] = build_ast(A[ap+0], depth+1); // <assignment-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-comma-statement>
      return mktuple(AST_comma_statement, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-comma-statement> =
    //\\    ',' <assignment-expression> <rest-of-comma-statement>,
    //\\   ;

    case P_rest_of_comma_statement:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <assignment-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-comma-statement>
        T[0] = mktuple(AST_rest_of_comma_statement, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_comma_statement, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<logical-or-expression> =
    //\\    <logical-and-expression> <rest-of-logical-or-expression>;

    case P_logical_or_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <logical-and-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-logical-or-expression>
      return mktuple(AST_logical_or_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-logical-or-expression> =
    //\\    <oror> <logical-and-expression> <rest-of-logical-or-expression>,
    //\\   ;

    case P_rest_of_logical_or_expression:
      if (alt == 0)        {
        T[1] = bip(AST_oror, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <logical-and-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-logical-or-expression>
        T[0] = mktuple(AST_rest_of_logical_or_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_logical_or_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<logical-and-expression> =
    //\\    <inclusive-or-expression> <rest-of-logical-and-expression>;

    case P_logical_and_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <inclusive-or-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-logical-and-expression>
      return mktuple(AST_logical_and_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-logical-and-expression> =
    //\\    <andand> <inclusive-or-expression> <rest-of-logical-and-expression>,
    //\\   ;

    case P_rest_of_logical_and_expression:
      if (alt == 0)        {
        T[1] = bip(AST_andand, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <inclusive-or-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-logical-and-expression>
        T[0] = mktuple(AST_rest_of_logical_and_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_logical_and_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<inclusive-or-expression> =
    //\\    <exclusive-or-expression> <rest-of-inclusive-or-expression>;

    case P_inclusive_or_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <exclusive-or-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-inclusive-or-expression>
      return mktuple(AST_inclusive_or_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-inclusive-or-expression> =
    //\\    '|' <exclusive-or-expression> <rest-of-inclusive-or-expression>,
    //\\   ;

    case P_rest_of_inclusive_or_expression:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '|', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <exclusive-or-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-inclusive-or-expression>
        T[0] = mktuple(AST_rest_of_inclusive_or_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_inclusive_or_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<exclusive-or-expression> =
    //\\    <bitwise-and-expression> <rest-of-exclusive-or-expression>;

    case P_exclusive_or_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <bitwise-and-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-exclusive-or-expression>
      return mktuple(AST_exclusive_or_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-exclusive-or-expression> =
    //\\    '^' <bitwise-and-expression> <rest-of-exclusive-or-expression>,
    //\\   ;

    case P_rest_of_exclusive_or_expression:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '^', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <bitwise-and-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-exclusive-or-expression>
        T[0] = mktuple(AST_rest_of_exclusive_or_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_exclusive_or_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<bitwise-and-expression> =
    //\\    <equality-expression> <rest-of-bitwise-and-expression>;

    case P_bitwise_and_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <equality-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-bitwise-and-expression>
      return mktuple(AST_bitwise_and_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-bitwise-and-expression> =
    //\\    '&' <equality-expression> <rest-of-bitwise-and-expression>,
    //\\   ;

    case P_rest_of_bitwise_and_expression:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '&', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <equality-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-bitwise-and-expression>
        T[0] = mktuple(AST_rest_of_bitwise_and_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_bitwise_and_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<equality-expression> =
    //\\    <relational-expression> <rest-of-equality-expression>;

    case P_equality_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <relational-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-equality-expression>
      return mktuple(AST_equality_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-equality-expression> =
    //\\    <eqop> <relational-expression> <rest-of-equality-expression>,
    //\\   ;

    case P_rest_of_equality_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <eqop>
        T[2] = build_ast(A[ap+1], depth+1); // <relational-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-equality-expression>
        T[0] = mktuple(AST_rest_of_equality_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_equality_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<relational-expression> =
    //\\    <shift-expression> <rest-of-relational-expression>;

    case P_relational_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <shift-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-relational-expression>
      return mktuple(AST_relational_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-relational-expression> =
    //\\    <relop> <shift-expression> <rest-of-relational-expression>,
    //\\   ;

    case P_rest_of_relational_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <relop>
        T[2] = build_ast(A[ap+1], depth+1); // <shift-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-relational-expression>
        T[0] = mktuple(AST_rest_of_relational_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_relational_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<shift-expression> =
    //\\    <additive-expression> <rest-of-shift-expression>;

    case P_shift_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <additive-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-shift-expression>
      return mktuple(AST_shift_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-shift-expression> =
    //\\    <shiftop> <additive-expression> <rest-of-shift-expression>,
    //\\   ;

    case P_rest_of_shift_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <shiftop>
        T[2] = build_ast(A[ap+1], depth+1); // <additive-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-shift-expression>
        T[0] = mktuple(AST_rest_of_shift_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_shift_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<additive-expression> =
    //\\    <multiplicative-expression> <rest-of-additive-expression>;

    case P_additive_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <multiplicative-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-additive-expression>
      return mktuple(AST_additive_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-additive-expression> =
    //\\    <plusminus> <multiplicative-expression> <rest-of-additive-expression>,
    //\\   ;

    case P_rest_of_additive_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <plusminus>
        T[2] = build_ast(A[ap+1], depth+1); // <multiplicative-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-additive-expression>
        T[0] = mktuple(AST_rest_of_additive_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_additive_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<multiplicative-expression> =
    //\\    <unary-rvalue-expression> <rest-of-multiplicative-expression>;

    case P_multiplicative_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <unary-rvalue-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-multiplicative-expression>
      return mktuple(AST_multiplicative_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-multiplicative-expression> =
    //\\    <mulop> <unary-rvalue-expression> <rest-of-multiplicative-expression>,
    //\\   ;

    case P_rest_of_multiplicative_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <mulop>
        T[2] = build_ast(A[ap+1], depth+1); // <unary-rvalue-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-multiplicative-expression>
        T[0] = mktuple(AST_rest_of_multiplicative_expression, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_multiplicative_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ # my reading of the spec is that "sizeof" <type-specifier> is valid but "sizeof" '(' <type-specifier> ')' is not,
    //\\ # however the latter appears to be accepted by gcc.
    //\\ # Should we merge <type-specifier> with <opt-indirection-unary-ops>? Is <type-specifier> ever used without an optional '*' following?

    //\\ P<unary-rvalue-expression> =
    //\\    <arithmetic-unary-op> <optionally-cast-unary-rvalue-expression>,
    //\\    <boolean-unary-ops> <optionally-cast-unary-rvalue-expression>,
    //\\    <bitwise-unary-ops> <optionally-cast-unary-rvalue-expression>,
    //\\    <indirection-unary-ops> <unary-address-expression>,
    //\\    "sizeof" <unary-rvalue-expression>,
    //\\    "sizeof" <unary-lvalue-expression>,
    //\\    "sizeof" <type-specifier> <opt-indirection-unary-ops>,
    //\\    "sizeof" '(' <type-specifier> <opt-indirection-unary-ops> ')',
    //\\    <optionally-cast-postfix-rvalue-expression>;

    case P_unary_rvalue_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <arithmetic-unary-op>
        T[2] = build_ast(A[ap+1], depth+1); // <optionally-cast-unary-rvalue-expression>
        T[0] = mktuple(AST_unary_rvalue_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <boolean-unary-ops>
        T[2] = build_ast(A[ap+1], depth+1); // <optionally-cast-unary-rvalue-expression>
        T[0] = mktuple(AST_unary_rvalue_expression, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 2) {
        T[1] = build_ast(A[ap+0], depth+1); // <bitwise-unary-ops>
        T[2] = build_ast(A[ap+1], depth+1); // <optionally-cast-unary-rvalue-expression>
        T[0] = mktuple(AST_unary_rvalue_expression, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 3) {
        T[1] = build_ast(A[ap+0], depth+1); // <indirection-unary-ops>
        T[2] = build_ast(A[ap+1], depth+1); // <unary-address-expression>
        T[0] = mktuple(AST_unary_rvalue_expression, alt /*3*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 4) {
        T[1] = kw(AST__KW, KW_sizeof, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <unary-rvalue-expression>
        T[0] = mktuple(AST_unary_rvalue_expression, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 5) {
        T[1] = kw(AST__KW, KW_sizeof, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <unary-lvalue-expression>
        T[0] = mktuple(AST_unary_rvalue_expression, alt /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 6) {
        T[1] = kw(AST__KW, KW_sizeof, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <type-specifier>
        T[3] = build_ast(A[ap+2], depth+1); // <opt-indirection-unary-ops>
        T[0] = mktuple(AST_unary_rvalue_expression, alt /*6*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 7) {
        T[1] = kw(AST__KW, KW_sizeof, A[ap+0]);
        T[2] = lit(AST__LIT, '(', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <type-specifier>
        T[4] = build_ast(A[ap+3], depth+1); // <opt-indirection-unary-ops>
        T[5] = lit(AST__LIT, ')', A[ap+4]);
        T[0] = mktuple(AST_unary_rvalue_expression, alt /*7*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <optionally-cast-postfix-rvalue-expression>
        T[0] = mktuple(AST_unary_rvalue_expression, alt /*8*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<optionally-cast-postfix-rvalue-expression> =
    //\\    <cast> <optionally-cast-postfix-rvalue-expression>,
    //\\    <postfix-rvalue-expression>;

    case P_optionally_cast_postfix_rvalue_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <cast>
        T[2] = build_ast(A[ap+1], depth+1); // <optionally-cast-postfix-rvalue-expression>
        T[0] = mktuple(AST_optionally_cast_postfix_rvalue_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <postfix-rvalue-expression>
        T[0] = mktuple(AST_optionally_cast_postfix_rvalue_expression, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<postfix-rvalue-expression> =
    //\\    <primary-expression> <rest-of-postfix-rvalue-expression>,
    //\\    <unary-lvalue-expression> <rest-of-postfix-rvalue-expression>;

    case P_postfix_rvalue_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <primary-expression>
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(AST_postfix_rvalue_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <unary-lvalue-expression>
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(AST_postfix_rvalue_expression, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      }
      return T[0];

    //\\ P<rest-of-postfix-rvalue-expression> =
    //\\    '[' <expression> ']' <rest-of-postfix-rvalue-expression>,
    //\\    '(' <actual-param-list> ')' <rest-of-postfix-rvalue-expression>,
    //\\    '.' <identifier> <rest-of-postfix-rvalue-expression>,
    //\\    '-' '>' <identifier> <rest-of-postfix-rvalue-expression>,
    //\\    <post-increment-op> <rest-of-postfix-rvalue-expression>,
    //\\   ;

    case P_rest_of_postfix_rvalue_expression:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '[', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <expression>
        T[3] = lit(AST__LIT, ']', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(AST_rest_of_postfix_rvalue_expression, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, '(', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <actual-param-list>
        T[3] = lit(AST__LIT, ')', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(AST_rest_of_postfix_rvalue_expression, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 2) {
        T[1] = lit(AST__LIT, '.', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(AST_rest_of_postfix_rvalue_expression, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 3) {
        T[1] = lit(AST__LIT, '-', A[ap+0]);
        T[2] = lit(AST__LIT, '>', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <identifier>
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(AST_rest_of_postfix_rvalue_expression, alt /*3*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 4) {
        T[1] = build_ast(A[ap+0], depth+1); // <post-increment-op>
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(AST_rest_of_postfix_rvalue_expression, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_postfix_rvalue_expression, alt /*5*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<post-increment-op> =
    //\\    <pp>,
    //\\    <mm>;

    case P_post_increment_op:
      if (alt == 0)        {
        T[1] = bip(AST_pp, A[ap+0]);
        T[0] = mktuple(AST_post_increment_op, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = bip(AST_mm, A[ap+0]);
        T[0] = mktuple(AST_post_increment_op, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<actual-param-list> =
    //\\    <assignment-expression> <rest-of-param-list>,
    //\\   ;

    case P_actual_param_list:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <assignment-expression>
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-param-list>
        T[0] = mktuple(AST_actual_param_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_actual_param_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<rest-of-param-list> =
    //\\    ',' <assignment-expression> <rest-of-param-list>,
    //\\   ;

    case P_rest_of_param_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <assignment-expression>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-param-list>
        T[0] = mktuple(AST_rest_of_param_list, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_param_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<unary-lvalue-expression> =
    //\\    <pre-increment-op> <unary-lvalue-expression>,
    //\\    <indirection-unary-ops> <optionally-cast-unary-lvalue-expression>,
    //\\    <unary-address-expression>,
    //\\    <postfix-lvalue-expression>;

    case P_unary_lvalue_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <pre-increment-op>
        T[2] = build_ast(A[ap+1], depth+1); // <unary-lvalue-expression>
        T[0] = mktuple(AST_unary_lvalue_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <indirection-unary-ops>
        T[2] = build_ast(A[ap+1], depth+1); // <optionally-cast-unary-lvalue-expression>
        T[0] = mktuple(AST_unary_lvalue_expression, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 2) {
        T[1] = build_ast(A[ap+0], depth+1); // <unary-address-expression>
        T[0] = mktuple(AST_unary_lvalue_expression, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <postfix-lvalue-expression>
        T[0] = mktuple(AST_unary_lvalue_expression, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<postfix-lvalue-expression> =
    //\\    <primary-expression> <rest-of-postfix-expression>;

    case P_postfix_lvalue_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <primary-expression>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-expression>
      return mktuple(AST_postfix_lvalue_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-postfix-expression> =
    //\\    '[' <expression> ']' <rest-of-postfix-expression>,
    //\\    '(' <actual-param-list> ')' <non-empty-rest-of-postfix-expression>,
    //\\    '.' <identifier> <rest-of-postfix-expression>,
    //\\    '-' '>' <identifier> <rest-of-postfix-expression>,
    //\\    <post-increment-op> <rest-of-postfix-expression>,
    //\\   ;

    case P_rest_of_postfix_expression:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '[', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <expression>
        T[3] = lit(AST__LIT, ']', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(AST_rest_of_postfix_expression, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, '(', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <actual-param-list>
        T[3] = lit(AST__LIT, ')', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <non-empty-rest-of-postfix-expression>
        T[0] = mktuple(AST_rest_of_postfix_expression, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 2) {
        T[1] = lit(AST__LIT, '.', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(AST_rest_of_postfix_expression, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 3) {
        T[1] = lit(AST__LIT, '-', A[ap+0]);
        T[2] = lit(AST__LIT, '>', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <identifier>
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(AST_rest_of_postfix_expression, alt /*3*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 4) {
        T[1] = build_ast(A[ap+0], depth+1); // <post-increment-op>
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(AST_rest_of_postfix_expression, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_postfix_expression, alt /*5*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<non-empty-rest-of-postfix-expression> =
    //\\    '[' <expression> ']' <rest-of-postfix-expression>,
    //\\    '(' <actual-param-list> ')' <non-empty-rest-of-postfix-expression>,
    //\\    '.' <identifier> <rest-of-postfix-expression>,
    //\\    '-' '>' <identifier> <rest-of-postfix-expression>,
    //\\    <post-increment-op> <rest-of-postfix-expression>;

    case P_non_empty_rest_of_postfix_expression:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '[', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <expression>
        T[3] = lit(AST__LIT, ']', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(AST_non_empty_rest_of_postfix_expression, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, '(', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <actual-param-list>
        T[3] = lit(AST__LIT, ')', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <non-empty-rest-of-postfix-expression>
        T[0] = mktuple(AST_non_empty_rest_of_postfix_expression, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 2) {
        T[1] = lit(AST__LIT, '.', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(AST_non_empty_rest_of_postfix_expression, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 3) {
        T[1] = lit(AST__LIT, '-', A[ap+0]);
        T[2] = lit(AST__LIT, '>', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <identifier>
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(AST_non_empty_rest_of_postfix_expression, alt /*3*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <post-increment-op>
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(AST_non_empty_rest_of_postfix_expression, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      }
      return T[0];

    //\\ P<primary-expression> =
    //\\    <identifier>,
    //\\    <constant>,
    //\\    <dqstring>,
    //\\    '(' <expression> ')';

    case P_primary_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <identifier>
        T[0] = mktuple(AST_primary_expression, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <constant>
        T[0] = mktuple(AST_primary_expression, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = bip(AST_dqstring, A[ap+0]);
        T[0] = mktuple(AST_primary_expression, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit(AST__LIT, '(', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <expression>
        T[3] = lit(AST__LIT, ')', A[ap+2]);
        T[0] = mktuple(AST_primary_expression, alt /*3*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      }
      return T[0];

    //\\ P<constant> =
    //\\    <integer-constant>,
    //\\    <sqstring>,
    //\\    <floating-constant>,
    //\\    <enumeration-constant>;

    case P_constant:
      if (alt == 0)        {
        T[1] = bip(AST_integer_constant, A[ap+0]);
        T[0] = mktuple(AST_constant, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = bip(AST_sqstring, A[ap+0]);
        T[0] = mktuple(AST_constant, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = bip(AST_floating_constant, A[ap+0]);
        T[0] = mktuple(AST_constant, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <enumeration-constant>
        T[0] = mktuple(AST_constant, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<enumeration-constant> =
    //\\    <identifier>;

    case P_enumeration_constant:
      T[1] = build_ast(A[ap+0], depth+1); // <identifier>
      return mktuple(AST_enumeration_constant, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

    //\\ P<unary-address-expression> =
    //\\    <address-operator> <optionally-cast-unary-lvalue-expression>;

    case P_unary_address_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <address-operator>
      T[2] = build_ast(A[ap+1], depth+1); // <optionally-cast-unary-lvalue-expression>
      return mktuple(AST_unary_address_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<optionally-cast-unary-lvalue-expression> =
    //\\    <cast> <optionally-cast-unary-lvalue-expression>,
    //\\    <unary-lvalue-expression>;

    case P_optionally_cast_unary_lvalue_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <cast>
        T[2] = build_ast(A[ap+1], depth+1); // <optionally-cast-unary-lvalue-expression>
        T[0] = mktuple(AST_optionally_cast_unary_lvalue_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <unary-lvalue-expression>
        T[0] = mktuple(AST_optionally_cast_unary_lvalue_expression, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<cast> =
    //\\    '(' <type-specifier> <opt-indirection-unary-ops> ')',
    //\\    '(' "typeof" '(' <unary-lvalue-expression> ')' ')',
    //\\    '(' "typeof" '(' <type-specifier> <opt-indirection-unary-ops> ')' ')';

    case P_cast:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '(', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <type-specifier>
        T[3] = build_ast(A[ap+2], depth+1); // <opt-indirection-unary-ops>
        T[4] = lit(AST__LIT, ')', A[ap+3]);
        T[0] = mktuple(AST_cast, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, '(', A[ap+0]);
        T[2] = kw(AST__KW, KW_typeof, A[ap+1]);
        T[3] = lit(AST__LIT, '(', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <unary-lvalue-expression>
        T[5] = lit(AST__LIT, ')', A[ap+4]);
        T[6] = lit(AST__LIT, ')', A[ap+5]);
        T[0] = mktuple(AST_cast, alt /*1*/, /*phrases*/ 6, T /*T[1], T[2], T[3], T[4], T[5], T[6]*/);
      } else               {
        T[1] = lit(AST__LIT, '(', A[ap+0]);
        T[2] = kw(AST__KW, KW_typeof, A[ap+1]);
        T[3] = lit(AST__LIT, '(', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <type-specifier>
        T[5] = build_ast(A[ap+4], depth+1); // <opt-indirection-unary-ops>
        T[6] = lit(AST__LIT, ')', A[ap+5]);
        T[7] = lit(AST__LIT, ')', A[ap+6]);
        T[0] = mktuple(AST_cast, alt /*2*/, /*phrases*/ 7, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7]*/);
      }
      return T[0];

    //\\ # <opt-indirection-decl> looks just like <opt-indirection-unary-ops> except that it only
    //\\ # happens in a declaration, not a data access.  The significant difference is that the '*'
    //\\ # can be preceded by a "const" (and maybe "volatile") keyword, eg "int const *fred" which
    //\\ # is a constant pointer to an int.
    //\\ #

    //\\ P<opt-indirection-decl> =
    //\\    <opt-const-or-volatile-type-qualifier> '*' <opt-indirection-decl>,
    //\\   ;

    case P_opt_indirection_decl:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-const-or-volatile-type-qualifier>
        T[2] = lit(AST__LIT, '*', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <opt-indirection-decl>
        T[0] = mktuple(AST_opt_indirection_decl, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_opt_indirection_decl, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<indirection-unary-ops> =
    //\\    '*' <opt-indirection-unary-ops>;

    case P_indirection_unary_ops:
      T[1] = lit(AST__LIT, '*', A[ap+0]);
      T[2] = build_ast(A[ap+1], depth+1); // <opt-indirection-unary-ops>
      return mktuple(AST_indirection_unary_ops, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<opt-indirection-unary-ops> =
    //\\    '*' <opt-indirection-unary-ops>,
    //\\   ;

    case P_opt_indirection_unary_ops:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '*', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <opt-indirection-unary-ops>
        T[0] = mktuple(AST_opt_indirection_unary_ops, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_opt_indirection_unary_ops, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<type-specifier> =
    //\\    <basic-type-specifier>,
    //\\    <typedef-name>;

    case P_type_specifier:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <basic-type-specifier>
        T[0] = mktuple(AST_type_specifier, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <typedef-name>
        T[0] = mktuple(AST_type_specifier, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<typedef-name> =
    //\\    <identifier>;

    case P_typedef_name:
      T[1] = build_ast(A[ap+0], depth+1); // <identifier>
      return mktuple(AST_typedef_name, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

    //\\ # I think struct or union or enum specifier below can be an actual declaration using '{}'s
    //\\ # rather than just a struct or enum name.
    //\\ #

    //\\ P<basic-type-specifier> =
    //\\    "double",
    //\\    "long" "double",
    //\\    <opt-signed> "char",
    //\\    <opt-signed-inttype>,
    //\\    "float",
    //\\    <struct-or-union-specifier>,
    //\\    <enum-specifier>,
    //\\    "void";

    case P_basic_type_specifier:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_double, A[ap+0]);
        T[0] = mktuple(AST_basic_type_specifier, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = kw(AST__KW, KW_long, A[ap+0]);
        T[2] = kw(AST__KW, KW_double, A[ap+1]);
        T[0] = mktuple(AST_basic_type_specifier, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 2) {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-signed>
        T[2] = kw(AST__KW, KW_char, A[ap+1]);
        T[0] = mktuple(AST_basic_type_specifier, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 3) {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-signed-inttype>
        T[0] = mktuple(AST_basic_type_specifier, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 4) {
        T[1] = kw(AST__KW, KW_float, A[ap+0]);
        T[0] = mktuple(AST_basic_type_specifier, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 5) {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-or-union-specifier>
        T[0] = mktuple(AST_basic_type_specifier, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 6) {
        T[1] = build_ast(A[ap+0], depth+1); // <enum-specifier>
        T[0] = mktuple(AST_basic_type_specifier, alt /*6*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = kw(AST__KW, KW_void, A[ap+0]);
        T[0] = mktuple(AST_basic_type_specifier, alt /*7*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<enum-specifier> =
    //\\    "enum" '{' <enumerator-list> '}',
    //\\    "enum" <identifier> '{' <enumerator-list> '}',
    //\\    "enum" <identifier>;

    case P_enum_specifier:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_enum, A[ap+0]);
        T[2] = lit(AST__LIT, '{', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <enumerator-list>
        T[4] = lit(AST__LIT, '}', A[ap+3]);
        T[0] = mktuple(AST_enum_specifier, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = kw(AST__KW, KW_enum, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[3] = lit(AST__LIT, '{', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <enumerator-list>
        T[5] = lit(AST__LIT, '}', A[ap+4]);
        T[0] = mktuple(AST_enum_specifier, alt /*1*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else               {
        T[1] = kw(AST__KW, KW_enum, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[0] = mktuple(AST_enum_specifier, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      }
      return T[0];

    //\\ P<enumerator-list> =
    //\\    <enumerator> <rest-of-enumerator-list>;

    case P_enumerator_list:
      T[1] = build_ast(A[ap+0], depth+1); // <enumerator>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-enumerator-list>
      return mktuple(AST_enumerator_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-enumerator-list> =
    //\\    ',' <enumerator> <rest-of-enumerator-list>,
    //\\    ',',
    //\\   ;

    case P_rest_of_enumerator_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <enumerator>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-enumerator-list>
        T[0] = mktuple(AST_rest_of_enumerator_list, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[0] = mktuple(AST_rest_of_enumerator_list, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_enumerator_list, alt /*2*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<enumerator> =
    //\\    <identifier> '=' <constant-expression>,
    //\\    <identifier>;

    case P_enumerator:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <identifier>
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <constant-expression>
        T[0] = mktuple(AST_enumerator, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <identifier>
        T[0] = mktuple(AST_enumerator, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<constant-expression> =
    //\\    <conditional-expression>;

    case P_constant_expression:
      T[1] = build_ast(A[ap+0], depth+1); // <conditional-expression>
      return mktuple(AST_constant_expression, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

    //\\ # does this omit "signed int"? - check, and add <opt-signed> "int" if needed...

    //\\ P<opt-signed-inttype> =
    //\\    <opt-signed> "short" <opt-int>,
    //\\    <opt-signed> "long" "long" <opt-int>,
    //\\    <opt-signed> "long" <opt-int>,
    //\\    <opt-signed> "int",
    //\\    "signed",
    //\\    "unsigned";

    case P_opt_signed_inttype:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-signed>
        T[2] = kw(AST__KW, KW_short, A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <opt-int>
        T[0] = mktuple(AST_opt_signed_inttype, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-signed>
        T[2] = kw(AST__KW, KW_long, A[ap+1]);
        T[3] = kw(AST__KW, KW_long, A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <opt-int>
        T[0] = mktuple(AST_opt_signed_inttype, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 2) {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-signed>
        T[2] = kw(AST__KW, KW_long, A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <opt-int>
        T[0] = mktuple(AST_opt_signed_inttype, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 3) {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-signed>
        T[2] = kw(AST__KW, KW_int, A[ap+1]);
        T[0] = mktuple(AST_opt_signed_inttype, alt /*3*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 4) {
        T[1] = kw(AST__KW, KW_signed, A[ap+0]);
        T[0] = mktuple(AST_opt_signed_inttype, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = kw(AST__KW, KW_unsigned, A[ap+0]);
        T[0] = mktuple(AST_opt_signed_inttype, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<opt-int> =
    //\\    "int",
    //\\   ;

    case P_opt_int:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_int, A[ap+0]);
        T[0] = mktuple(AST_opt_int, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_opt_int, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<opt-signed> =
    //\\    "signed",
    //\\    "unsigned",
    //\\   ;

    case P_opt_signed:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_signed, A[ap+0]);
        T[0] = mktuple(AST_opt_signed, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = kw(AST__KW, KW_unsigned, A[ap+0]);
        T[0] = mktuple(AST_opt_signed, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_opt_signed, alt /*2*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<address-operator> =
    //\\    '&';

    case P_address_operator:
      T[1] = lit(AST__LIT, '&', A[ap+0]);
      return mktuple(AST_address_operator, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

    //\\ P<pre-increment-op> =
    //\\    <pp>,
    //\\    <mm>;

    case P_pre_increment_op:
      if (alt == 0)        {
        T[1] = bip(AST_pp, A[ap+0]);
        T[0] = mktuple(AST_pre_increment_op, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = bip(AST_mm, A[ap+0]);
        T[0] = mktuple(AST_pre_increment_op, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<optionally-cast-unary-rvalue-expression> =
    //\\    <cast> <optionally-cast-unary-rvalue-expression>,
    //\\    <unary-rvalue-expression>;

    case P_optionally_cast_unary_rvalue_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <cast>
        T[2] = build_ast(A[ap+1], depth+1); // <optionally-cast-unary-rvalue-expression>
        T[0] = mktuple(AST_optionally_cast_unary_rvalue_expression, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <unary-rvalue-expression>
        T[0] = mktuple(AST_optionally_cast_unary_rvalue_expression, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<bitwise-unary-ops> =
    //\\    '~' <rest-of-bitwise-unary-ops>;

    case P_bitwise_unary_ops:
      T[1] = lit(AST__LIT, '~', A[ap+0]);
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-bitwise-unary-ops>
      return mktuple(AST_bitwise_unary_ops, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-bitwise-unary-ops> =
    //\\    '~' <rest-of-bitwise-unary-ops>,
    //\\   ;

    case P_rest_of_bitwise_unary_ops:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '~', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-bitwise-unary-ops>
        T[0] = mktuple(AST_rest_of_bitwise_unary_ops, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_bitwise_unary_ops, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<boolean-unary-ops> =
    //\\    '!' <rest-of-boolean-unary-ops>;

    case P_boolean_unary_ops:
      T[1] = lit(AST__LIT, '!', A[ap+0]);
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-boolean-unary-ops>
      return mktuple(AST_boolean_unary_ops, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-boolean-unary-ops> =
    //\\    '!' <rest-of-boolean-unary-ops>,
    //\\   ;

    case P_rest_of_boolean_unary_ops:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '!', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-boolean-unary-ops>
        T[0] = mktuple(AST_rest_of_boolean_unary_ops, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_boolean_unary_ops, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<arithmetic-unary-op> =
    //\\    '+',
    //\\    '-';

    case P_arithmetic_unary_op:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '+', A[ap+0]);
        T[0] = mktuple(AST_arithmetic_unary_op, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit(AST__LIT, '-', A[ap+0]);
        T[0] = mktuple(AST_arithmetic_unary_op, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<mulop> =
    //\\    '*',
    //\\    '/',
    //\\    '%';

    case P_mulop:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '*', A[ap+0]);
        T[0] = mktuple(AST_mulop, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, '/', A[ap+0]);
        T[0] = mktuple(AST_mulop, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit(AST__LIT, '%', A[ap+0]);
        T[0] = mktuple(AST_mulop, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<plusminus> =
    //\\    '+',
    //\\    '-';

    case P_plusminus:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '+', A[ap+0]);
        T[0] = mktuple(AST_plusminus, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit(AST__LIT, '-', A[ap+0]);
        T[0] = mktuple(AST_plusminus, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<shiftop> =
    //\\    '<' '<',
    //\\    '>' '>';

    case P_shiftop:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '<', A[ap+0]);
        T[2] = lit(AST__LIT, '<', A[ap+1]);
        T[0] = mktuple(AST_shiftop, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = lit(AST__LIT, '>', A[ap+0]);
        T[2] = lit(AST__LIT, '>', A[ap+1]);
        T[0] = mktuple(AST_shiftop, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      }
      return T[0];

    //\\ P<relop> =
    //\\    '<' '=',
    //\\    '<',
    //\\    '>' '=',
    //\\    '>';

    case P_relop:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '<', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_relop, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, '<', A[ap+0]);
        T[0] = mktuple(AST_relop, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = lit(AST__LIT, '>', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_relop, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = lit(AST__LIT, '>', A[ap+0]);
        T[0] = mktuple(AST_relop, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<eqop> =
    //\\    <eqeq>,
    //\\    '!' '=';

    case P_eqop:
      if (alt == 0)        {
        T[1] = bip(AST_eqeq, A[ap+0]);
        T[0] = mktuple(AST_eqop, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit(AST__LIT, '!', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_eqop, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      }
      return T[0];

    //\\ P<assignment-operator> =
    //\\    '=',
    //\\    '*' '=',
    //\\    '/' '=',
    //\\    '%' '=',
    //\\    '+' '=',
    //\\    '-' '=',
    //\\    '<' '<' '=',
    //\\    '>' '>' '=',
    //\\    '&' '=',
    //\\    '^' '=',
    //\\    '|' '=';

    case P_assignment_operator:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '=', A[ap+0]);
        T[0] = mktuple(AST_assignment_operator, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, '*', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_assignment_operator, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 2) {
        T[1] = lit(AST__LIT, '/', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_assignment_operator, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 3) {
        T[1] = lit(AST__LIT, '%', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_assignment_operator, alt /*3*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 4) {
        T[1] = lit(AST__LIT, '+', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_assignment_operator, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 5) {
        T[1] = lit(AST__LIT, '-', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_assignment_operator, alt /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 6) {
        T[1] = lit(AST__LIT, '<', A[ap+0]);
        T[2] = lit(AST__LIT, '<', A[ap+1]);
        T[3] = lit(AST__LIT, '=', A[ap+2]);
        T[0] = mktuple(AST_assignment_operator, alt /*6*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 7) {
        T[1] = lit(AST__LIT, '>', A[ap+0]);
        T[2] = lit(AST__LIT, '>', A[ap+1]);
        T[3] = lit(AST__LIT, '=', A[ap+2]);
        T[0] = mktuple(AST_assignment_operator, alt /*7*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 8) {
        T[1] = lit(AST__LIT, '&', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_assignment_operator, alt /*8*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 9) {
        T[1] = lit(AST__LIT, '^', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_assignment_operator, alt /*9*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = lit(AST__LIT, '|', A[ap+0]);
        T[2] = lit(AST__LIT, '=', A[ap+1]);
        T[0] = mktuple(AST_assignment_operator, alt /*10*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      }
      return T[0];

    //\\ P<opt-lvalue-assign> =
    //\\    <unary-lvalue-expression> <assignment-operator>,
    //\\   ;

    case P_opt_lvalue_assign:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <unary-lvalue-expression>
        T[2] = build_ast(A[ap+1], depth+1); // <assignment-operator>
        T[0] = mktuple(AST_opt_lvalue_assign, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_opt_lvalue_assign, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<opt-array-init> =
    //\\    '=' '{' <constant-initializer-list> '}',
    //\\    '=' <dqstring>,
    //\\   ;

    case P_opt_array_init:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '=', A[ap+0]);
        T[2] = lit(AST__LIT, '{', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <constant-initializer-list>
        T[4] = lit(AST__LIT, '}', A[ap+3]);
        T[0] = mktuple(AST_opt_array_init, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, '=', A[ap+0]);
        T[2] = bip(AST_dqstring, A[ap+1]);
        T[0] = mktuple(AST_opt_array_init, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_opt_array_init, alt /*2*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<constant-initializer-list> =
    //\\    <constant-initializer> <rest-of-constant-initializer-list>;

    case P_constant_initializer_list:
      T[1] = build_ast(A[ap+0], depth+1); // <constant-initializer>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-constant-initializer-list>
      return mktuple(AST_constant_initializer_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-constant-initializer-list> =
    //\\    ',' <constant-initializer> <rest-of-constant-initializer-list>,
    //\\    ',',
    //\\   ;

    case P_rest_of_constant_initializer_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <constant-initializer>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-constant-initializer-list>
        T[0] = mktuple(AST_rest_of_constant_initializer_list, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[0] = mktuple(AST_rest_of_constant_initializer_list, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_constant_initializer_list, alt /*2*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<constant-initializer> =
    //\\    <constant-expression>,
    //\\    '{' <constant-initializer-list> '}';

    case P_constant_initializer:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <constant-expression>
        T[0] = mktuple(AST_constant_initializer, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit(AST__LIT, '{', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <constant-initializer-list>
        T[3] = lit(AST__LIT, '}', A[ap+2]);
        T[0] = mktuple(AST_constant_initializer, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      }
      return T[0];

    //\\ P<array-bounds> =
    //\\    '[' <opt-constant-expression> ']' <opt-array-bounds>;

    case P_array_bounds:
      T[1] = lit(AST__LIT, '[', A[ap+0]);
      T[2] = build_ast(A[ap+1], depth+1); // <opt-constant-expression>
      T[3] = lit(AST__LIT, ']', A[ap+2]);
      T[4] = build_ast(A[ap+3], depth+1); // <opt-array-bounds>
      return mktuple(AST_array_bounds, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);

    //\\ P<opt-array-bounds> =
    //\\    '[' <opt-constant-expression> ']' <opt-array-bounds>,
    //\\   ;

    case P_opt_array_bounds:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '[', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <opt-constant-expression>
        T[3] = lit(AST__LIT, ']', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <opt-array-bounds>
        T[0] = mktuple(AST_opt_array_bounds, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[0] = mktuple(AST_opt_array_bounds, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<opt-constant-expression> =
    //\\    <constant-expression>,
    //\\   ;

    case P_opt_constant_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <constant-expression>
        T[0] = mktuple(AST_opt_constant_expression, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_opt_constant_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<type> =
    //\\    <enum-specifier>,
    //\\    <struct-or-union-specifier>,
    //\\    "typeof" '(' <unary-lvalue-expression> ')',
    //\\    "typeof" '(' <type-specifier> <opt-indirection-unary-ops> ')',
    //\\    <basic-type-specifier>,
    //\\    <typedef-name>,
    //\\    "void";

    case P_type:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <enum-specifier>
        T[0] = mktuple(AST_type, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-or-union-specifier>
        T[0] = mktuple(AST_type, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = kw(AST__KW, KW_typeof, A[ap+0]);
        T[2] = lit(AST__LIT, '(', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <unary-lvalue-expression>
        T[4] = lit(AST__LIT, ')', A[ap+3]);
        T[0] = mktuple(AST_type, alt /*2*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 3) {
        T[1] = kw(AST__KW, KW_typeof, A[ap+0]);
        T[2] = lit(AST__LIT, '(', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <type-specifier>
        T[4] = build_ast(A[ap+3], depth+1); // <opt-indirection-unary-ops>
        T[5] = lit(AST__LIT, ')', A[ap+4]);
        T[0] = mktuple(AST_type, alt /*3*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else if (alt == 4) {
        T[1] = build_ast(A[ap+0], depth+1); // <basic-type-specifier>
        T[0] = mktuple(AST_type, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 5) {
        T[1] = build_ast(A[ap+0], depth+1); // <typedef-name>
        T[0] = mktuple(AST_type, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = kw(AST__KW, KW_void, A[ap+0]);
        T[0] = mktuple(AST_type, alt /*6*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<opt-const-or-volatile-type-qualifier> =
    //\\    <const-or-volatile-type-qualifier>,
    //\\   ;

    case P_opt_const_or_volatile_type_qualifier:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <const-or-volatile-type-qualifier>
        T[0] = mktuple(AST_opt_const_or_volatile_type_qualifier, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_opt_const_or_volatile_type_qualifier, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<const-or-volatile-type-qualifier> =
    //\\    "const",
    //\\    "volatile";

    case P_const_or_volatile_type_qualifier:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_const, A[ap+0]);
        T[0] = mktuple(AST_const_or_volatile_type_qualifier, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = kw(AST__KW, KW_volatile, A[ap+0]);
        T[0] = mktuple(AST_const_or_volatile_type_qualifier, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<opt-auto-reg-static-ext> =
    //\\    "auto",
    //\\    "register",
    //\\    "static",
    //\\    "extern",
    //\\   ;

    case P_opt_auto_reg_static_ext:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_auto, A[ap+0]);
        T[0] = mktuple(AST_opt_auto_reg_static_ext, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = kw(AST__KW, KW_register, A[ap+0]);
        T[0] = mktuple(AST_opt_auto_reg_static_ext, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = kw(AST__KW, KW_static, A[ap+0]);
        T[0] = mktuple(AST_opt_auto_reg_static_ext, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 3) {
        T[1] = kw(AST__KW, KW_extern, A[ap+0]);
        T[0] = mktuple(AST_opt_auto_reg_static_ext, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_opt_auto_reg_static_ext, alt /*4*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<identifier-list> =
    //\\    <identifier> <rest-of-identifier-list>;

    case P_identifier_list:
      T[1] = build_ast(A[ap+0], depth+1); // <identifier>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-identifier-list>
      return mktuple(AST_identifier_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-identifier-list> =
    //\\    ',' <identifier-list>,
    //\\   ;

    case P_rest_of_identifier_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <identifier-list>
        T[0] = mktuple(AST_rest_of_identifier_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_identifier_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<more-forward-decls-or-actual-body> =
    //\\    <opt-extern-proc-name-and-params-list> ';',
    //\\    <compound-statement>;

    case P_more_forward_decls_or_actual_body:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-extern-proc-name-and-params-list>
        T[2] = lit(AST__LIT, ';', A[ap+1]);
        T[0] = mktuple(AST_more_forward_decls_or_actual_body, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <compound-statement>
        T[0] = mktuple(AST_more_forward_decls_or_actual_body, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<extern-proc-spec> =
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <opt-basic-type-specifier-or-typedef-name>;

    case P_extern_proc_spec:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-auto-reg-static-ext>
      T[2] = build_ast(A[ap+1], depth+1); // <opt-const-or-volatile-type-qualifier>
      T[3] = build_ast(A[ap+2], depth+1); // <opt-basic-type-specifier-or-typedef-name>
      return mktuple(AST_extern_proc_spec, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);

    //\\ P<opt-basic-type-specifier-or-typedef-name> =
    //\\    <opt-basic-type-specifier>,
    //\\    <typedef-name>;

    case P_opt_basic_type_specifier_or_typedef_name:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-basic-type-specifier>
        T[0] = mktuple(AST_opt_basic_type_specifier_or_typedef_name, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <typedef-name>
        T[0] = mktuple(AST_opt_basic_type_specifier_or_typedef_name, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<identifier-or-function-pointer> =
    //\\    '(' '*' <identifier> ')',
    //\\    <identifier>;

    case P_identifier_or_function_pointer:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '(', A[ap+0]);
        T[2] = lit(AST__LIT, '*', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <identifier>
        T[4] = lit(AST__LIT, ')', A[ap+3]);
        T[0] = mktuple(AST_identifier_or_function_pointer, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <identifier>
        T[0] = mktuple(AST_identifier_or_function_pointer, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<extern-proc-name-and-params> =
    //\\    <opt-indirection-decl> <identifier-or-function-pointer> '(' <opt-param-list> ')';

    case P_extern_proc_name_and_params:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-indirection-decl>
      T[2] = build_ast(A[ap+1], depth+1); // <identifier-or-function-pointer>
      T[3] = lit(AST__LIT, '(', A[ap+2]);
      T[4] = build_ast(A[ap+3], depth+1); // <opt-param-list>
      T[5] = lit(AST__LIT, ')', A[ap+4]);
      return mktuple(AST_extern_proc_name_and_params, alt /*0*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);

    //\\ P<opt-extern-proc-name-and-params-list> =
    //\\    ',' <extern-proc-name-and-params> <opt-extern-proc-name-and-params-list>,
    //\\   ;

    case P_opt_extern_proc_name_and_params_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <extern-proc-name-and-params>
        T[3] = build_ast(A[ap+2], depth+1); // <opt-extern-proc-name-and-params-list>
        T[0] = mktuple(AST_opt_extern_proc_name_and_params_list, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_opt_extern_proc_name_and_params_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<proc-fn-decl> =
    //\\    <extern-proc-spec> <extern-proc-name-and-params> <more-forward-decls-or-actual-body>,
    //\\    <extern-proc-spec> <opt-indirection-decl> <identifier> '(' <identifier-list> ')' <opt-oldstyle-param-list> ';' <compound-statement>;

    case P_proc_fn_decl:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <extern-proc-spec>
        T[2] = build_ast(A[ap+1], depth+1); // <extern-proc-name-and-params>
        T[3] = build_ast(A[ap+2], depth+1); // <more-forward-decls-or-actual-body>
        T[0] = mktuple(AST_proc_fn_decl, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <extern-proc-spec>
        T[2] = build_ast(A[ap+1], depth+1); // <opt-indirection-decl>
        T[3] = build_ast(A[ap+2], depth+1); // <identifier>
        T[4] = lit(AST__LIT, '(', A[ap+3]);
        T[5] = build_ast(A[ap+4], depth+1); // <identifier-list>
        T[6] = lit(AST__LIT, ')', A[ap+5]);
        T[7] = build_ast(A[ap+6], depth+1); // <opt-oldstyle-param-list>
        T[8] = lit(AST__LIT, ';', A[ap+7]);
        T[9] = build_ast(A[ap+8], depth+1); // <compound-statement>
        T[0] = mktuple(AST_proc_fn_decl, alt /*1*/, /*phrases*/ 9, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]*/);
      }
      return T[0];

    //\\ P<compound-statement> =
    //\\    '{' '}',
    //\\    '{' <statement-list> '}';

    case P_compound_statement:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '{', A[ap+0]);
        T[2] = lit(AST__LIT, '}', A[ap+1]);
        T[0] = mktuple(AST_compound_statement, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = lit(AST__LIT, '{', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <statement-list>
        T[3] = lit(AST__LIT, '}', A[ap+2]);
        T[0] = mktuple(AST_compound_statement, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      }
      return T[0];

    //\\ # Actually I don't think declarations inside a block are allowed
    //\\ # to be preceded by labels.
    //\\ # So the three lines below (which are in P<statement>) probably should
    //\\ # be separated out and put in <statement-list> below separately from the
    //\\ # options which can have <opt-labels> in front of them.
    //\\ #
    //\\ #   <extern-proc-spec> <extern-proc-name-and-params> <more-forward-decls-or-actual-body>,
    //\\ #   <in-proc-data-declaration>,
    //\\ #   <opt-external-declaration-list>;
    //\\ # Also still to add are label declarations (inside blocks):
    //\\ # P<label-declaration> =
    //\\ #    "__label__" <identifier-list> ';';
    //\\ # (I'm not sure if "label" as a keyword is valid too, or does it have to be #define'd as __label__ ?

    //\\ P<statement-list> =
    //\\    <opt-labels> <statement> <rest-of-statement-list>;

    case P_statement_list:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-labels>
      T[2] = build_ast(A[ap+1], depth+1); // <statement>
      T[3] = build_ast(A[ap+2], depth+1); // <rest-of-statement-list>
      return mktuple(AST_statement_list, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);

    //\\ P<rest-of-statement-list> =
    //\\    <opt-labels> <statement> <rest-of-statement-list>,
    //\\   ;

    case P_rest_of_statement_list:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-labels>
        T[2] = build_ast(A[ap+1], depth+1); // <statement>
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-statement-list>
        T[0] = mktuple(AST_rest_of_statement_list, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_statement_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ # added as a test: <extern-proc-spec> <extern-proc-name-and-params> <more-forward-decls-or-actual-body>,

    //\\ P<statement> =
    //\\    ';',
    //\\    <compound-statement>,
    //\\    <selection-statement>,
    //\\    <iteration-statement>,
    //\\    <jump-statement>,
    //\\    <expression> ';',
    //\\    <extern-proc-spec> <extern-proc-name-and-params> <more-forward-decls-or-actual-body>,
    //\\    <in-proc-data-declaration>,
    //\\    <opt-external-declaration-list>;

    case P_statement:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ';', A[ap+0]);
        T[0] = mktuple(AST_statement, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <compound-statement>
        T[0] = mktuple(AST_statement, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = build_ast(A[ap+0], depth+1); // <selection-statement>
        T[0] = mktuple(AST_statement, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 3) {
        T[1] = build_ast(A[ap+0], depth+1); // <iteration-statement>
        T[0] = mktuple(AST_statement, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 4) {
        T[1] = build_ast(A[ap+0], depth+1); // <jump-statement>
        T[0] = mktuple(AST_statement, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 5) {
        T[1] = build_ast(A[ap+0], depth+1); // <expression>
        T[2] = lit(AST__LIT, ';', A[ap+1]);
        T[0] = mktuple(AST_statement, alt /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 6) {
        T[1] = build_ast(A[ap+0], depth+1); // <extern-proc-spec>
        T[2] = build_ast(A[ap+1], depth+1); // <extern-proc-name-and-params>
        T[3] = build_ast(A[ap+2], depth+1); // <more-forward-decls-or-actual-body>
        T[0] = mktuple(AST_statement, alt /*6*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 7) {
        T[1] = build_ast(A[ap+0], depth+1); // <in-proc-data-declaration>
        T[0] = mktuple(AST_statement, alt /*7*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-external-declaration-list>
        T[0] = mktuple(AST_statement, alt /*8*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<in-proc-data-declaration> =
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <type> <decl-list>,
    //\\    <struct-decl>;

    case P_in_proc_data_declaration:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-auto-reg-static-ext>
        T[2] = build_ast(A[ap+1], depth+1); // <opt-const-or-volatile-type-qualifier>
        T[3] = build_ast(A[ap+2], depth+1); // <type>
        T[4] = build_ast(A[ap+3], depth+1); // <decl-list>
        T[0] = mktuple(AST_in_proc_data_declaration, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-decl>
        T[0] = mktuple(AST_in_proc_data_declaration, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<struct-decl> =
    //\\    "struct" <new-structname> '{' <struct-member-list> '}';

    case P_struct_decl:
      T[1] = kw(AST__KW, KW_struct, A[ap+0]);
      T[2] = build_ast(A[ap+1], depth+1); // <new-structname>
      T[3] = lit(AST__LIT, '{', A[ap+2]);
      T[4] = build_ast(A[ap+3], depth+1); // <struct-member-list>
      T[5] = lit(AST__LIT, '}', A[ap+4]);
      return mktuple(AST_struct_decl, alt /*0*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);

    //\\ P<struct-member-list> =
    //\\    <struct-member-declaration> <struct-member-list>,
    //\\   ;

    case P_struct_member_list:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-member-declaration>
        T[2] = build_ast(A[ap+1], depth+1); // <struct-member-list>
        T[0] = mktuple(AST_struct_member_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_struct_member_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<struct-member-declaration> =
    //\\    <struct-decl>,
    //\\    <possibly-initialised-scalar-decl>,
    //\\    <possibly-initialised-array-decl>;

    case P_struct_member_declaration:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-decl>
        T[0] = mktuple(AST_struct_member_declaration, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <possibly-initialised-scalar-decl>
        T[0] = mktuple(AST_struct_member_declaration, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <possibly-initialised-array-decl>
        T[0] = mktuple(AST_struct_member_declaration, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<possibly-initialised-array-decl> =
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <type> <opt-indirection-decl> <identifier> <array-bounds> <opt-array-init> ';';

    case P_possibly_initialised_array_decl:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-auto-reg-static-ext>
      T[2] = build_ast(A[ap+1], depth+1); // <opt-const-or-volatile-type-qualifier>
      T[3] = build_ast(A[ap+2], depth+1); // <type>
      T[4] = build_ast(A[ap+3], depth+1); // <opt-indirection-decl>
      T[5] = build_ast(A[ap+4], depth+1); // <identifier>
      T[6] = build_ast(A[ap+5], depth+1); // <array-bounds>
      T[7] = build_ast(A[ap+6], depth+1); // <opt-array-init>
      T[8] = lit(AST__LIT, ';', A[ap+7]);
      return mktuple(AST_possibly_initialised_array_decl, alt /*0*/, /*phrases*/ 8, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8]*/);

    //\\ P<possibly-initialised-scalar-decl> =
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <type> <rest-of-scalar-decl>;

    case P_possibly_initialised_scalar_decl:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-auto-reg-static-ext>
      T[2] = build_ast(A[ap+1], depth+1); // <opt-const-or-volatile-type-qualifier>
      T[3] = build_ast(A[ap+2], depth+1); // <type>
      T[4] = build_ast(A[ap+3], depth+1); // <rest-of-scalar-decl>
      return mktuple(AST_possibly_initialised_scalar_decl, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);

    //\\ P<rest-of-scalar-decl> =
    //\\    <opt-indirection-decl> <identifier> <opt-scalar-init> <opt-rest-of-scalar-decl> ';';

    case P_rest_of_scalar_decl:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-indirection-decl>
      T[2] = build_ast(A[ap+1], depth+1); // <identifier>
      T[3] = build_ast(A[ap+2], depth+1); // <opt-scalar-init>
      T[4] = build_ast(A[ap+3], depth+1); // <opt-rest-of-scalar-decl>
      T[5] = lit(AST__LIT, ';', A[ap+4]);
      return mktuple(AST_rest_of_scalar_decl, alt /*0*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);

    //\\ P<opt-rest-of-scalar-decl> =
    //\\    ',' <opt-indirection-decl> <identifier> <opt-scalar-init> <opt-rest-of-scalar-decl>,
    //\\   ;

    case P_opt_rest_of_scalar_decl:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <opt-indirection-decl>
        T[3] = build_ast(A[ap+2], depth+1); // <identifier>
        T[4] = build_ast(A[ap+3], depth+1); // <opt-scalar-init>
        T[5] = build_ast(A[ap+4], depth+1); // <opt-rest-of-scalar-decl>
        T[0] = mktuple(AST_opt_rest_of_scalar_decl, alt /*0*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else               {
        T[0] = mktuple(AST_opt_rest_of_scalar_decl, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<new-structname> =
    //\\    <identifier>;

    case P_new_structname:
      T[1] = build_ast(A[ap+0], depth+1); // <identifier>
      return mktuple(AST_new_structname, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

    //\\ P<decl-list> =
    //\\    <decl> <rest-of-decl-list>;

    case P_decl_list:
      T[1] = build_ast(A[ap+0], depth+1); // <decl>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-decl-list>
      return mktuple(AST_decl_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-decl-list> =
    //\\    ',' <decl-list>,
    //\\   ;

    case P_rest_of_decl_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <decl-list>
        T[0] = mktuple(AST_rest_of_decl_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_decl_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<decl> =
    //\\    <opt-indirection-decl> <identifier> <possibly-empty-array-bounds-list> <opt-array-init>,
    //\\    <opt-indirection-decl> <identifier> <opt-scalar-init>;

    case P_decl:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-indirection-decl>
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[3] = build_ast(A[ap+2], depth+1); // <possibly-empty-array-bounds-list>
        T[4] = build_ast(A[ap+3], depth+1); // <opt-array-init>
        T[0] = mktuple(AST_decl, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-indirection-decl>
        T[2] = build_ast(A[ap+1], depth+1); // <identifier>
        T[3] = build_ast(A[ap+2], depth+1); // <opt-scalar-init>
        T[0] = mktuple(AST_decl, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      }
      return T[0];

    //\\ P<possibly-empty-array-bounds-list> =
    //\\    '[' <opt-constant-expression> ']' <optional-possibly-empty-array-bounds-list>;

    case P_possibly_empty_array_bounds_list:
      T[1] = lit(AST__LIT, '[', A[ap+0]);
      T[2] = build_ast(A[ap+1], depth+1); // <opt-constant-expression>
      T[3] = lit(AST__LIT, ']', A[ap+2]);
      T[4] = build_ast(A[ap+3], depth+1); // <optional-possibly-empty-array-bounds-list>
      return mktuple(AST_possibly_empty_array_bounds_list, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);

    //\\ P<optional-possibly-empty-array-bounds-list> =
    //\\    '[' <opt-constant-expression> ']' <optional-possibly-empty-array-bounds-list>,
    //\\   ;

    case P_optional_possibly_empty_array_bounds_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, '[', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <opt-constant-expression>
        T[3] = lit(AST__LIT, ']', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <optional-possibly-empty-array-bounds-list>
        T[0] = mktuple(AST_optional_possibly_empty_array_bounds_list, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[0] = mktuple(AST_optional_possibly_empty_array_bounds_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<jump-statement> =
    //\\    "goto" <label> ';',
    //\\    "continue" ';',
    //\\    "break" ';',
    //\\    "return" <opt-expression> ';';

    case P_jump_statement:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_goto, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <label>
        T[3] = lit(AST__LIT, ';', A[ap+2]);
        T[0] = mktuple(AST_jump_statement, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 1) {
        T[1] = kw(AST__KW, KW_continue, A[ap+0]);
        T[2] = lit(AST__LIT, ';', A[ap+1]);
        T[0] = mktuple(AST_jump_statement, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 2) {
        T[1] = kw(AST__KW, KW_break, A[ap+0]);
        T[2] = lit(AST__LIT, ';', A[ap+1]);
        T[0] = mktuple(AST_jump_statement, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = kw(AST__KW, KW_return, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <opt-expression>
        T[3] = lit(AST__LIT, ';', A[ap+2]);
        T[0] = mktuple(AST_jump_statement, alt /*3*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      }
      return T[0];

    //\\ P<opt-expression> =
    //\\    <expression>,
    //\\   ;

    case P_opt_expression:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <expression>
        T[0] = mktuple(AST_opt_expression, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_opt_expression, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<label> =
    //\\    <identifier>;

    case P_label:
      T[1] = build_ast(A[ap+0], depth+1); // <identifier>
      return mktuple(AST_label, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

    //\\ P<iteration-statement> =
    //\\    "while" '(' <expression> ')' <statement>,
    //\\    "do" <statement> "while" '(' <expression> ')' ';',
    //\\    "for" '(' <opt-expression> ';' <opt-expression> ';' <opt-expression> ')' <statement>;

    case P_iteration_statement:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_while, A[ap+0]);
        T[2] = lit(AST__LIT, '(', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <expression>
        T[4] = lit(AST__LIT, ')', A[ap+3]);
        T[5] = build_ast(A[ap+4], depth+1); // <statement>
        T[0] = mktuple(AST_iteration_statement, alt /*0*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else if (alt == 1) {
        T[1] = kw(AST__KW, KW_do, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <statement>
        T[3] = kw(AST__KW, KW_while, A[ap+2]);
        T[4] = lit(AST__LIT, '(', A[ap+3]);
        T[5] = build_ast(A[ap+4], depth+1); // <expression>
        T[6] = lit(AST__LIT, ')', A[ap+5]);
        T[7] = lit(AST__LIT, ';', A[ap+6]);
        T[0] = mktuple(AST_iteration_statement, alt /*1*/, /*phrases*/ 7, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7]*/);
      } else               {
        T[1] = kw(AST__KW, KW_for, A[ap+0]);
        T[2] = lit(AST__LIT, '(', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <opt-expression>
        T[4] = lit(AST__LIT, ';', A[ap+3]);
        T[5] = build_ast(A[ap+4], depth+1); // <opt-expression>
        T[6] = lit(AST__LIT, ';', A[ap+5]);
        T[7] = build_ast(A[ap+6], depth+1); // <opt-expression>
        T[8] = lit(AST__LIT, ')', A[ap+7]);
        T[9] = build_ast(A[ap+8], depth+1); // <statement>
        T[0] = mktuple(AST_iteration_statement, alt /*2*/, /*phrases*/ 9, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]*/);
      }
      return T[0];

    //\\ P<selection-statement> =
    //\\    "if" '(' <expression> ')' <statement> <opt-else>,
    //\\    "switch" '(' <expression> ')' <statement>;

    case P_selection_statement:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_if, A[ap+0]);
        T[2] = lit(AST__LIT, '(', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <expression>
        T[4] = lit(AST__LIT, ')', A[ap+3]);
        T[5] = build_ast(A[ap+4], depth+1); // <statement>
        T[6] = build_ast(A[ap+5], depth+1); // <opt-else>
        T[0] = mktuple(AST_selection_statement, alt /*0*/, /*phrases*/ 6, T /*T[1], T[2], T[3], T[4], T[5], T[6]*/);
      } else               {
        T[1] = kw(AST__KW, KW_switch, A[ap+0]);
        T[2] = lit(AST__LIT, '(', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <expression>
        T[4] = lit(AST__LIT, ')', A[ap+3]);
        T[5] = build_ast(A[ap+4], depth+1); // <statement>
        T[0] = mktuple(AST_selection_statement, alt /*1*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      }
      return T[0];

    //\\ P<opt-else> =
    //\\    "else" <statement>,
    //\\   ;

    case P_opt_else:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_else, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <statement>
        T[0] = mktuple(AST_opt_else, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_opt_else, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ # guard to give better error on "label: }" which should be "label: ; }"

    //\\ P<missing-semicolon-after-label-at-end-of-block> =
    //\\    '}';

    case P_missing_semicolon_after_label_at_end_of_block:
      T[1] = lit(AST__LIT, '}', A[ap+0]);
      return mktuple(AST_missing_semicolon_after_label_at_end_of_block, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

    //\\ P<opt-labels> =
    //\\    <label> ':' <opt-labels> <!missing-semicolon-after-label-at-end-of-block>,
    //\\    "case" <constant-expression> ':' <opt-labels> <!missing-semicolon-after-label-at-end-of-block>,
    //\\    "default" ':' <opt-labels> <!missing-semicolon-after-label-at-end-of-block>,
    //\\   ;

    case P_opt_labels:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <label>
        T[2] = lit(AST__LIT, ':', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <opt-labels>
        T[4] = -1; // <!missing-semicolon-after-label-at-end-of-block>
        T[0] = mktuple(AST_opt_labels, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = kw(AST__KW, KW_case, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <constant-expression>
        T[3] = lit(AST__LIT, ':', A[ap+2]);
        T[4] = build_ast(A[ap+3], depth+1); // <opt-labels>
        T[5] = -1; // <!missing-semicolon-after-label-at-end-of-block>
        T[0] = mktuple(AST_opt_labels, alt /*1*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else if (alt == 2) {
        T[1] = kw(AST__KW, KW_default, A[ap+0]);
        T[2] = lit(AST__LIT, ':', A[ap+1]);
        T[3] = build_ast(A[ap+2], depth+1); // <opt-labels>
        T[4] = -1; // <!missing-semicolon-after-label-at-end-of-block>
        T[0] = mktuple(AST_opt_labels, alt /*2*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[0] = mktuple(AST_opt_labels, alt /*3*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ # formal parameter list can also be just a list of types (but can still end in "...")
    //\\ # normal current style however is to have named parameters.
    //\\ #

    //\\ P<opt-param-list> =
    //\\    <formal-param> <opt-rest-of-param-list>,
    //\\    "void",
    //\\   ;

    case P_opt_param_list:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <formal-param>
        T[2] = build_ast(A[ap+1], depth+1); // <opt-rest-of-param-list>
        T[0] = mktuple(AST_opt_param_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 1) {
        T[1] = kw(AST__KW, KW_void, A[ap+0]);
        T[0] = mktuple(AST_opt_param_list, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_opt_param_list, alt /*2*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<opt-oldstyle-param-list> =
    //\\    <oldstyle-param-list>,
    //\\   ;

    case P_opt_oldstyle_param_list:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <oldstyle-param-list>
        T[0] = mktuple(AST_opt_oldstyle_param_list, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_opt_oldstyle_param_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<oldstyle-param-list> =
    //\\    <oldstyle-formal-param> <opt-rest-of-oldstyle-param-list>,
    //\\    "void";

    case P_oldstyle_param_list:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <oldstyle-formal-param>
        T[2] = build_ast(A[ap+1], depth+1); // <opt-rest-of-oldstyle-param-list>
        T[0] = mktuple(AST_oldstyle_param_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = kw(AST__KW, KW_void, A[ap+0]);
        T[0] = mktuple(AST_oldstyle_param_list, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<opt-rest-of-oldstyle-param-list> =
    //\\    ';' <oldstyle-param-list>,
    //\\   ;

    case P_opt_rest_of_oldstyle_param_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ';', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <oldstyle-param-list>
        T[0] = mktuple(AST_opt_rest_of_oldstyle_param_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_opt_rest_of_oldstyle_param_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<oldstyle-formal-param> =
    //\\    <opt-const-or-volatile-type-qualifier> <type> <oldstyle-parameter-list>;

    case P_oldstyle_formal_param:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-const-or-volatile-type-qualifier>
      T[2] = build_ast(A[ap+1], depth+1); // <type>
      T[3] = build_ast(A[ap+2], depth+1); // <oldstyle-parameter-list>
      return mktuple(AST_oldstyle_formal_param, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);

    //\\ P<oldstyle-parameter-list> =
    //\\    <whatever> <rest-of-oldstyle-parameter-list>;

    case P_oldstyle_parameter_list:
      T[1] = build_ast(A[ap+0], depth+1); // <whatever>
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-oldstyle-parameter-list>
      return mktuple(AST_oldstyle_parameter_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);

    //\\ P<rest-of-oldstyle-parameter-list> =
    //\\    ',' <oldstyle-parameter-list>,
    //\\   ;

    case P_rest_of_oldstyle_parameter_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <oldstyle-parameter-list>
        T[0] = mktuple(AST_rest_of_oldstyle_parameter_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_oldstyle_parameter_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<whatever> =
    //\\    <opt-indirection-decl> <opt-identifier> <optional-possibly-empty-array-bounds-list>;

    case P_whatever:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-indirection-decl>
      T[2] = build_ast(A[ap+1], depth+1); // <opt-identifier>
      T[3] = build_ast(A[ap+2], depth+1); // <optional-possibly-empty-array-bounds-list>
      return mktuple(AST_whatever, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);

    //\\ P<opt-rest-of-param-list> =
    //\\    ',' '.' '.' '.',
    //\\    ',' <formal-param> <opt-rest-of-param-list>,
    //\\   ;

    case P_opt_rest_of_param_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = lit(AST__LIT, '.', A[ap+1]);
        T[3] = lit(AST__LIT, '.', A[ap+2]);
        T[4] = lit(AST__LIT, '.', A[ap+3]);
        T[0] = mktuple(AST_opt_rest_of_param_list, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <formal-param>
        T[3] = build_ast(A[ap+2], depth+1); // <opt-rest-of-param-list>
        T[0] = mktuple(AST_opt_rest_of_param_list, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(AST_opt_rest_of_param_list, alt /*2*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<formal-param> =
    //\\    <procedure-as-parameter>,
    //\\    <opt-const-or-volatile-type-qualifier> <type> <opt-indirection-decl> <opt-identifier> <optional-possibly-empty-array-bounds-list>;

    case P_formal_param:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <procedure-as-parameter>
        T[0] = mktuple(AST_formal_param, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-const-or-volatile-type-qualifier>
        T[2] = build_ast(A[ap+1], depth+1); // <type>
        T[3] = build_ast(A[ap+2], depth+1); // <opt-indirection-decl>
        T[4] = build_ast(A[ap+3], depth+1); // <opt-identifier>
        T[5] = build_ast(A[ap+4], depth+1); // <optional-possibly-empty-array-bounds-list>
        T[0] = mktuple(AST_formal_param, alt /*1*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      }
      return T[0];

    //\\ P<opt-identifier> =
    //\\    <identifier>,
    //\\   ;

    case P_opt_identifier:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <identifier>
        T[0] = mktuple(AST_opt_identifier, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_opt_identifier, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<procedure-as-parameter> =
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <opt-basic-type-specifier> '(' <opt-indirection-decl> <identifier> ')' '(' <opt-param-list> ')',
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <typedef-name> '(' <opt-indirection-decl> <identifier> ')' '(' <opt-param-list> ')';

    case P_procedure_as_parameter:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-auto-reg-static-ext>
        T[2] = build_ast(A[ap+1], depth+1); // <opt-const-or-volatile-type-qualifier>
        T[3] = build_ast(A[ap+2], depth+1); // <opt-basic-type-specifier>
        T[4] = lit(AST__LIT, '(', A[ap+3]);
        T[5] = build_ast(A[ap+4], depth+1); // <opt-indirection-decl>
        T[6] = build_ast(A[ap+5], depth+1); // <identifier>
        T[7] = lit(AST__LIT, ')', A[ap+6]);
        T[8] = lit(AST__LIT, '(', A[ap+7]);
        T[9] = build_ast(A[ap+8], depth+1); // <opt-param-list>
        T[10] = lit(AST__LIT, ')', A[ap+9]);
        T[0] = mktuple(AST_procedure_as_parameter, alt /*0*/, /*phrases*/ 10, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-auto-reg-static-ext>
        T[2] = build_ast(A[ap+1], depth+1); // <opt-const-or-volatile-type-qualifier>
        T[3] = build_ast(A[ap+2], depth+1); // <typedef-name>
        T[4] = lit(AST__LIT, '(', A[ap+3]);
        T[5] = build_ast(A[ap+4], depth+1); // <opt-indirection-decl>
        T[6] = build_ast(A[ap+5], depth+1); // <identifier>
        T[7] = lit(AST__LIT, ')', A[ap+6]);
        T[8] = lit(AST__LIT, '(', A[ap+7]);
        T[9] = build_ast(A[ap+8], depth+1); // <opt-param-list>
        T[10] = lit(AST__LIT, ')', A[ap+9]);
        T[0] = mktuple(AST_procedure_as_parameter, alt /*1*/, /*phrases*/ 10, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10]*/);
      }
      return T[0];

    //\\ P<opt-basic-type-specifier> =
    //\\    <basic-type-specifier>,
    //\\   ;

    case P_opt_basic_type_specifier:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <basic-type-specifier>
        T[0] = mktuple(AST_opt_basic_type_specifier, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(AST_opt_basic_type_specifier, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ # Wonder if this would do it? <opt-indirection-decl> '(' <opt-indirection-decl> <identifier> ')' '(' <opt-param-list> ')' <opt-scalar-init> <opt-rest-of-scalar-or-array-decl>,

    //\\ P<typedef-declaration> =
    //\\    "typedef" <type-specifier> <opt-indirection-decl> '(' <opt-indirection-decl> <identifier> ')' '(' <opt-param-list> ')',
    //\\    "typedef" <struct-decl> <maybe-indirect-typedef-name-list>,
    //\\    "typedef" <type-specifier> <maybe-indirect-typedef-name-list>;

    case P_typedef_declaration:
      if (alt == 0)        {
        T[1] = kw(AST__KW, KW_typedef, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <type-specifier>
        T[3] = build_ast(A[ap+2], depth+1); // <opt-indirection-decl>
        T[4] = lit(AST__LIT, '(', A[ap+3]);
        T[5] = build_ast(A[ap+4], depth+1); // <opt-indirection-decl>
        T[6] = build_ast(A[ap+5], depth+1); // <identifier>
        T[7] = lit(AST__LIT, ')', A[ap+6]);
        T[8] = lit(AST__LIT, '(', A[ap+7]);
        T[9] = build_ast(A[ap+8], depth+1); // <opt-param-list>
        T[10] = lit(AST__LIT, ')', A[ap+9]);
        T[0] = mktuple(AST_typedef_declaration, alt /*0*/, /*phrases*/ 10, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10]*/);
      } else if (alt == 1) {
        T[1] = kw(AST__KW, KW_typedef, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <struct-decl>
        T[3] = build_ast(A[ap+2], depth+1); // <maybe-indirect-typedef-name-list>
        T[0] = mktuple(AST_typedef_declaration, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[1] = kw(AST__KW, KW_typedef, A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <type-specifier>
        T[3] = build_ast(A[ap+2], depth+1); // <maybe-indirect-typedef-name-list>
        T[0] = mktuple(AST_typedef_declaration, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      }
      return T[0];

    //\\ P<maybe-indirect-typedef-name-list> =
    //\\    <opt-indirection-decl> <typedef-name> <rest-of-maybe-indirect-typedef-name-list>;

    case P_maybe_indirect_typedef_name_list:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-indirection-decl>
      T[2] = build_ast(A[ap+1], depth+1); // <typedef-name>
      T[3] = build_ast(A[ap+2], depth+1); // <rest-of-maybe-indirect-typedef-name-list>
      return mktuple(AST_maybe_indirect_typedef_name_list, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);

    //\\ P<rest-of-maybe-indirect-typedef-name-list> =
    //\\    ',' <maybe-indirect-typedef-name-list>,
    //\\   ;

    case P_rest_of_maybe_indirect_typedef_name_list:
      if (alt == 0)        {
        T[1] = lit(AST__LIT, ',', A[ap+0]);
        T[2] = build_ast(A[ap+1], depth+1); // <maybe-indirect-typedef-name-list>
        T[0] = mktuple(AST_rest_of_maybe_indirect_typedef_name_list, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(AST_rest_of_maybe_indirect_typedef_name_list, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ E