c-gram.c

    //\\ B<char> = 0;
    //\\ B<identifier> = 1;
    //\\ B<integer-constant> = 2;
    //\\ B<character-constant> = 3;
    //\\ B<floating-constant> = 4;
    //\\ B<string> = 5;
    //\\ B<keyword> = 6;
    //\\ B<pp> = 7;
    //\\ B<mm> = 8;
    //\\ B<andand> = 9;
    //\\ B<oror> = 10;
    //\\ B<eqeq> = 11;
    //\\ B<EOF> = 12;

    //\\ # top-level statement

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

    case P_SS:
      T[1] = build_ast(A[ap+0], depth+1); // <opt-external-declaration-list>
      return mktuple(phrase /*P_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(phrase /*P_opt_external_declaration_list*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = bip(B_EOF, ap+0);
        T[0] = mktuple(phrase /*P_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(';');
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_external_declaration*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit(';');
        T[0] = mktuple(phrase /*P_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] = bip(B_identifier, ap+1);
        T[3] = lit('{');
        T[4] = build_ast(A[ap+3], depth+1); // <struct-field-declarations>
        T[5] = lit('}');
        T[0] = mktuple(phrase /*P_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('{');
        T[3] = build_ast(A[ap+2], depth+1); // <struct-field-declarations>
        T[4] = lit('}');
        T[0] = mktuple(phrase /*P_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] = bip(B_identifier, ap+1);
        T[0] = mktuple(phrase /*P_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(/*"struct"*/ 0);
        T[0] = mktuple(phrase /*P_struct_or_union*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = kw(/*"union"*/ 1);
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_rest_of_struct_field_declarations*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(';');
      return mktuple(phrase /*P_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] = bip(B_identifier, ap+1);
        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(phrase /*P_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('(');
        T[3] = build_ast(A[ap+2], depth+1); // <opt-indirection-decl>
        T[4] = bip(B_identifier, ap+3);
        T[5] = lit(')');
        T[6] = lit('(');
        T[7] = build_ast(A[ap+6], depth+1); // <opt-param-list>
        T[8] = lit(')');
        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(phrase /*P_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] = bip(B_identifier, ap+1);
        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(phrase /*P_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(',');
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-scalar-or-array-decl>
        T[0] = mktuple(phrase /*P_opt_rest_of_scalar_or_array_decl*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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('=');
        T[2] = build_ast(A[ap+1], depth+1); // <assignment-expression>
        T[0] = mktuple(phrase /*P_opt_scalar_init*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_opt_rest_of_assignment_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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('?');
        T[2] = build_ast(A[ap+1], depth+1); // <expression>
        T[3] = lit(':');
        T[4] = build_ast(A[ap+3], depth+1); // <conditional-expression>
        T[0] = mktuple(phrase /*P_rest_of_conditional_expression*/, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_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(',');
        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(phrase /*P_rest_of_comma_statement*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(B_oror, 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(phrase /*P_rest_of_logical_or_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(B_andand, 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(phrase /*P_rest_of_logical_and_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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('|');
        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(phrase /*P_rest_of_inclusive_or_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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('^');
        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(phrase /*P_rest_of_exclusive_or_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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('&');
        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(phrase /*P_rest_of_bitwise_and_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_rest_of_equality_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_rest_of_relational_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_rest_of_shift_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_rest_of_additive_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_rest_of_multiplicative_expression*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_rest_of_multiplicative_expression*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ 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>,
    //\\    <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(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_unary_rvalue_expression*/, alt /*3*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 4) {
        T[1] = kw(/*"sizeof"*/ 2);
        T[2] = build_ast(A[ap+1], depth+1); // <unary-rvalue-expression>
        T[0] = mktuple(phrase /*P_unary_rvalue_expression*/, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 5) {
        T[1] = kw(/*"sizeof"*/ 2);
        T[2] = build_ast(A[ap+1], depth+1); // <unary-lvalue-expression>
        T[0] = mktuple(phrase /*P_unary_rvalue_expression*/, alt /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 6) {
        T[1] = kw(/*"sizeof"*/ 2);
        T[2] = build_ast(A[ap+1], depth+1); // <type-specifier>
        T[0] = mktuple(phrase /*P_unary_rvalue_expression*/, alt /*6*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <optionally-cast-postfix-rvalue-expression>
        T[0] = mktuple(phrase /*P_unary_rvalue_expression*/, alt /*7*/, /*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(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_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('[');
        T[2] = build_ast(A[ap+1], depth+1); // <expression>
        T[3] = lit(']');
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(phrase /*P_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('(');
        T[2] = build_ast(A[ap+1], depth+1); // <actual-param-list>
        T[3] = lit(')');
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(phrase /*P_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('.');
        T[2] = bip(B_identifier, ap+1);
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(phrase /*P_rest_of_postfix_rvalue_expression*/, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 3) {
        T[1] = lit('-');
        T[2] = lit('>');
        T[3] = bip(B_identifier, ap+2);
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-rvalue-expression>
        T[0] = mktuple(phrase /*P_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(phrase /*P_rest_of_postfix_rvalue_expression*/, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(B_pp, ap+0);
        T[0] = mktuple(phrase /*P_post_increment_op*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = bip(B_mm, ap+0);
        T[0] = mktuple(phrase /*P_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(phrase /*P_actual_param_list*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(',');
        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(phrase /*P_rest_of_param_list*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_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('[');
        T[2] = build_ast(A[ap+1], depth+1); // <expression>
        T[3] = lit(']');
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(phrase /*P_rest_of_postfix_expression*/, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = lit('(');
        T[2] = build_ast(A[ap+1], depth+1); // <actual-param-list>
        T[3] = lit(')');
        T[4] = build_ast(A[ap+3], depth+1); // <non-empty-rest-of-postfix-expression>
        T[0] = mktuple(phrase /*P_rest_of_postfix_expression*/, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 2) {
        T[1] = lit('.');
        T[2] = bip(B_identifier, ap+1);
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(phrase /*P_rest_of_postfix_expression*/, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 3) {
        T[1] = lit('-');
        T[2] = lit('>');
        T[3] = bip(B_identifier, ap+2);
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(phrase /*P_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(phrase /*P_rest_of_postfix_expression*/, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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('[');
        T[2] = build_ast(A[ap+1], depth+1); // <expression>
        T[3] = lit(']');
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(phrase /*P_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('(');
        T[2] = build_ast(A[ap+1], depth+1); // <actual-param-list>
        T[3] = lit(')');
        T[4] = build_ast(A[ap+3], depth+1); // <non-empty-rest-of-postfix-expression>
        T[0] = mktuple(phrase /*P_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('.');
        T[2] = bip(B_identifier, ap+1);
        T[3] = build_ast(A[ap+2], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(phrase /*P_non_empty_rest_of_postfix_expression*/, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 3) {
        T[1] = lit('-');
        T[2] = lit('>');
        T[3] = bip(B_identifier, ap+2);
        T[4] = build_ast(A[ap+3], depth+1); // <rest-of-postfix-expression>
        T[0] = mktuple(phrase /*P_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(phrase /*P_non_empty_rest_of_postfix_expression*/, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      }
      return T[0];

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

    case P_primary_expression:
      if (alt == 0)        {
        T[1] = bip(B_identifier, ap+0);
        T[0] = mktuple(phrase /*P_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(phrase /*P_primary_expression*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = bip(B_string, ap+0);
        T[0] = mktuple(phrase /*P_primary_expression*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit('(');
        T[2] = build_ast(A[ap+1], depth+1); // <expression>
        T[3] = lit(')');
        T[0] = mktuple(phrase /*P_primary_expression*/, alt /*3*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      }
      return T[0];

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

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

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

    case P_enumeration_constant:
      T[1] = bip(B_identifier, ap+0);
      return mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_optionally_cast_unary_lvalue_expression*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

    //\\ P<cast> =
    //\\    '(' <type-specifier> <opt-indirection-unary-ops> ')';

    case P_cast:
      T[1] = lit('(');
      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(')');
      return mktuple(phrase /*P_cast*/, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);

    //\\ # <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('*');
        T[3] = build_ast(A[ap+2], depth+1); // <opt-indirection-decl>
        T[0] = mktuple(phrase /*P_opt_indirection_decl*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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('*');
      T[2] = build_ast(A[ap+1], depth+1); // <opt-indirection-unary-ops>
      return mktuple(phrase /*P_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('*');
        T[2] = build_ast(A[ap+1], depth+1); // <opt-indirection-unary-ops>
        T[0] = mktuple(phrase /*P_opt_indirection_unary_ops*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_type_specifier*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <typedef-name>
        T[0] = mktuple(phrase /*P_type_specifier*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

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

    case P_typedef_name:
      T[1] = bip(B_identifier, ap+0);
      return mktuple(phrase /*P_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> =
    //\\    "void",
    //\\    "double",
    //\\    "long" "double",
    //\\    <opt-signed> "char",
    //\\    <opt-signed> <inttype>,
    //\\    "float",
    //\\    <struct-or-union-specifier>,
    //\\    <enum-specifier>;

    case P_basic_type_specifier:
      if (alt == 0)        {
        T[1] = kw(/*"void"*/ 3);
        T[0] = mktuple(phrase /*P_basic_type_specifier*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = kw(/*"double"*/ 4);
        T[0] = mktuple(phrase /*P_basic_type_specifier*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = kw(/*"long"*/ 5);
        T[2] = kw(/*"double"*/ 4);
        T[0] = mktuple(phrase /*P_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>
        T[2] = kw(/*"char"*/ 6);
        T[0] = mktuple(phrase /*P_basic_type_specifier*/, alt /*3*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 4) {
        T[1] = build_ast(A[ap+0], depth+1); // <opt-signed>
        T[2] = build_ast(A[ap+1], depth+1); // <inttype>
        T[0] = mktuple(phrase /*P_basic_type_specifier*/, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 5) {
        T[1] = kw(/*"float"*/ 7);
        T[0] = mktuple(phrase /*P_basic_type_specifier*/, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 6) {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-or-union-specifier>
        T[0] = mktuple(phrase /*P_basic_type_specifier*/, alt /*6*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <enum-specifier>
        T[0] = mktuple(phrase /*P_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(/*"enum"*/ 8);
        T[2] = lit('{');
        T[3] = build_ast(A[ap+2], depth+1); // <enumerator-list>
        T[4] = lit('}');
        T[0] = mktuple(phrase /*P_enum_specifier*/, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = kw(/*"enum"*/ 8);
        T[2] = bip(B_identifier, ap+1);
        T[3] = lit('{');
        T[4] = build_ast(A[ap+3], depth+1); // <enumerator-list>
        T[5] = lit('}');
        T[0] = mktuple(phrase /*P_enum_specifier*/, alt /*1*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else               {
        T[1] = kw(/*"enum"*/ 8);
        T[2] = bip(B_identifier, ap+1);
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(',');
        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(phrase /*P_rest_of_enumerator_list*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 1) {
        T[1] = lit(',');
        T[0] = mktuple(phrase /*P_rest_of_enumerator_list*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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] = bip(B_identifier, ap+0);
        T[2] = lit('=');
        T[3] = build_ast(A[ap+2], depth+1); // <constant-expression>
        T[0] = mktuple(phrase /*P_enumerator*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[1] = bip(B_identifier, ap+0);
        T[0] = mktuple(phrase /*P_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(phrase /*P_constant_expression*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);

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

    case P_inttype:
      if (alt == 0)        {
        T[1] = kw(/*"short"*/ 9);
        T[2] = build_ast(A[ap+1], depth+1); // <opt-int>
        T[0] = mktuple(phrase /*P_inttype*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 1) {
        T[1] = kw(/*"long"*/ 5);
        T[2] = kw(/*"long"*/ 5);
        T[3] = build_ast(A[ap+2], depth+1); // <opt-int>
        T[0] = mktuple(phrase /*P_inttype*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 2) {
        T[1] = kw(/*"long"*/ 5);
        T[2] = build_ast(A[ap+1], depth+1); // <opt-int>
        T[0] = mktuple(phrase /*P_inttype*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = kw(/*"int"*/ 10);
        T[0] = mktuple(phrase /*P_inttype*/, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

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

    case P_opt_int:
      if (alt == 0)        {
        T[1] = kw(/*"int"*/ 10);
        T[0] = mktuple(phrase /*P_opt_int*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(/*"signed"*/ 11);
        T[0] = mktuple(phrase /*P_opt_signed*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = kw(/*"unsigned"*/ 12);
        T[0] = mktuple(phrase /*P_opt_signed*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_opt_signed*/, alt /*2*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

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

    case P_address_operator:
      T[1] = lit('&');
      return mktuple(phrase /*P_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(B_pp, ap+0);
        T[0] = mktuple(phrase /*P_pre_increment_op*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = bip(B_mm, ap+0);
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_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('~');
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-bitwise-unary-ops>
      return mktuple(phrase /*P_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('~');
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-bitwise-unary-ops>
        T[0] = mktuple(phrase /*P_rest_of_bitwise_unary_ops*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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('!');
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-boolean-unary-ops>
      return mktuple(phrase /*P_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('!');
        T[2] = build_ast(A[ap+1], depth+1); // <rest-of-boolean-unary-ops>
        T[0] = mktuple(phrase /*P_rest_of_boolean_unary_ops*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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('+');
        T[0] = mktuple(phrase /*P_arithmetic_unary_op*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit('-');
        T[0] = mktuple(phrase /*P_arithmetic_unary_op*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

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

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

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

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

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

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

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

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

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

    case P_eqop:
      if (alt == 0)        {
        T[1] = bip(B_eqeq, ap+0);
        T[0] = mktuple(phrase /*P_eqop*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit('!');
        T[2] = lit('=');
        T[0] = mktuple(phrase /*P_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('=');
        T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = lit('*');
        T[2] = lit('=');
        T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 2) {
        T[1] = lit('/');
        T[2] = lit('=');
        T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 3) {
        T[1] = lit('%');
        T[2] = lit('=');
        T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*3*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 4) {
        T[1] = lit('+');
        T[2] = lit('=');
        T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 5) {
        T[1] = lit('-');
        T[2] = lit('=');
        T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 6) {
        T[1] = lit('<');
        T[2] = lit('<');
        T[3] = lit('=');
        T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*6*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 7) {
        T[1] = lit('>');
        T[2] = lit('>');
        T[3] = lit('=');
        T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*7*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 8) {
        T[1] = lit('&');
        T[2] = lit('=');
        T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*8*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 9) {
        T[1] = lit('^');
        T[2] = lit('=');
        T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*9*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = lit('|');
        T[2] = lit('=');
        T[0] = mktuple(phrase /*P_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(phrase /*P_opt_lvalue_assign*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_opt_lvalue_assign*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

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

    case P_opt_array_init:
      if (alt == 0)        {
        T[1] = lit('=');
        T[2] = lit('{');
        T[3] = build_ast(A[ap+2], depth+1); // <constant-initializer-list>
        T[4] = lit('}');
        T[0] = mktuple(phrase /*P_opt_array_init*/, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 1) {
        T[1] = lit('=');
        T[2] = bip(B_string, ap+1);
        T[0] = mktuple(phrase /*P_opt_array_init*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(',');
        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(phrase /*P_rest_of_constant_initializer_list*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 1) {
        T[1] = lit(',');
        T[0] = mktuple(phrase /*P_rest_of_constant_initializer_list*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_constant_initializer*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = lit('{');
        T[2] = build_ast(A[ap+1], depth+1); // <constant-initializer-list>
        T[3] = lit('}');
        T[0] = mktuple(phrase /*P_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('[');
      T[2] = build_ast(A[ap+1], depth+1); // <opt-constant-expression>
      T[3] = lit(']');
      T[4] = build_ast(A[ap+3], depth+1); // <opt-array-bounds>
      return mktuple(phrase /*P_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('[');
        T[2] = build_ast(A[ap+1], depth+1); // <opt-constant-expression>
        T[3] = lit(']');
        T[4] = build_ast(A[ap+3], depth+1); // <opt-array-bounds>
        T[0] = mktuple(phrase /*P_opt_array_bounds*/, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_opt_constant_expression*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_opt_constant_expression*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

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

    case P_type:
      if (alt == 0)        {
        T[1] = kw(/*"void"*/ 3);
        T[0] = mktuple(phrase /*P_type*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = build_ast(A[ap+0], depth+1); // <enum-specifier>
        T[0] = mktuple(phrase /*P_type*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = build_ast(A[ap+0], depth+1); // <struct-or-union-specifier>
        T[0] = mktuple(phrase /*P_type*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 3) {
        T[1] = kw(/*"typeof"*/ 13);
        T[2] = lit('(');
        T[3] = build_ast(A[ap+2], depth+1); // <unary-lvalue-expression>
        T[4] = lit(')');
        T[0] = mktuple(phrase /*P_type*/, 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); // <basic-type-specifier>
        T[0] = mktuple(phrase /*P_type*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <typedef-name>
        T[0] = mktuple(phrase /*P_type*/, alt /*5*/, /*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(phrase /*P_opt_const_or_volatile_type_qualifier*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(/*"const"*/ 14);
        T[0] = mktuple(phrase /*P_const_or_volatile_type_qualifier*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = kw(/*"volatile"*/ 15);
        T[0] = mktuple(phrase /*P_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(/*"auto"*/ 16);
        T[0] = mktuple(phrase /*P_opt_auto_reg_static_ext*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        T[1] = kw(/*"register"*/ 17);
        T[0] = mktuple(phrase /*P_opt_auto_reg_static_ext*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 2) {
        T[1] = kw(/*"static"*/ 18);
        T[0] = mktuple(phrase /*P_opt_auto_reg_static_ext*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 3) {
        T[1] = kw(/*"extern"*/ 19);
        T[0] = mktuple(phrase /*P_opt_auto_reg_static_ext*/, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_opt_auto_reg_static_ext*/, alt /*4*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

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

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

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

    case P_identifier_list:
      T[1] = bip(B_identifier, ap+0);
      T[2] = build_ast(A[ap+1], depth+1); // <rest-of-identifier-list>
      return mktuple(phrase /*P_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(',');
        T[2] = build_ast(A[ap+1], depth+1); // <identifier-list>
        T[0] = mktuple(phrase /*P_rest_of_identifier_list*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_rest_of_identifier_list*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<proc-fn-decl> =
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <opt-basic-type-specifier> <opt-indirection-decl> <identifier> '(' <opt-param-list> ')' <forward-decl-or-actual-body>,
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <typedef-name> <opt-indirection-decl> <identifier> '(' <opt-param-list> ')' <forward-decl-or-actual-body>,
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <opt-basic-type-specifier> <opt-indirection-decl> <identifier> '(' <identifier-list> ')' <opt-oldstyle-param-list> ';' <compound-statement>,
    //\\    <opt-auto-reg-static-ext> <opt-const-or-volatile-type-qualifier> <typedef-name> <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); // <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] = build_ast(A[ap+3], depth+1); // <opt-indirection-decl>
        T[5] = bip(B_identifier, ap+4);
        T[6] = lit('(');
        T[7] = build_ast(A[ap+6], depth+1); // <opt-param-list>
        T[8] = lit(')');
        T[9] = build_ast(A[ap+8], depth+1); // <forward-decl-or-actual-body>
        T[0] = mktuple(phrase /*P_proc_fn_decl*/, alt /*0*/, /*phrases*/ 9, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]*/);
      } else if (alt == 1) {
        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] = build_ast(A[ap+3], depth+1); // <opt-indirection-decl>
        T[5] = bip(B_identifier, ap+4);
        T[6] = lit('(');
        T[7] = build_ast(A[ap+6], depth+1); // <opt-param-list>
        T[8] = lit(')');
        T[9] = build_ast(A[ap+8], depth+1); // <forward-decl-or-actual-body>
        T[0] = mktuple(phrase /*P_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]*/);
      } else if (alt == 2) {
        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] = build_ast(A[ap+3], depth+1); // <opt-indirection-decl>
        T[5] = bip(B_identifier, ap+4);
        T[6] = lit('(');
        T[7] = build_ast(A[ap+6], depth+1); // <identifier-list>
        T[8] = lit(')');
        T[9] = build_ast(A[ap+8], depth+1); // <opt-oldstyle-param-list>
        T[10] = lit(';');
        T[11] = build_ast(A[ap+10], depth+1); // <compound-statement>
        T[0] = mktuple(phrase /*P_proc_fn_decl*/, alt /*2*/, /*phrases*/ 11, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10], T[11]*/);
      } 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] = build_ast(A[ap+3], depth+1); // <opt-indirection-decl>
        T[5] = bip(B_identifier, ap+4);
        T[6] = lit('(');
        T[7] = build_ast(A[ap+6], depth+1); // <identifier-list>
        T[8] = lit(')');
        T[9] = build_ast(A[ap+8], depth+1); // <opt-oldstyle-param-list>
        T[10] = lit(';');
        T[11] = build_ast(A[ap+10], depth+1); // <compound-statement>
        T[0] = mktuple(phrase /*P_proc_fn_decl*/, alt /*3*/, /*phrases*/ 11, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10], T[11]*/);
      }
      return T[0];

    //\\ P<forward-decl-or-actual-body> =
    //\\    ';',
    //\\    <compound-statement>;

    case P_forward_decl_or_actual_body:
      if (alt == 0)        {
        T[1] = lit(';');
        T[0] = mktuple(phrase /*P_forward_decl_or_actual_body*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <compound-statement>
        T[0] = mktuple(phrase /*P_forward_decl_or_actual_body*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
      }
      return T[0];

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

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

    //\\ 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(phrase /*P_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(phrase /*P_rest_of_statement_list*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_rest_of_statement_list*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<statement> =
    //\\    ';',
    //\\    <compound-statement>,
    //\\    <selection-statement>,
    //\\    <iteration-statement>,
    //\\    <jump-statement>,
    //\\    <expression> ';',
    //\\    <in-proc-data-declaration>;

    case P_statement:
      if (alt == 0)        {
        T[1] = lit(';');
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_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(';');
        T[0] = mktuple(phrase /*P_statement*/, alt /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = build_ast(A[ap+0], depth+1); // <in-proc-data-declaration>
        T[0] = mktuple(phrase /*P_statement*/, alt /*6*/, /*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(phrase /*P_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(phrase /*P_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(/*"struct"*/ 0);
      T[2] = build_ast(A[ap+1], depth+1); // <new-structname>
      T[3] = lit('{');
      T[4] = build_ast(A[ap+3], depth+1); // <struct-member-list>
      T[5] = lit('}');
      return mktuple(phrase /*P_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(phrase /*P_struct_member_list*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_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(phrase /*P_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] = bip(B_identifier, ap+4);
      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(';');
      return mktuple(phrase /*P_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(phrase /*P_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] = bip(B_identifier, ap+1);
      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(';');
      return mktuple(phrase /*P_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(',');
        T[2] = build_ast(A[ap+1], depth+1); // <opt-indirection-decl>
        T[3] = bip(B_identifier, ap+2);
        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(phrase /*P_opt_rest_of_scalar_decl*/, alt /*0*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else               {
        T[0] = mktuple(phrase /*P_opt_rest_of_scalar_decl*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

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

    case P_new_structname:
      T[1] = bip(B_identifier, ap+0);
      return mktuple(phrase /*P_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(phrase /*P_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] = kw(/*","*/ 20);
        T[2] = build_ast(A[ap+1], depth+1); // <decl-list>
        T[0] = mktuple(phrase /*P_rest_of_decl_list*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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] = bip(B_identifier, ap+1);
        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(phrase /*P_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] = bip(B_identifier, ap+1);
        T[3] = build_ast(A[ap+2], depth+1); // <opt-scalar-init>
        T[0] = mktuple(phrase /*P_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('[');
      T[2] = build_ast(A[ap+1], depth+1); // <opt-constant-expression>
      T[3] = lit(']');
      T[4] = build_ast(A[ap+3], depth+1); // <optional-possibly-empty-array-bounds-list>
      return mktuple(phrase /*P_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('[');
        T[2] = build_ast(A[ap+1], depth+1); // <opt-constant-expression>
        T[3] = lit(']');
        T[4] = build_ast(A[ap+3], depth+1); // <optional-possibly-empty-array-bounds-list>
        T[0] = mktuple(phrase /*P_optional_possibly_empty_array_bounds_list*/, alt /*0*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(/*"goto"*/ 21);
        T[2] = build_ast(A[ap+1], depth+1); // <label>
        T[3] = lit(';');
        T[0] = mktuple(phrase /*P_jump_statement*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 1) {
        T[1] = kw(/*"continue"*/ 22);
        T[2] = lit(';');
        T[0] = mktuple(phrase /*P_jump_statement*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else if (alt == 2) {
        T[1] = kw(/*"break"*/ 23);
        T[2] = lit(';');
        T[0] = mktuple(phrase /*P_jump_statement*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[1] = kw(/*"return"*/ 24);
        T[2] = build_ast(A[ap+1], depth+1); // <opt-expression>
        T[3] = lit(';');
        T[0] = mktuple(phrase /*P_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(phrase /*P_opt_expression*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_opt_expression*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

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

    case P_label:
      T[1] = bip(B_identifier, ap+0);
      return mktuple(phrase /*P_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(/*"while"*/ 25);
        T[2] = lit('(');
        T[3] = build_ast(A[ap+2], depth+1); // <expression>
        T[4] = lit(')');
        T[5] = build_ast(A[ap+4], depth+1); // <statement>
        T[0] = mktuple(phrase /*P_iteration_statement*/, alt /*0*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
      } else if (alt == 1) {
        T[1] = kw(/*"do"*/ 26);
        T[2] = build_ast(A[ap+1], depth+1); // <statement>
        T[3] = kw(/*"while"*/ 25);
        T[4] = lit('(');
        T[5] = build_ast(A[ap+4], depth+1); // <expression>
        T[6] = lit(')');
        T[7] = lit(';');
        T[0] = mktuple(phrase /*P_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(/*"for"*/ 27);
        T[2] = lit('(');
        T[3] = build_ast(A[ap+2], depth+1); // <opt-expression>
        T[4] = lit(';');
        T[5] = build_ast(A[ap+4], depth+1); // <opt-expression>
        T[6] = lit(';');
        T[7] = build_ast(A[ap+6], depth+1); // <opt-expression>
        T[8] = lit(')');
        T[9] = build_ast(A[ap+8], depth+1); // <statement>
        T[0] = mktuple(phrase /*P_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(/*"if"*/ 28);
        T[2] = lit('(');
        T[3] = build_ast(A[ap+2], depth+1); // <expression>
        T[4] = lit(')');
        T[5] = build_ast(A[ap+4], depth+1); // <statement>
        T[6] = build_ast(A[ap+5], depth+1); // <opt-else>
        T[0] = mktuple(phrase /*P_selection_statement*/, alt /*0*/, /*phrases*/ 6, T /*T[1], T[2], T[3], T[4], T[5], T[6]*/);
      } else               {
        T[1] = kw(/*"switch"*/ 29);
        T[2] = lit('(');
        T[3] = build_ast(A[ap+2], depth+1); // <expression>
        T[4] = lit(')');
        T[5] = build_ast(A[ap+4], depth+1); // <statement>
        T[0] = mktuple(phrase /*P_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(/*"else"*/ 30);
        T[2] = build_ast(A[ap+1], depth+1); // <statement>
        T[0] = mktuple(phrase /*P_opt_else*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_opt_else*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<opt-labels> =
    //\\    <label> ':' <opt-labels>,
    //\\    "case" <constant-expression> ':' <opt-labels>,
    //\\    "default" ':' <opt-labels>,
    //\\   ;

    case P_opt_labels:
      if (alt == 0)        {
        T[1] = build_ast(A[ap+0], depth+1); // <label>
        T[2] = lit(':');
        T[3] = build_ast(A[ap+2], depth+1); // <opt-labels>
        T[0] = mktuple(phrase /*P_opt_labels*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else if (alt == 1) {
        T[1] = kw(/*"case"*/ 31);
        T[2] = build_ast(A[ap+1], depth+1); // <constant-expression>
        T[3] = lit(':');
        T[4] = build_ast(A[ap+3], depth+1); // <opt-labels>
        T[0] = mktuple(phrase /*P_opt_labels*/, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
      } else if (alt == 2) {
        T[1] = kw(/*"default"*/ 32);
        T[2] = lit(':');
        T[3] = build_ast(A[ap+2], depth+1); // <opt-labels>
        T[0] = mktuple(phrase /*P_opt_labels*/, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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> =
    //\\    "void",
    //\\    <formal-param> <opt-rest-of-param-list>,
    //\\   ;

    case P_opt_param_list:
      if (alt == 0)        {
        T[1] = kw(/*"void"*/ 3);
        T[0] = mktuple(phrase /*P_opt_param_list*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else if (alt == 1) {
        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(phrase /*P_opt_param_list*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_opt_oldstyle_param_list*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_opt_oldstyle_param_list*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

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

    case P_oldstyle_param_list:
      if (alt == 0)        {
        T[1] = kw(/*"void"*/ 3);
        T[0] = mktuple(phrase /*P_oldstyle_param_list*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        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(phrase /*P_oldstyle_param_list*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      }
      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(';');
        T[2] = build_ast(A[ap+1], depth+1); // <oldstyle-param-list>
        T[0] = mktuple(phrase /*P_opt_rest_of_oldstyle_param_list*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_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(',');
        T[2] = build_ast(A[ap+1], depth+1); // <oldstyle-parameter-list>
        T[0] = mktuple(phrase /*P_rest_of_oldstyle_parameter_list*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(',');
        T[2] = lit('.');
        T[3] = lit('.');
        T[4] = lit('.');
        T[0] = mktuple(phrase /*P_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(',');
        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(phrase /*P_opt_rest_of_param_list*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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(phrase /*P_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(phrase /*P_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] = bip(B_identifier, ap+0);
        T[0] = mktuple(phrase /*P_opt_identifier*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_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('(');
        T[5] = build_ast(A[ap+4], depth+1); // <opt-indirection-decl>
        T[6] = bip(B_identifier, ap+5);
        T[7] = lit(')');
        T[8] = lit('(');
        T[9] = build_ast(A[ap+8], depth+1); // <opt-param-list>
        T[10] = lit(')');
        T[0] = mktuple(phrase /*P_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('(');
        T[5] = build_ast(A[ap+4], depth+1); // <opt-indirection-decl>
        T[6] = bip(B_identifier, ap+5);
        T[7] = lit(')');
        T[8] = lit('(');
        T[9] = build_ast(A[ap+8], depth+1); // <opt-param-list>
        T[10] = lit(')');
        T[0] = mktuple(phrase /*P_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(phrase /*P_opt_basic_type_specifier*/, alt /*0*/, /*phrases*/ 1, T /*T[1]*/);
      } else               {
        T[0] = mktuple(phrase /*P_opt_basic_type_specifier*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ P<typedef-declaration> =
    //\\    "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(/*"typedef"*/ 33);
        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(phrase /*P_typedef_declaration*/, alt /*0*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
      } else               {
        T[1] = kw(/*"typedef"*/ 33);
        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(phrase /*P_typedef_declaration*/, alt /*1*/, /*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(phrase /*P_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(',');
        T[2] = build_ast(A[ap+1], depth+1); // <maybe-indirect-typedef-name-list>
        T[0] = mktuple(phrase /*P_rest_of_maybe_indirect_typedef_name_list*/, alt /*0*/, /*phrases*/ 2, T /*T[1], T[2]*/);
      } else               {
        T[0] = mktuple(phrase /*P_rest_of_maybe_indirect_typedef_name_list*/, alt /*1*/, /*phrases*/ 0, T /**/);
      }
      return T[0];

    //\\ E