// This is the grammar for a parser which will read the C code generated by my various
// static binary translators, and perform some source cleanups and optimisations in order
// to make the generated code more easily hand-maintainable.  It is not a decompiler
// however - the generated C will always be rather low-level.

// This code is loosely based on the grammar from:

//   https://cs.wmich.edu/~gupta/teaching/cs4850/sumII06/The%20syntax%20of%20C%20in%20Backus-Naur%20form.htm

// - unfortunately when you get down to using it, there are several errors and omissions in that grammar
// which had to be fixed.  Also, that grammar is written assuming a left-recursive style of parsing, whereas
// our parser has to be right-recursive or it will get into infinite loops.

// A few constructs (especially concerning lvalues vs rvalues) which were handled totally by
// semantic rules if using the grammar above have been handled using a slightly rewritten
// syntax in my modification of the grammar.

// Some of the ambiguities of that grammar were also fixed using the information in:

//   https://en.cppreference.com/w/c/language/operator_precedence

// Note that this grammar primarily parses C expressions - it does not handle flow control
// constructs (apart from one trivial one used in the SBT output) or declarations.
// Declarations would be needed for proper code generation, but since this will be a
// source to source filter, we can get away with a few shortcuts...

// These are built-in phrases which are handled by C code in parser.c rather than by grammatical rules:

//\\ B<char> = 0;
//\\ B<identifier> = 1;
//\\ B<integer-constant> = 2;
//\\ B<character-constant> = 3;
//\\ B<floating-constant> = 4;
//\\ B<string> = 5;
//\\ B<EOF> = 6;

// And here is the entire grammar.  The entry point is phrase "SS" (Source Statement).

// The grammar is extracted from the comments in this file using grep, and is converted
// into a set of tables using the program "takeon.c".

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

// The code to take the parse tree and construct an AST from it was generated from the
// grammar, using the utility "create_parser.c".  The first iteration of the parse tree
// is really a "Concrete Syntax Tree" rather than an Abstract Syntax Tree, i.e. the
// generated code below initially builds an AST which reflects the raw text that was
// matched by the parser.  Eventually this code will be modified to produce a more
// realistic AST where the "A" truly does stand for "Abstract".

// At some point once the C code in this file is modified, it will no longer make sense
// to rebuild this file from the compiled grammar.

// Some work may be needed to re-order tree branches to ensure left-to-right and
// right-to-left order of precedence for some of the operations.

// The only known current issue is that standard C will lex an input stream of +'s
// by grabbing two at a time if available for '++', whereas my parser will actually
// parse "A=B+++++C;" as "A=B++ + ++C;" - standard C will see "A=B++ ++ + C;" and
// give a syntax error (because B++ is not an lvalue so cannot have the second ++ applied)
// However spaces if present are significant and disrupt the recognition of '++'...

// I don't *think* there are any circumstances where my parser would reject a valid
// input, or interpret a valid input differently from C, so I'll leave it as-is and
// allow us to accept some constructs that C would reject.  The SBTs that this is
// going to be used with would never generate such complex C code anyway.

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

//\\ P<post-increment-op> =
//\\    '++',
//\\    '--';

case P_post_increment_op:
  if (alt == 0)        {
    T[1] = lit('+');
    T[2] = lit('+');
    T[0] = mktuple(phrase /*P_post_increment_op*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[1] = lit('-');
    T[2] = lit('-');
    T[0] = mktuple(phrase /*P_post_increment_op*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  }
  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 /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);

//\\ P<rest-of-postfix-expression> =
//\\    '[' <expression> ']' <rest-of-postfix-expression>,
//\\    '(' <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+0], depth+1); // <expression>
    T[3] = lit(']');
    T[4] = build_ast(A[ap+1], depth+1); // <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 == 1) {
    T[1] = lit('(');
    T[2] = build_ast(A[ap+0], depth+1); // <param-list>
    T[3] = lit(')');
    T[4] = build_ast(A[ap+1], depth+1); // <non-empty-rest-of-postfix-expression>
    T[0] = mktuple(phrase /*P_rest_of_postfix_expression*/, alt /*2*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 2) {
    T[1] = lit('.');
    T[2] = identifier(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-expression>
    T[0] = mktuple(phrase /*P_rest_of_postfix_expression*/, alt /*3*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 3) {
    T[1] = lit('-');
    T[2] = lit('>');
    T[3] = identifier(ap+0);
    T[4] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-expression>
    T[0] = mktuple(phrase /*P_rest_of_postfix_expression*/, alt /*4*/, /*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 /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_postfix_expression*/, alt /*6*/, /*phrases*/ 0, T /**/);
  }
  return T[0];

//\\ P<non-empty-rest-of-postfix-expression> =
//\\    '[' <expression> ']' <rest-of-postfix-expression>,
//\\    '(' <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+0], depth+1); // <expression>
    T[3] = lit(']');
    T[4] = build_ast(A[ap+1], depth+1); // <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 == 1) {
    T[1] = lit('(');
    T[2] = build_ast(A[ap+0], depth+1); // <param-list>
    T[3] = lit(')');
    T[4] = build_ast(A[ap+1], depth+1); // <non-empty-rest-of-postfix-expression>
    T[0] = mktuple(phrase /*P_non_empty_rest_of_postfix_expression*/, alt /*2*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 2) {
    T[1] = lit('.');
    T[2] = identifier(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-expression>
    T[0] = mktuple(phrase /*P_non_empty_rest_of_postfix_expression*/, alt /*3*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 3) {
    T[1] = lit('-');
    T[2] = lit('>');
    T[3] = identifier(ap+0);
    T[4] = 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*/ 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 /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  }
  return T[0];

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

case P_postfix_rvalue_expression:
  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>
  return mktuple(phrase /*P_postfix_rvalue_expression*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);

//\\ P<rest-of-postfix-rvalue-expression> =
//\\    '[' <expression> ']' <rest-of-postfix-rvalue-expression>,
//\\    '(' <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+0], depth+1); // <expression>
    T[3] = lit(']');
    T[4] = build_ast(A[ap+1], 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 == 1) {
    T[1] = lit('(');
    T[2] = build_ast(A[ap+0], depth+1); // <param-list>
    T[3] = lit(')');
    T[4] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-rvalue-expression>
    T[0] = mktuple(phrase /*P_rest_of_postfix_rvalue_expression*/, alt /*2*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 2) {
    T[1] = lit('.');
    T[2] = identifier(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <rest-of-postfix-rvalue-expression>
    T[0] = mktuple(phrase /*P_rest_of_postfix_rvalue_expression*/, alt /*3*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 3) {
    T[1] = lit('-');
    T[2] = lit('>');
    T[3] = identifier(ap+0);
    T[4] = 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*/ 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 /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_postfix_rvalue_expression*/, alt /*6*/, /*phrases*/ 0, T /**/);
  }
  return T[0];

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

case P_signed:
  if (alt == 0)        {
    T[1] = kw(/*"signed"*/ 0);
    T[0] = mktuple(phrase /*P_signed*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"unsigned"*/ 1);
    T[0] = mktuple(phrase /*P_signed*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[0] = mktuple(phrase /*P_signed*/, alt /*3*/, /*phrases*/ 0, T /**/);
  }
  return T[0];

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

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

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

case P_int:
  if (alt == 0)        {
    T[1] = kw(/*"int"*/ 4);
    T[0] = mktuple(phrase /*P_int*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[0] = mktuple(phrase /*P_int*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];

//\\ P<type-specifier> =
//\\    "void",
//\\    <signed> "char",
//\\    <signed> <inttype>,
//\\    "float",
//\\    "double",
//\\    <typedef-name>;

case P_type_specifier:
  if (alt == 0)        {
    T[1] = kw(/*"void"*/ 5);
    T[0] = mktuple(phrase /*P_type_specifier*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = build_ast(A[ap+0], depth+1); // <signed>
    T[2] = kw(/*"char"*/ 6);
    T[0] = mktuple(phrase /*P_type_specifier*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 2) {
    T[1] = build_ast(A[ap+0], depth+1); // <signed>
    T[2] = build_ast(A[ap+1], depth+1); // <inttype>
    T[0] = mktuple(phrase /*P_type_specifier*/, alt /*3*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"float"*/ 7);
    T[0] = mktuple(phrase /*P_type_specifier*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"double"*/ 8);
    T[0] = mktuple(phrase /*P_type_specifier*/, alt /*5*/, /*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 /*6*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];

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

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

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

case P_rest_of_indirection_unary_ops:
  if (alt == 0)        {
    T[1] = lit('*');
    T[2] = build_ast(A[ap+0], depth+1); // <rest-of-indirection-unary-ops>
    T[0] = mktuple(phrase /*P_rest_of_indirection_unary_ops*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_indirection_unary_ops*/, alt /*2*/, /*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 /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = lit('-');
    T[0] = mktuple(phrase /*P_arithmetic_unary_op*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  }
  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+0], depth+1); // <rest-of-boolean-unary-ops>
  return mktuple(phrase /*P_boolean_unary_ops*/, alt /*1*/, /*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+0], depth+1); // <rest-of-boolean-unary-ops>
    T[0] = mktuple(phrase /*P_rest_of_boolean_unary_ops*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_boolean_unary_ops*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  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+0], depth+1); // <rest-of-bitwise-unary-ops>
  return mktuple(phrase /*P_bitwise_unary_ops*/, alt /*1*/, /*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+0], depth+1); // <rest-of-bitwise-unary-ops>
    T[0] = mktuple(phrase /*P_rest_of_bitwise_unary_ops*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_bitwise_unary_ops*/, 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 /*1*/, /*phrases*/ 1, T /*T[1]*/);

//\\ P<pre-increment-op> =
//\\    '++',
//\\    '--';

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

//\\ P<optionally-cast-unary-rvalue-expression> =
//\\    '(' <type-specifier> ')' <optionally-cast-unary-rvalue-expression>,
//\\    <unary-rvalue-expression>;

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

//\\ P<optionally-cast-postfix-rvalue-expression> =
//\\    '(' <type-specifier> ')' <optionally-cast-postfix-rvalue-expression>,
//\\    <postfix-rvalue-expression>;

case P_optionally_cast_postfix_rvalue_expression:
  if (alt == 0)        {
    T[1] = lit('(');
    T[2] = build_ast(A[ap+0], depth+1); // <type-specifier>
    T[3] = lit(')');
    T[4] = build_ast(A[ap+1], depth+1); // <optionally-cast-postfix-rvalue-expression>
    T[0] = mktuple(phrase /*P_optionally_cast_postfix_rvalue_expression*/, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else               {
    T[1] = build_ast(A[ap+0], depth+1); // <postfix-rvalue-expression>
    T[0] = mktuple(phrase /*P_optionally_cast_postfix_rvalue_expression*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  }
  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 /*1*/, /*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 /*2*/, /*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 /*3*/, /*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 /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"sizeof"*/ 9);
    T[2] = build_ast(A[ap+0], depth+1); // <unary-rvalue-expression>
    T[0] = mktuple(phrase /*P_unary_rvalue_expression*/, alt /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 5) {
    T[1] = kw(/*"sizeof"*/ 9);
    T[2] = build_ast(A[ap+0], depth+1); // <unary-lvalue-expression>
    T[0] = mktuple(phrase /*P_unary_rvalue_expression*/, alt /*6*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 6) {
    T[1] = kw(/*"sizeof"*/ 9);
    T[2] = build_ast(A[ap+0], depth+1); // <type-specifier>
    T[0] = mktuple(phrase /*P_unary_rvalue_expression*/, alt /*7*/, /*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 /*8*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];

//\\ P<optionally-cast-unary-lvalue-expression> =
//\\    '(' <type-specifier> ')' <optionally-cast-unary-lvalue-expression>,
//\\    <unary-lvalue-expression>;

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

//\\ P<unary-lvalue-expression> =
//\\    <pre-increment-op> <unary-lvalue-expression>,
//\\    <indirection-unary-ops> <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 /*1*/, /*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); // <unary-address-expression>
    T[0] = mktuple(phrase /*P_unary_lvalue_expression*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } 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<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 /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);

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

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

case P_mulop:
  if (alt == 0)        {
    T[1] = lit('*');
    T[0] = mktuple(phrase /*P_mulop*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = lit('/');
    T[0] = mktuple(phrase /*P_mulop*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = lit('%');
    T[0] = mktuple(phrase /*P_mulop*/, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
  }
  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 /*1*/, /*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 /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_additive_expression*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];

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

case P_plusminus:
  if (alt == 0)        {
    T[1] = lit('+');
    T[0] = mktuple(phrase /*P_plusminus*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = lit('-');
    T[0] = mktuple(phrase /*P_plusminus*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  }
  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 /*1*/, /*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 /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_shift_expression*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];

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

case P_shiftop:
  if (alt == 0)        {
    T[1] = lit('<');
    T[2] = lit('<');
    T[0] = mktuple(phrase /*P_shiftop*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[1] = lit('>');
    T[2] = lit('>');
    T[0] = mktuple(phrase /*P_shiftop*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  }
  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 /*1*/, /*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 /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_relational_expression*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];

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

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

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

case P_eqop:
  if (alt == 0)        {
    T[1] = lit('=');
    T[2] = lit('=');
    T[0] = mktuple(phrase /*P_eqop*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[1] = lit('!');
    T[2] = lit('=');
    T[0] = mktuple(phrase /*P_eqop*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  }
  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 /*1*/, /*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+0], depth+1); // <equality-expression>
    T[3] = build_ast(A[ap+1], depth+1); // <rest-of-bitwise-and-expression>
    T[0] = mktuple(phrase /*P_rest_of_bitwise_and_expression*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_bitwise_and_expression*/, alt /*2*/, /*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 /*1*/, /*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+0], depth+1); // <bitwise-and-expression>
    T[3] = build_ast(A[ap+1], depth+1); // <rest-of-exclusive-or-expression>
    T[0] = mktuple(phrase /*P_rest_of_exclusive_or_expression*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_exclusive_or_expression*/, alt /*2*/, /*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 /*1*/, /*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+0], depth+1); // <exclusive-or-expression>
    T[3] = build_ast(A[ap+1], depth+1); // <rest-of-inclusive-or-expression>
    T[0] = mktuple(phrase /*P_rest_of_inclusive_or_expression*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_inclusive_or_expression*/, alt /*2*/, /*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 /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);

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

case P_rest_of_logical_and_expression:
  if (alt == 0)        {
    T[1] = lit('&');
    T[2] = lit('&');
    T[3] = build_ast(A[ap+0], depth+1); // <inclusive-or-expression>
    T[4] = build_ast(A[ap+1], depth+1); // <rest-of-logical-and-expression>
    T[0] = mktuple(phrase /*P_rest_of_logical_and_expression*/, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_logical_and_expression*/, alt /*2*/, /*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 /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);

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

case P_rest_of_logical_or_expression:
  if (alt == 0)        {
    T[1] = lit('|');
    T[2] = lit('|');
    T[3] = build_ast(A[ap+0], depth+1); // <logical-and-expression>
    T[4] = build_ast(A[ap+1], depth+1); // <rest-of-logical-or-expression>
    T[0] = mktuple(phrase /*P_rest_of_logical_or_expression*/, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_logical_or_expression*/, alt /*2*/, /*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 /*1*/, /*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+0], depth+1); // <expression>
    T[3] = lit(':');
    T[4] = build_ast(A[ap+1], depth+1); // <conditional-expression>
    T[0] = mktuple(phrase /*P_rest_of_conditional_expression*/, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_conditional_expression*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];

//\\ P<assignment-expression> =
//\\    <opt-lvalue-assign> <conditional-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>
  return mktuple(phrase /*P_assignment_expression*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);

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

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

case P_assignment_operator:
  if (alt == 0)        {
    T[1] = lit('=');
    T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    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 == 2) {
    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 == 3) {
    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 == 4) {
    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 == 5) {
    T[1] = lit('-');
    T[2] = lit('=');
    T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*6*/, /*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 /*7*/, /*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 /*8*/, /*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 /*9*/, /*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 /*10*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[1] = lit('|');
    T[2] = lit('=');
    T[0] = mktuple(phrase /*P_assignment_operator*/, alt /*11*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  }
  return T[0];

//\\ 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 /*1*/, /*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+0], depth+1); // <assignment-expression>
    T[3] = build_ast(A[ap+1], depth+1); // <rest-of-comma-statement>
    T[0] = mktuple(phrase /*P_rest_of_comma_statement*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_comma_statement*/, alt /*2*/, /*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 /*1*/, /*phrases*/ 1, T /*T[1]*/);

//\\ 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 /*1*/, /*phrases*/ 1, T /*T[1]*/);

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

case P_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_param_list*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[0] = mktuple(phrase /*P_param_list*/, alt /*2*/, /*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+0], depth+1); // <assignment-expression>
    T[3] = build_ast(A[ap+1], depth+1); // <rest-of-param-list>
    T[0] = mktuple(phrase /*P_rest_of_param_list*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_rest_of_param_list*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];

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

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

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

case P_enumeration_constant:
  T[1] = identifier(ap+0);
  return mktuple(phrase /*P_enumeration_constant*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);

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

case P_typedef_name:
  T[1] = identifier(ap+0);
  return mktuple(phrase /*P_typedef_name*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);

//\\ 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+1], depth+1); // <opt-labels>
    T[0] = mktuple(phrase /*P_opt_labels*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"case"*/ 10);
    T[2] = build_ast(A[ap+0], depth+1); // <constant-expression>
    T[3] = lit(':');
    T[4] = build_ast(A[ap+1], depth+1); // <opt-labels>
    T[0] = mktuple(phrase /*P_opt_labels*/, alt /*2*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"default"*/ 11);
    T[2] = lit(':');
    T[3] = build_ast(A[ap+0], depth+1); // <opt-labels>
    T[0] = mktuple(phrase /*P_opt_labels*/, alt /*3*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_opt_labels*/, alt /*4*/, /*phrases*/ 0, T /**/);
  }
  return T[0];

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

case P_label:
  T[1] = identifier(ap+0);
  return mktuple(phrase /*P_label*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);

//\\ P<SS> =
//\\    <opt-labels> "if" '(' <expression> ')' '{',
//\\    '}',
//\\    <opt-labels> <expression> ';';

case P_SS:
  if (alt == 0)        {
    T[1] = build_ast(A[ap+0], depth+1); // <opt-labels>
    T[2] = kw(/*"if"*/ 12);
    T[3] = lit('(');
    T[4] = build_ast(A[ap+1], depth+1); // <expression>
    T[5] = lit(')');
    T[6] = lit('{');
    T[0] = mktuple(phrase /*P_SS*/, alt /*1*/, /*phrases*/ 6, T /*T[1], T[2], T[3], T[4], T[5], T[6]*/);
  } else if (alt == 1) {
    T[1] = lit('}');
    T[0] = mktuple(phrase /*P_SS*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = build_ast(A[ap+0], depth+1); // <opt-labels>
    T[2] = build_ast(A[ap+1], depth+1); // <expression>
    T[3] = lit(';');
    T[0] = mktuple(phrase /*P_SS*/, alt /*3*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  }
  return T[0];

//\\ E
