/*

TO DO: Fix '\' -> '\\'
       Remove 'translate_hack()' and do translations on output
       Dump switch table at end of scope that it was declared in
       Add #define x (*x) for %NAME parameters
       Add #define PROC(x) _PROC(&x) for procedures with %NAME parameters,
        and remember to undo defines at end of scope in which procedure
        was declared.  See test.c for example

long term: remove expedient hacks that assume the AA compiler is the only program
           this will be translating... eg procedure parameters, %MAPs etc.

           Handle assembly language by static binary translation methods (ie not run-time emulation)
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define isoctal(i) (isdigit(i) && ((i)<'8'))
#ifndef FALSE
#define FALSE (0!=0)
#define TRUE (0==0)
#endif

static int debug_parser = FALSE;
static int stop_compiling = FALSE;
#define DEBUG_PARSER_PARSER 1
#define EXTENDED_ERROR_REPORTING 1

#include "grammar.h"

/*  Parsing.  (Table driven top-down recursive-descent parser) */

/*   The parser used here is based on a design by Tony Brooker which was
    originally used in Atlas Autocode and the "Compiler Compiler".
    It generates a concrete syntax tree rather than the abstract
    syntax tree more popular in modern compilers.  A later phase
    can convert from concrete to abstract syntax, but this compiler
    is simple enough that it's easier to generate C directly.

    (The concrete syntax tree is a reasonable tool to use for source
     to source manipulations, prettyprinting, etc etc; you *can*
     use it to generate code from directly, but it's far more awkward.)

    Note that the parsing procedure here is just a piece of code
    to walk a pre-built table.  There is nothing in this section
    which reflects the grammar, if that is what you are looking for.
    You'll find the grammar embedded in the 'compile()' procedure
    in the following section.
 */

// It might be possible to have the parser transparently skip any whitespace c[] tokens
// while parsing.  Then with cooperation from the lexer we can actually store the white space
// on a line-by-line basis, thus allowing full source reconstruction for error reporting,
// code listings etc.  Maybe just:  while (c[cp].t == TYPE_WHITESPACE) cp += 1;

#define MAX_PARSE_SIZE 1000000
static int A[MAX_PARSE_SIZE];
static char *c; // points to line-reconstructed source text
static int next_free_a = 0;
int fp = 0;  // size of source text in bytes
int cp = 0;  // code pointer.  Has to be global state.
int ap = 0;  // Analysis record pointer.
int bestparse = -1;
char *looking_for = "<UNKNOWN>";

#define SP "                                                            "

#define DROP_SPECIAL_BITS ((1<<14)-1)
#define NEGATED_PHRASE (1<<15)
#define OPTIONAL_PHRASE (1<<14)

int Parse_BIP(int pp, int *cp, int depth) { // parsed on the fly ...
  if (debug_parser) fprintf(stderr, "%.*s>> BIP(@%d, %s)\n", depth*3, SP, *cp, phrasename[pp-512]);
  int ocp = *cp;
  switch (pp-512) {
//\\ B<EOD> = 0;
  case B_EOD:
    if (*cp == fp) {
      return TRUE; // replace when we use memmap, and have an end pointer.
    }
    break;

//\\ B<NAME> = 1;
  case B_NAME:
    if (isalpha(c[*cp]) && isupper(c[*cp])) {
      for (;;) {
        (*cp)++;
	if (!((isalpha(c[*cp]) && isupper(c[*cp]))
	      || isdigit(c[*cp]) || (c[*cp] == '\''))) {
	  if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> %.*s\n", depth*3, SP, *cp, phrasename[pp-512], *cp-ocp, &c[ocp]);
	  return TRUE;
	}
      }
    }
    break;

//\\ B<N> = 2;
  case B_N:
    if (isdigit(c[*cp])) {
      for (;;) {
        (*cp)++;
	if (!isdigit(c[*cp])) {
	  if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> %.*s\n", depth*3, SP, *cp, phrasename[pp-512], *cp-ocp, &c[ocp]);
	  return TRUE;
	}
      }
    }
    break;

//\\ B<OCTAL> = 3;
  case B_OCTAL:
    if (isoctal(c[*cp])) {
      for (;;) {
        (*cp)++;
	if (!isoctal(c[*cp])) {
	  if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> %.*s\n", depth*3, SP, *cp, phrasename[pp-512], *cp-ocp, &c[ocp]);
	  return TRUE;
	}
      }
    }
    break;

//\\ B<SETMARKER1> = 4;
  case B_SETMARKER1:
    if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> TRUE\n", depth*3, SP, *cp, phrasename[pp-512]);
    return TRUE;

//\\ B<SETMARKER2> = 5;
  case B_SETMARKER2:
    if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> TRUE\n", depth*3, SP, *cp, phrasename[pp-512]);
    return TRUE;

//\\ B<S> = 6;
  case B_S:
    if (c[*cp] == '\n') { // ';' already translated during line reconstruction
      (*cp)++;
      if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> \'\\n\'\n", depth*3, SP, *cp, phrasename[pp-512]);
      return TRUE;
    }
    break;

//\\ B<TEXT> = 7;
  case B_TEXT:  
    for (;;) {
      if (c[(*cp)++] == '\n') break;
    }
    if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> %.*s\n", depth*3, SP, *cp, phrasename[pp-512], *cp-ocp, &c[ocp]);
    return TRUE;

//\\ B<CAPTIONTEXT> = 8;
  case B_CAPTIONTEXT:
    for (;;) {
      if (c[*cp] == '\n') break;
      int ch = c[(*cp)++];
    }
    if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> %.*s\n", depth*3, SP, *cp, phrasename[pp-512], *cp-ocp, &c[ocp]);
    return TRUE;

//\\ B<CONST> = 9;
  case B_CONST:
    if (isdigit(c[*cp])) {
      for (;;) {
        (*cp)++;
	if (!isdigit(c[*cp])) {
	  if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> %.*s\n", depth*3, SP, *cp, phrasename[pp-512], *cp-ocp, &c[ocp]);
	  return TRUE;
	}
      }
    } else if ((c[*cp] == '\'') && (c[(*cp)+1] != '\'') && (c[(*cp)+2] == '\'')) {
        (*cp) += 3;
        if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> %.*s\n", depth*3, SP, *cp, phrasename[pp-512], 3, &c[ocp]);
        return TRUE;
    }
    break;

  default:
    fprintf(stderr, "Bad BIP(%d)\n", pp); exit(1);
  }
  if (debug_parser) fprintf(stderr, "%.*s<< BIP(@%d, %s) -> FAIL\n", depth*3, SP, *cp, phrasename[pp-512]);
  return FALSE;
}

int parse(int pp, int depth) // depth is only for indentation in diags
{
  /*  Main parsing procedure.  This is a table-driven parser, with the tables
      being generated from the grammar rules embedded in the 'compile' procedure
      below.  The result of the parse is a tree structure, and the values of the
      nodes in the tree structure are used to drive a large 'case' statement
      which selects the actions to be performed after a successful parse.

      There is no grammatical structure embedded in this procedure.  If you're
      looking for the grammar definition, see the procedure called 'compile' instead.
   */
  int saved_cp;
  int saved_ap;
  int i;
  int gp;
  int alts;
  int match;
  // char saved_desc[256];

  /*  Initialisation */
  gp = phrase_start[pp-512-MAX_BIP];
  alts = gram[gp];
  gp++; // gp now points to first element (length) of first alt

  saved_cp = cp;
  saved_ap = ap;
  
  if (debug_parser) fprintf(stderr, "%.*s>> parse(@%d, %s)\n", depth*3, SP, cp, phrasename[pp-512]);
  for (i = 0; i < alts; i++) {
    /*  Starting with the root phrase, recursively examine each alternative */
    int each;
    int phrases = gram[gp++];
    int phrase_count;
    int gap = 0;

    if (debug_parser) fprintf(stderr, "%.*s%s Alt %d\n", depth*3+3, SP, phrasename[pp-512], i);

    cp = saved_cp;
    ap = saved_ap;

    if (ap+3 > next_free_a) next_free_a = ap+3;

    A[ap++] = pp;   // record which phrase (could be done outside loop)
    A[ap++] = i;    // and which alt.

    // Count slots needed.  *Could* be precalculated and stored
    // in the grammar, either embedded (after the ALT) or as a
    // separate table

    for (each = 0; each < phrases; each++) if (gram[gp+each] >= 512) gap++;

    A[ap++] = gap;    // Count of alts (gap)
    // ap+gap now points to the slot after the space required, which
    // is where the first subphrase will be stored.
    ap = ap+gap; // recursive subphrases are stored after this phrase.
                 // ap is left updated if successful.


    // successfully parsed phrases are stored in A[saved_ap+3+n]

    if (saved_ap+3+gap > next_free_a) next_free_a = saved_ap+3+gap;

    match = TRUE; // stays true if all subphrases match
    phrase_count = 0; // only phrases which make it into the A record,
                      // i.e. excluding literals and keywords
    for (each = 0; each < phrases; each++) {
      /*  Within a single grammar rule (alternative), ensure that each subphrase is present */
      int phrase = gram[gp+each] & DROP_SPECIAL_BITS;
      int optional_phrase = gram[gp+each] & OPTIONAL_PHRASE;
      int negated_phrase = gram[gp+each] & NEGATED_PHRASE;

      if (cp > bestparse) {
        static char s[128]; // off heap instead?  - binary size

        // this is used in reporting syntax errors.
        // we get better diags if DEBUG_PARSER_PARSER is true
        if (phrase < 256) {
          sprintf(s, "'%c'", phrase);
        } else if (phrase < 512) {
          sprintf(s, "\"%s\"", keyword[phrase-256]);
        } else if (phrase < 512+MAX_BIP) {
#ifdef EXTENDED_ERROR_REPORTING
          sprintf(s, "{%s}", phrasename[phrase-512]);
#else
          //sprintf(s, "{BIP %d}", phrase-512);
#endif
        } else {
#ifdef EXTENDED_ERROR_REPORTING
          sprintf(s, "<%s>", phrasename[phrase-512]);
#else
          //sprintf(s, "<Phrase %d>", phrase-512);
#endif
        }
        looking_for = s;
        bestparse = cp;
      }

      if (phrase < 256) {
	/*  Literal */
        fprintf(stderr, "Bug - should not be any literals in this grammar\n");exit(1);
        // Don't record literals        
      } else if (phrase < 512) {
	/*  Keyword */
        if (strncmp(keyword[phrase-256], c+cp, strlen(keyword[phrase-256]))) {
          if (debug_parser) fprintf(stderr, "%.*sNo Match \'%s\'\n", depth*3+3, SP, keyword[phrase-256]);
          match = FALSE;
        } else {
          if (debug_parser) fprintf(stderr, "%.*sMatch \'%s\' \'%.*s\'\n", depth*3+3, SP, keyword[phrase-256], (int)strlen(keyword[phrase-256]), c+cp);
          cp+=strlen(keyword[phrase-256]);
	}
        // Don't record keywords
      } else if (phrase < 512+MAX_BIP) {
	/*  Built-in phrase */
        int where = ap; // next phrase to be parsed will be stored at current 'ap'.
        int ocp = cp;
	// BUG: BIPS should also allow <?...> and <!...> as users won't distinguish BIPs from phrases
        if (Parse_BIP(phrase, &cp, depth+1)) { // parsed on the fly ...
          A[ap++] = phrase;
          A[ap++] = 1; // always alt 1
          A[ap++] = 2; // store 2 value in tuple
          A[ap++] = cp-ocp; // length of string
          A[ap++] = ocp; // index of text in c[] array
          A[saved_ap+3+phrase_count++] = where; // Record BIP
        } else match = FALSE;
      } else {
	/*  Recursive call to parser for a subphrase */
        int where = ap; // next phrase to be parsed will be stored at current 'ap'.
        if (negated_phrase) {
          int here = cp;
          if (!parse(phrase, depth+1)) {
            A[saved_ap+3+phrase_count++] = -1; // was 'where'
          } else {
            match = FALSE;
	  }
          cp = here; // negated phrase never consumes any input
	} else if (optional_phrase) {	
          int input_stream_pos = cp;
          if (parse(phrase, depth+1)) {
            A[saved_ap+3+phrase_count++] = where;
            cp = input_stream_pos; // now re-parse the input stream with the following alts
          } else {
            match = FALSE;
	  }
        } else {
          if (parse(phrase, depth+1)) {
            A[saved_ap+3+phrase_count++] = where;
          } else {
            match = FALSE;
	  }
        }
      }
      
      if (!match) break;
      
    }
    gp += phrases; // move over all phrases, to next alt

    if (match) break;

    // gp now points to first element (length) of next alt, or start of next phrase
    
  }

  if (debug_parser) fprintf(stderr, "%.*s<< parse(%s) -> %s\n", depth*3, SP, phrasename[pp-512], match?"SUCCEED":"FAIL");
  return(match);
  }



static int nexttuple = 0;
static int AST[1024*1024];

#define OVERHEAD 4
int SETMARKER2(int ap) { return 0; }
int mktuple(int P, int alt, int phrases, int *T) {
  int i, tuple;
  tuple = nexttuple;
  nexttuple = tuple + OVERHEAD + 1 + phrases;
  AST[tuple+0] = P;
  AST[tuple+1] = alt;
  AST[tuple+2] = 2222;
  AST[tuple+3] = 3333;
  // Needed later:
  // +2 next sequential statement
  // +3 previous sequential statement
  AST[tuple+OVERHEAD] = phrases;        // redundant points to itself I think.  Ignore.
  for (i = 1; i <= phrases; i++) {       // if phrases == 0 then T can be NULL
    AST[tuple+OVERHEAD+i] = T[i];     // phrases 1,2,3, ... indexed by AST[p+OVERHEAD+1,2,3, ...]
  }
  return tuple;
}

// NOTE: if we mmap the source rather than loading it, writing back to the source text
// will fail.  In which case either convert ' to _ in the line reconstruction filter stage,
// or filter on every occurance of outputting a NAME.
void translate_hack(int len, int base, char from, char to)
{
  int i;
  for (i = 0; i < len; i++) {
    if (c[base+i] == from) c[base+i] = to;
  }
}

int kw(int key)         { int T[2]; T[1] = key;                            return mktuple(-1, 0, 1, T); }
int NAME(int ap)        { int T[3]; T[1] = A[A[ap]+3]; T[2] = A[A[ap]+4];
                          translate_hack(T[1],T[2],'\'','_');              return mktuple(P_NAME, 0, 2, T); }
int N(int ap)           { int T[3]; T[1] = A[A[ap]+3]; T[2] = A[A[ap]+4];  return mktuple(P_N, 0, 2, T); }
int S(int ap)           { int T[3]; T[1] = A[A[ap]+3]; T[2] = A[A[ap]+4];  return mktuple(P_S, 0, 2, T); }
int TEXT(int ap)        { int T[3]; T[1] = A[A[ap]+3]; T[2] = A[A[ap]+4];  return mktuple(P_TEXT, 0, 2, T); }
int CONST(int ap)       { int T[3]; T[1] = A[A[ap]+3]; T[2] = A[A[ap]+4];  return mktuple(P_CONST, 0, 2, T); }
int OCTAL(int ap)       { int T[3]; T[1] = A[A[ap]+3]; T[2] = A[A[ap]+4];  return mktuple(P_OCTAL, 0, 2, T); }
int SETMARKER1(int ap)  { int T[3]; T[1] = A[A[ap]+3]; T[2] = A[A[ap]+4];  return mktuple(P_SETMARKER1, 0, 2, T); }
int CAPTIONTEXT(int ap) { int T[3]; T[1] = A[A[ap]+3]; T[2] = A[A[ap]+4];  
                          translate_hack(T[1],T[2],'\\','\n');
                          translate_hack(T[1],T[2],'_',' ');               return mktuple(P_CAPTIONTEXT, 0, 2, T); }

char *CaptionTextFixupHack(int len, char *s) {
  static char line[128], *t;
  int i;
  if (len > 127) {
    fprintf(stderr, "hack #1 insufficient\n"); exit(1);
  }
  t = line;
  for (i = 0; i < len; i++) {
    if (*s == '\0') break;
    if (*s == '\n') {
      *t++ = '\\'; *t++ = 'n'; s +=1;
    } else *t++ = *s++;
  }
  *t = '\0';
  return line;
}

char *ConstFixupHack(int len, char *s) {
  static char line[128], *t;
  int i;
  if (len > 127) {
    fprintf(stderr, "hack #1 insufficient\n"); exit(1);
  }
  t = line;
  for (i = 0; i < len; i++) {
    if (*s == '\0') break;
    if (*s == '\\') {
      *t++ = '\\'; *t++ = '\\'; s += 1;
    } else *t++ = *s++;
  }
  *t = '\0';
  return line;
}

int build_ast(int ap, int depth) {
  int T[100];

  int saved_ap;
  int phrase;  // A[ap] is the phrase number. A[ap+1] is the alt.
  int alt;     // For consistency, in BIPs, the Alt should always be 1
               // although that may not be the case at the moment :-(
  int phrases; // defined subphrases

  //fprintf(stdout, "\"grammar.c\", %d: build_ast(%d);\n", caller, ap);

  saved_ap = ap;
  phrase = A[ap++] & DROP_SPECIAL_BITS;
  alt = A[ap++];
  phrases = A[ap++];

  if ((phrase < 512) || (phrase > MAX_PHRASE+512)) {
    fprintf(stderr, "* Internal error: build_ast(%d) - phrase = %d\n",
            ap, phrase); exit(1);
  }

  switch (phrase) { 
//\\ P<SS> = 
//\\    <UI> <SETMARKER2> <RESTOF_SS1>,
//\\    "cycle" <NAME> <APP> "=" <Opt_Plus> <OPERAND> <RESTOF_EXPR> "," <Opt_Plus> <OPERAND> <RESTOF_EXPR> "," <Opt_Plus> <OPERAND> <RESTOF_EXPR> <S>,
//\\    "repeat" <S>,
//\\    <N> ":",
//\\    <Percent_IU> <SC> <RESTOF_COND> "then" <UI> <S>,
//\\    "!" <TEXT>,
//\\    <TYPE> <NAME> <RESTOF_NAMELIST> <S>,
//\\    "end" <S>,
//\\    <RT> <Opt_Percent_SPEC> <NAME> <FPP> <S>,
//\\    "spec" <NAME> <FPP> <S>,
//\\    "comment" <TEXT>,
//\\    <Opt_TYPE> "array" <NAME> <RESTOF_NAMELIST> "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> ":" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_FPP_LIST> ")" <RESTOF_ARRAYLIST> <S>,
//\\    "***A" <S>,
//\\    "begin" <S>,
//\\    "endofprogram",
//\\    "uppercasedelimiters" <S>,
//\\    <NAME> "(" <Opt_Plus> <CONST> "):",
//\\    "switch" <NAME> <RESTOF_NAMELIST> "(" <Opt_Plus> <CONST> ":" <CONST> ")" <RESTOF_SWITCHLIST> <S>,
//\\    "compilequeries" <S>,
//\\    "ignorequeries" <S>,
//\\    "mcode" <S>,
//\\    <N> "P:",
//\\    "*" <UCI> <S>,
//\\    "fault" <N> <RESTOF_FN_LIST> "->" <N> <RESTOF_FAULTLIST> <S>,
//\\    "normaldelimiters" <S>,
//\\    "strings" <S>,
//\\    "endofperm" <S>,
//\\    "endofmcode" <S>,
//\\    "definecompiler" <S>,
//\\    <S>,
//\\    <EOD>;

case P_SS:
  if (alt == 0)        {
    T[1] = build_ast(A[ap+0], depth+1); // <UI>
    T[2] = SETMARKER2(ap+1);
    T[3] = build_ast(A[ap+2], depth+1); // <RESTOF_SS1>
    T[0] = mktuple(phrase /*P_SS*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);

    if (AST[T[3]+1] == 1) { // alt 1 of <RESTOF_SS1>
      int ui = T[1];
      int restof_ss1 = T[3]; // now points to: <Percent_IU> <SC> <RESTOF_COND> <S>;
      // Reversed if or unless statement.  Turn them around here, it's easier.

      /* <UI> if or unless ... - change it to read:  if or unless ... then <UI> */
      alt = 4;  
      T[1] = AST[restof_ss1+OVERHEAD+1]; // <Percent_IU>
      T[2] = AST[restof_ss1+OVERHEAD+2]; // <SC>
      T[3] = AST[restof_ss1+OVERHEAD+3]; // <RESTOF_COND>
      T[4] = kw(/*"then"*/ 5);
      T[5] = ui; // <UI>
      T[6] = AST[restof_ss1+OVERHEAD+4];
      T[0] = mktuple(phrase /*P_SS*/, alt /*5*/, /*phrases*/ 6, T /*T[1], T[2], T[3], T[4], T[5], T[6]*/);
    }



  } else if (alt == 1) {
    T[1] = kw(/*"cycle"*/ 0);
    T[2] = NAME(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <APP>
    T[4] = kw(/*"="*/ 1);
    T[5] = build_ast(A[ap+2], depth+1); // <Opt_Plus>
    T[6] = build_ast(A[ap+3], depth+1); // <OPERAND>
    T[7] = build_ast(A[ap+4], depth+1); // <RESTOF_EXPR>
    T[8] = kw(/*","*/ 2);
    T[9] = build_ast(A[ap+5], depth+1); // <Opt_Plus>
    T[10] = build_ast(A[ap+6], depth+1); // <OPERAND>
    T[11] = build_ast(A[ap+7], depth+1); // <RESTOF_EXPR>
    T[12] = kw(/*","*/ 2);
    T[13] = build_ast(A[ap+8], depth+1); // <Opt_Plus>
    T[14] = build_ast(A[ap+9], depth+1); // <OPERAND>
    T[15] = build_ast(A[ap+10], depth+1); // <RESTOF_EXPR>
    T[16] = S(ap+11);
    T[0] = mktuple(phrase /*P_SS*/, alt /*2*/, /*phrases*/ 16, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10], T[11], T[12], T[13], T[14], T[15], T[16]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"repeat"*/ 3);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*3*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 3) {
    T[1] = N(ap+0);
    T[2] = kw(/*":"*/ 4);
    T[0] = mktuple(phrase /*P_SS*/, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 4) {
    T[1] = build_ast(A[ap+0], depth+1); // <Percent_IU>
    T[2] = build_ast(A[ap+1], depth+1); // <SC>
    T[3] = build_ast(A[ap+2], depth+1); // <RESTOF_COND>
    T[4] = kw(/*"then"*/ 5);
    T[5] = build_ast(A[ap+3], depth+1); // <UI>
    T[6] = S(ap+4);
    T[0] = mktuple(phrase /*P_SS*/, alt /*5*/, /*phrases*/ 6, T /*T[1], T[2], T[3], T[4], T[5], T[6]*/);
  } else if (alt == 5) {
    T[1] = kw(/*"!"*/ 6);
    T[2] = TEXT(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*6*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 6) {
    T[1] = build_ast(A[ap+0], depth+1); // <TYPE>
    T[2] = NAME(ap+1);
    T[3] = build_ast(A[ap+2], depth+1); // <RESTOF_NAMELIST>
    T[4] = S(ap+3);
    T[0] = mktuple(phrase /*P_SS*/, alt /*7*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 7) {
    T[1] = kw(/*"end"*/ 7);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*8*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 8) {
    T[1] = build_ast(A[ap+0], depth+1); // <RT>
    T[2] = build_ast(A[ap+1], depth+1); // <Opt_Percent_SPEC>
    T[3] = NAME(ap+2);
    T[4] = build_ast(A[ap+3], depth+1); // <FPP>
    T[5] = S(ap+4);
    T[0] = mktuple(phrase /*P_SS*/, alt /*9*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  } else if (alt == 9) {
    T[1] = kw(/*"spec"*/ 8);
    T[2] = NAME(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <FPP>
    T[4] = S(ap+2);
    T[0] = mktuple(phrase /*P_SS*/, alt /*10*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 10) {
    T[1] = kw(/*"comment"*/ 9);
    T[2] = TEXT(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*11*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 11) {
    T[1] = build_ast(A[ap+0], depth+1); // <Opt_TYPE>
    T[2] = kw(/*"array"*/ 10);
    T[3] = NAME(ap+1);
    T[4] = build_ast(A[ap+2], depth+1); // <RESTOF_NAMELIST>
    T[5] = kw(/*"("*/ 11);
    T[6] = build_ast(A[ap+3], depth+1); // <Opt_Plus>
    T[7] = build_ast(A[ap+4], depth+1); // <OPERAND>
    T[8] = build_ast(A[ap+5], depth+1); // <RESTOF_EXPR>
    T[9] = kw(/*":"*/ 4);
    T[10] = build_ast(A[ap+6], depth+1); // <Opt_Plus>
    T[11] = build_ast(A[ap+7], depth+1); // <OPERAND>
    T[12] = build_ast(A[ap+8], depth+1); // <RESTOF_EXPR>
    T[13] = build_ast(A[ap+9], depth+1); // <RESTOF_FPP_LIST>
    T[14] = kw(/*")"*/ 12);
    T[15] = build_ast(A[ap+10], depth+1); // <RESTOF_ARRAYLIST>
    T[16] = S(ap+11);
    T[0] = mktuple(phrase /*P_SS*/, alt /*12*/, /*phrases*/ 16, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10], T[11], T[12], T[13], T[14], T[15], T[16]*/);
  } else if (alt == 12) {
    T[1] = kw(/*"***A"*/ 13);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*13*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 13) {
    T[1] = kw(/*"begin"*/ 14);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*14*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 14) {
    T[1] = kw(/*"endofprogram"*/ 15);
    T[0] = mktuple(phrase /*P_SS*/, alt /*15*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 15) {
    T[1] = kw(/*"uppercasedelimiters"*/ 16);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*16*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 16) {
    T[1] = NAME(ap+0);
    T[2] = kw(/*"("*/ 11);
    T[3] = build_ast(A[ap+1], depth+1); // <Opt_Plus>
    T[4] = CONST(ap+2);
    T[5] = kw(/*"):"*/ 17);
    T[0] = mktuple(phrase /*P_SS*/, alt /*17*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  } else if (alt == 17) {
    T[1] = kw(/*"switch"*/ 18);
    T[2] = NAME(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <RESTOF_NAMELIST>
    T[4] = kw(/*"("*/ 11);
    T[5] = build_ast(A[ap+2], depth+1); // <Opt_Plus>
    T[6] = CONST(ap+3);
    T[7] = kw(/*":"*/ 4);
    T[8] = CONST(ap+4);
    T[9] = kw(/*")"*/ 12);
    T[10] = build_ast(A[ap+5], depth+1); // <RESTOF_SWITCHLIST>
    T[11] = S(ap+6);
    T[0] = mktuple(phrase /*P_SS*/, alt /*18*/, /*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 if (alt == 18) {
    T[1] = kw(/*"compilequeries"*/ 19);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*19*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 19) {
    T[1] = kw(/*"ignorequeries"*/ 20);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*20*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 20) {
    T[1] = kw(/*"mcode"*/ 21);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*21*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 21) {
    T[1] = N(ap+0);
    T[2] = kw(/*"P:"*/ 22);
    T[0] = mktuple(phrase /*P_SS*/, alt /*22*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 22) {
    T[1] = kw(/*"*"*/ 23);
    T[2] = build_ast(A[ap+0], depth+1); // <UCI>
    T[3] = S(ap+1);
    T[0] = mktuple(phrase /*P_SS*/, alt /*23*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 23) {
    T[1] = kw(/*"fault"*/ 24);
    T[2] = N(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <RESTOF_FN_LIST>
    T[4] = kw(/*"->"*/ 25);
    T[5] = N(ap+2);
    T[6] = build_ast(A[ap+3], depth+1); // <RESTOF_FAULTLIST>
    T[7] = S(ap+4);
    T[0] = mktuple(phrase /*P_SS*/, alt /*24*/, /*phrases*/ 7, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7]*/);
  } else if (alt == 24) {
    T[1] = kw(/*"normaldelimiters"*/ 26);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*25*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 25) {
    T[1] = kw(/*"strings"*/ 27);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*26*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 26) {
    T[1] = kw(/*"endofperm"*/ 28);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*27*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 27) {
    T[1] = kw(/*"endofmcode"*/ 29);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*28*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 28) {
    T[1] = kw(/*"definecompiler"*/ 30);
    T[2] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*29*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[1] = S(ap+0);
    T[0] = mktuple(phrase /*P_SS*/, alt /*30*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];



 
//\\ P<Opt_Plus> = 
//\\    "+",
//\\    "-",
//\\   ;

case P_Opt_Plus:
  if (alt == 0)        {
    T[1] = kw(/*"+"*/ 31);
    T[0] = mktuple(phrase /*P_Opt_Plus*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"-"*/ 32);
    T[0] = mktuple(phrase /*P_Opt_Plus*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[0] = mktuple(phrase /*P_Opt_Plus*/, alt /*3*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<OPERAND> = 
//\\    <NAME> <APP>,
//\\    <CONST>,
//\\    "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> ")",
//\\    "!" <Opt_Plus> <OPERAND> <RESTOF_EXPR> "!";

case P_OPERAND:
  if (alt == 0)        {
    T[1] = NAME(ap+0);
    T[2] = build_ast(A[ap+1], depth+1); // <APP>
    T[0] = mktuple(phrase /*P_OPERAND*/, alt /*1*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 1) {
    T[1] = CONST(ap+0);
    T[0] = mktuple(phrase /*P_OPERAND*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"("*/ 11);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = build_ast(A[ap+1], depth+1); // <OPERAND>
    T[4] = build_ast(A[ap+2], depth+1); // <RESTOF_EXPR>
    T[5] = kw(/*")"*/ 12);
    T[0] = mktuple(phrase /*P_OPERAND*/, alt /*3*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  } else               {
    T[1] = kw(/*"!"*/ 6);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = build_ast(A[ap+1], depth+1); // <OPERAND>
    T[4] = build_ast(A[ap+2], depth+1); // <RESTOF_EXPR>
    T[5] = kw(/*"!"*/ 6);
    T[0] = mktuple(phrase /*P_OPERAND*/, alt /*4*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  }
  return T[0];



 
//\\ P<RESTOF_EXPR> = 
//\\    <OP> <OPERAND> <RESTOF_EXPR>,
//\\   ;

case P_RESTOF_EXPR:
  if (alt == 0)        {
    T[1] = build_ast(A[ap+0], depth+1); // <OP>
    T[2] = build_ast(A[ap+1], depth+1); // <OPERAND>
    T[3] = build_ast(A[ap+2], depth+1); // <RESTOF_EXPR>
    T[0] = mktuple(phrase /*P_RESTOF_EXPR*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_EXPR*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<APP> = 
//\\    "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_EXPR_LIST> ")",
//\\   ;

case P_APP:
  if (alt == 0)        {
    T[1] = kw(/*"("*/ 11);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = build_ast(A[ap+1], depth+1); // <OPERAND>
    T[4] = build_ast(A[ap+2], depth+1); // <RESTOF_EXPR>
    T[5] = build_ast(A[ap+3], depth+1); // <RESTOF_EXPR_LIST>
    T[6] = kw(/*")"*/ 12);
    T[0] = mktuple(phrase /*P_APP*/, alt /*1*/, /*phrases*/ 6, T /*T[1], T[2], T[3], T[4], T[5], T[6]*/);
  } else               {
    T[0] = mktuple(phrase /*P_APP*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<RESTOF_EXPR_LIST> = 
//\\    "," <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_EXPR_LIST>,
//\\   ;

case P_RESTOF_EXPR_LIST:
  if (alt == 0)        {
    T[1] = kw(/*","*/ 2);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = build_ast(A[ap+1], depth+1); // <OPERAND>
    T[4] = build_ast(A[ap+2], depth+1); // <RESTOF_EXPR>
    T[5] = build_ast(A[ap+3], depth+1); // <RESTOF_EXPR_LIST>
    T[0] = mktuple(phrase /*P_RESTOF_EXPR_LIST*/, alt /*1*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_EXPR_LIST*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<OP> = 
//\\    "+",
//\\    "-",
//\\    "*",
//\\    "/",
//\\    "^"
//\\   ;

// there was a final NUL alt above.  Could that have been the implied multiplication???
// Is it even used in the AA source?

case P_OP:
  if (alt == 0)        {
    T[1] = kw(/*"+"*/ 31);
    T[0] = mktuple(phrase /*P_OP*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"-"*/ 32);
    T[0] = mktuple(phrase /*P_OP*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"*"*/ 23);
    T[0] = mktuple(phrase /*P_OP*/, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"/"*/ 33);
    T[0] = mktuple(phrase /*P_OP*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"^"*/ 34);
    T[0] = mktuple(phrase /*P_OP*/, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[0] = mktuple(phrase /*P_OP*/, alt /*6*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<Opt_QUERY> = 
//\\    "?",
//\\   ;

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



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

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



 
//\\ P<Percent_IU> = 
//\\    "if",
//\\    "unless";

case P_Percent_IU:
  if (alt == 0)        {
    T[1] = kw(/*"if"*/ 36);
    T[0] = mktuple(phrase /*P_Percent_IU*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = kw(/*"unless"*/ 37);
    T[0] = mktuple(phrase /*P_Percent_IU*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];



 
//\\ P<Opt_Percent_REAL> = 
//\\    "real",
//\\   ;

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



 
//\\ P<TYPE> = 
//\\    "integer",
//\\    "real";

case P_TYPE:
  if (alt == 0)        {
    T[1] = kw(/*"integer"*/ 39);
    T[0] = mktuple(phrase /*P_TYPE*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = kw(/*"real"*/ 38);
    T[0] = mktuple(phrase /*P_TYPE*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];



 
//\\ P<Opt_TYPE> = 
//\\    "integer",
//\\    "real",
//\\   ;

case P_Opt_TYPE:
  if (alt == 0)        {
    T[1] = kw(/*"integer"*/ 39);
    T[0] = mktuple(phrase /*P_Opt_TYPE*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"real"*/ 38);
    T[0] = mktuple(phrase /*P_Opt_TYPE*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[0] = mktuple(phrase /*P_Opt_TYPE*/, alt /*3*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<RT> = 
//\\    "routine",
//\\    "realfn",
//\\    "integerfn",
//\\    "realmap",
//\\    "integermap";

case P_RT:
  if (alt == 0)        {
    T[1] = kw(/*"routine"*/ 40);
    T[0] = mktuple(phrase /*P_RT*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"realfn"*/ 41);
    T[0] = mktuple(phrase /*P_RT*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"integerfn"*/ 42);
    T[0] = mktuple(phrase /*P_RT*/, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"realmap"*/ 43);
    T[0] = mktuple(phrase /*P_RT*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = kw(/*"integermap"*/ 44);
    T[0] = mktuple(phrase /*P_RT*/, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];



 
//\\ P<FP_DELIMITER> = 
//\\    <RT>,
//\\    "integerarrayname",
//\\    "integername",
//\\    "integer",
//\\    <Opt_Percent_REAL> "arrayname",
//\\    "realname",
//\\    "real",
//\\    "addr";

case P_FP_DELIMITER:
  if (alt == 0)        {
    T[1] = build_ast(A[ap+0], depth+1); // <RT>
    T[0] = mktuple(phrase /*P_FP_DELIMITER*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"integerarrayname"*/ 45);
    T[0] = mktuple(phrase /*P_FP_DELIMITER*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"integername"*/ 46);
    T[0] = mktuple(phrase /*P_FP_DELIMITER*/, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"integer"*/ 39);
    T[0] = mktuple(phrase /*P_FP_DELIMITER*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 4) {
    T[1] = build_ast(A[ap+0], depth+1); // <Opt_Percent_REAL>
    T[2] = kw(/*"arrayname"*/ 47);
    T[0] = mktuple(phrase /*P_FP_DELIMITER*/, alt /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 5) {
    T[1] = kw(/*"realname"*/ 48);
    T[0] = mktuple(phrase /*P_FP_DELIMITER*/, alt /*6*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 6) {
    T[1] = kw(/*"real"*/ 38);
    T[0] = mktuple(phrase /*P_FP_DELIMITER*/, alt /*7*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = kw(/*"addr"*/ 49);
    T[0] = mktuple(phrase /*P_FP_DELIMITER*/, alt /*8*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];



 
//\\ P<FPP> = 
//\\    "(" <FP_DELIMITER> <NAME> <RESTOF_NAMELIST> <RESTOF_FP_LIST> ")",
//\\   ;

case P_FPP:
  if (alt == 0)        {
    T[1] = kw(/*"("*/ 11);
    T[2] = build_ast(A[ap+0], depth+1); // <FP_DELIMITER>
    T[3] = NAME(ap+1);
    T[4] = build_ast(A[ap+2], depth+1); // <RESTOF_NAMELIST>
    T[5] = build_ast(A[ap+3], depth+1); // <RESTOF_FP_LIST>
    T[6] = kw(/*")"*/ 12);
    T[0] = mktuple(phrase /*P_FPP*/, alt /*1*/, /*phrases*/ 6, T /*T[1], T[2], T[3], T[4], T[5], T[6]*/);
  } else               {
    T[0] = mktuple(phrase /*P_FPP*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<RESTOF_FP_LIST> = 
//\\    <Opt_Comma> <FP_DELIMITER> <NAME> <RESTOF_NAMELIST> <RESTOF_FP_LIST>,
//\\   ;

case P_RESTOF_FP_LIST:
  if (alt == 0)        {
    T[1] = build_ast(A[ap+0], depth+1); // <Opt_Comma>
    T[2] = build_ast(A[ap+1], depth+1); // <FP_DELIMITER>
    T[3] = NAME(ap+2);
    T[4] = build_ast(A[ap+3], depth+1); // <RESTOF_NAMELIST>
    T[5] = build_ast(A[ap+4], depth+1); // <RESTOF_FP_LIST>
    T[0] = mktuple(phrase /*P_RESTOF_FP_LIST*/, alt /*1*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_FP_LIST*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<RESTOF_NAMELIST> = 
//\\    "," <NAME> <RESTOF_NAMELIST>,
//\\   ;

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



 
//\\ P<SC> = 
//\\    <Opt_Plus> <OPERAND> <RESTOF_EXPR> <COMP> <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_SC>,
//\\    "(" <SC> <RESTOF_COND> ")";

case P_SC:
  if (alt == 0)        {
    T[1] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[2] = build_ast(A[ap+1], depth+1); // <OPERAND>
    T[3] = build_ast(A[ap+2], depth+1); // <RESTOF_EXPR>
    T[4] = build_ast(A[ap+3], depth+1); // <COMP>
    T[5] = build_ast(A[ap+4], depth+1); // <Opt_Plus>
    T[6] = build_ast(A[ap+5], depth+1); // <OPERAND>
    T[7] = build_ast(A[ap+6], depth+1); // <RESTOF_EXPR>
    T[8] = build_ast(A[ap+7], depth+1); // <RESTOF_SC>
    T[0] = mktuple(phrase /*P_SC*/, alt /*1*/, /*phrases*/ 8, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8]*/);
  } else               {
    T[1] = kw(/*"("*/ 11);
    T[2] = build_ast(A[ap+0], depth+1); // <SC>
    T[3] = build_ast(A[ap+1], depth+1); // <RESTOF_COND>
    T[4] = kw(/*")"*/ 12);
    T[0] = mktuple(phrase /*P_SC*/, alt /*2*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  }
  return T[0];



 
//\\ P<RESTOF_SC> = 
//\\    <COMP> <Opt_Plus> <OPERAND> <RESTOF_EXPR>,
//\\   ;

case P_RESTOF_SC:
  if (alt == 0)        {
    T[1] = build_ast(A[ap+0], depth+1); // <COMP>
    T[2] = build_ast(A[ap+1], depth+1); // <Opt_Plus>
    T[3] = build_ast(A[ap+2], depth+1); // <OPERAND>
    T[4] = build_ast(A[ap+3], depth+1); // <RESTOF_EXPR>
    T[0] = mktuple(phrase /*P_RESTOF_SC*/, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_SC*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<RESTOF_COND> = 
//\\    "and" <SC> <RESTOF_AND_C>,
//\\    "or" <SC> <RESTOF_OR_C>,
//\\   ;

case P_RESTOF_COND:
  if (alt == 0)        {
    T[1] = kw(/*"and"*/ 50);
    T[2] = build_ast(A[ap+0], depth+1); // <SC>
    T[3] = build_ast(A[ap+1], depth+1); // <RESTOF_AND_C>
    T[0] = mktuple(phrase /*P_RESTOF_COND*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"or"*/ 51);
    T[2] = build_ast(A[ap+0], depth+1); // <SC>
    T[3] = build_ast(A[ap+1], depth+1); // <RESTOF_OR_C>
    T[0] = mktuple(phrase /*P_RESTOF_COND*/, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_COND*/, alt /*3*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<RESTOF_AND_C> = 
//\\    "and" <SC> <RESTOF_AND_C>,
//\\   ;

case P_RESTOF_AND_C:
  if (alt == 0)        {
    T[1] = kw(/*"and"*/ 50);
    T[2] = build_ast(A[ap+0], depth+1); // <SC>
    T[3] = build_ast(A[ap+1], depth+1); // <RESTOF_AND_C>
    T[0] = mktuple(phrase /*P_RESTOF_AND_C*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_AND_C*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<RESTOF_OR_C> = 
//\\    "or" <SC> <RESTOF_OR_C>,
//\\   ;

case P_RESTOF_OR_C:
  if (alt == 0)        {
    T[1] = kw(/*"or"*/ 51);
    T[2] = build_ast(A[ap+0], depth+1); // <SC>
    T[3] = build_ast(A[ap+1], depth+1); // <RESTOF_OR_C>
    T[0] = mktuple(phrase /*P_RESTOF_OR_C*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_OR_C*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<RESTOF_UI> = 
//\\    "=" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <Opt_QUERY>,
//\\   ;

case P_RESTOF_UI:
  if (alt == 0)        {
    T[1] = kw(/*"="*/ 1);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = build_ast(A[ap+1], depth+1); // <OPERAND>
    T[4] = build_ast(A[ap+2], depth+1); // <RESTOF_EXPR>
    T[5] = build_ast(A[ap+3], depth+1); // <Opt_QUERY>
    T[0] = mktuple(phrase /*P_RESTOF_UI*/, alt /*1*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_UI*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<Opt_Percent_SPEC> = 
//\\    "spec",
//\\   ;

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



 
//\\ P<RESTOF_FPP_LIST> = 
//\\    "," <Opt_Plus> <OPERAND> <RESTOF_EXPR> ":" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_FPP_LIST>,
//\\   ;

case P_RESTOF_FPP_LIST:
  if (alt == 0)        {
    T[1] = kw(/*","*/ 2);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = build_ast(A[ap+1], depth+1); // <OPERAND>
    T[4] = build_ast(A[ap+2], depth+1); // <RESTOF_EXPR>
    T[5] = kw(/*":"*/ 4);
    T[6] = build_ast(A[ap+3], depth+1); // <Opt_Plus>
    T[7] = build_ast(A[ap+4], depth+1); // <OPERAND>
    T[8] = build_ast(A[ap+5], depth+1); // <RESTOF_EXPR>
    T[9] = build_ast(A[ap+6], depth+1); // <RESTOF_FPP_LIST>
    T[0] = mktuple(phrase /*P_RESTOF_FPP_LIST*/, alt /*1*/, /*phrases*/ 9, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_FPP_LIST*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<RESTOF_ARRAYLIST> = 
//\\    "," <NAME> <RESTOF_NAMELIST> "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> ":" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_FPP_LIST> ")" <RESTOF_ARRAYLIST>,
//\\   ;

case P_RESTOF_ARRAYLIST:
  if (alt == 0)        {
    T[1] = kw(/*","*/ 2);
    T[2] = NAME(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <RESTOF_NAMELIST>
    T[4] = kw(/*"("*/ 11);
    T[5] = build_ast(A[ap+2], depth+1); // <Opt_Plus>
    T[6] = build_ast(A[ap+3], depth+1); // <OPERAND>
    T[7] = build_ast(A[ap+4], depth+1); // <RESTOF_EXPR>
    T[8] = kw(/*":"*/ 4);
    T[9] = build_ast(A[ap+5], depth+1); // <Opt_Plus>
    T[10] = build_ast(A[ap+6], depth+1); // <OPERAND>
    T[11] = build_ast(A[ap+7], depth+1); // <RESTOF_EXPR>
    T[12] = build_ast(A[ap+8], depth+1); // <RESTOF_FPP_LIST>
    T[13] = kw(/*")"*/ 12);
    T[14] = build_ast(A[ap+9], depth+1); // <RESTOF_ARRAYLIST>
    T[0] = mktuple(phrase /*P_RESTOF_ARRAYLIST*/, alt /*1*/, /*phrases*/ 14, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7], T[8], T[9], T[10], T[11], T[12], T[13], T[14]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_ARRAYLIST*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<RESTOF_SWITCHLIST> = 
//\\    "," <NAME> <RESTOF_NAMELIST> "(" <Opt_Plus> <CONST> ":" <Opt_Plus> <CONST> ")" <RESTOF_SWITCHLIST>,
//\\   ;

case P_RESTOF_SWITCHLIST:
  if (alt == 0)        {
    T[1] = kw(/*","*/ 2);
    T[2] = NAME(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <RESTOF_NAMELIST>
    T[4] = kw(/*"("*/ 11);
    T[5] = build_ast(A[ap+2], depth+1); // <Opt_Plus>
    T[6] = CONST(ap+3);
    T[7] = kw(/*":"*/ 4);
    T[8] = build_ast(A[ap+4], depth+1); // <Opt_Plus>
    T[9] = CONST(ap+5);
    T[10] = kw(/*")"*/ 12);
    T[11] = build_ast(A[ap+6], depth+1); // <RESTOF_SWITCHLIST>
    T[0] = mktuple(phrase /*P_RESTOF_SWITCHLIST*/, alt /*1*/, /*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[0] = mktuple(phrase /*P_RESTOF_SWITCHLIST*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<COMP> = 
//\\    "=",
//\\    ">=",
//\\    ">",
//\\    "#",
//\\    "<=",
//\\    "<";

case P_COMP:
  if (alt == 0)        {
    T[1] = kw(/*"="*/ 1);
    T[0] = mktuple(phrase /*P_COMP*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*">="*/ 52);
    T[0] = mktuple(phrase /*P_COMP*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 2) {
    T[1] = kw(/*">"*/ 53);
    T[0] = mktuple(phrase /*P_COMP*/, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"#"*/ 54);
    T[0] = mktuple(phrase /*P_COMP*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"<="*/ 55);
    T[0] = mktuple(phrase /*P_COMP*/, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = kw(/*"<"*/ 56);
    T[0] = mktuple(phrase /*P_COMP*/, alt /*6*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];



 
//\\ P<RESTOF_SS1> = 
//\\    <S>,
//\\    <Percent_IU> <SC> <RESTOF_COND> <S>;

case P_RESTOF_SS1:
  if (alt == 0)        {
    T[1] = S(ap+0);
    T[0] = mktuple(phrase /*P_RESTOF_SS1*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = build_ast(A[ap+0], depth+1); // <Percent_IU>
    T[2] = build_ast(A[ap+1], depth+1); // <SC>
    T[3] = build_ast(A[ap+2], depth+1); // <RESTOF_COND>
    T[4] = S(ap+3);
    T[0] = mktuple(phrase /*P_RESTOF_SS1*/, alt /*2*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  }
  return T[0];



 
//\\ P<RESTOF_FN_LIST> = 
//\\    "," <N> <RESTOF_FN_LIST>,
//\\   ;

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



 
//\\ P<RESTOF_FAULTLIST> = 
//\\    "," <N> <RESTOF_FN_LIST> "->" <N> <RESTOF_FAULTLIST>,
//\\   ;

case P_RESTOF_FAULTLIST:
  if (alt == 0)        {
    T[1] = kw(/*","*/ 2);
    T[2] = N(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <RESTOF_FN_LIST>
    T[4] = kw(/*"->"*/ 25);
    T[5] = N(ap+2);
    T[6] = build_ast(A[ap+3], depth+1); // <RESTOF_FAULTLIST>
    T[0] = mktuple(phrase /*P_RESTOF_FAULTLIST*/, alt /*1*/, /*phrases*/ 6, T /*T[1], T[2], T[3], T[4], T[5], T[6]*/);
  } else               {
    T[0] = mktuple(phrase /*P_RESTOF_FAULTLIST*/, alt /*2*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<UCI> = 
//\\    "*@" <NAME> <APP>,
//\\    "*" <Opt_Equals> <NAME> <APP>,
//\\    "J" <N> <Opt_P> <J_INSTR>,
//\\    "SETB" <OCTAL>,
//\\    "SET" <N> "P:",
//\\    "JS" <N> <Opt_P>,
//\\    "EXIT" <N>,
//\\    <Opt_Equals> "M" <N> "M" <N> <MS_INSTR>,
//\\    "SH" <SH_INSTR>,
//\\    "=" <QS_INSTR>,
//\\    "Q" <N> "TOQ" <N>,
//\\    "C" <N> "TOQ" <N>,
//\\    "I" <N> "TOQ" <N>,
//\\    "M" <N> "TOQ" <N>,
//\\    "IM" <N> "TOQ" <N>,
//\\    "CM" <N> "TOQ" <N>,
//\\    "CI" <N> "TOQ" <N>,
//\\    "I" <N> "=" <Opt_Plus> <N>,
//\\    "Q" <N>,
//\\    "C" <N>,
//\\    "I" <N>,
//\\    "M" <N>,
//\\    "NC" <N>,
//\\    "DC" <N>,
//\\    "LINK",
//\\    "M" <Plus> "I" <N>,
//\\    "X+" <Opt_Plus> <N>,
//\\    "X+C" <N>,
//\\    "ROUNDHF",
//\\    "ROUNDF",
//\\    "ROUNDH",
//\\    "ROUND",
//\\    "FLOATD",
//\\    "FLOAT",
//\\    "ERASE",
//\\    "REVD",
//\\    "REV",
//\\    "ZERO",
//\\    "DUPD",
//\\    "DUP",
//\\    "NEGDF",
//\\    "NEGF",
//\\    "NEGD",
//\\    "NEG",
//\\    "ABSF",
//\\    "ABS",
//\\    "MAXF",
//\\    "MAX",
//\\    "SIGNF",
//\\    "SIGN",
//\\    "CAB",
//\\    "FRB",
//\\    "STAND",
//\\    "/DF",
//\\    "/D",
//\\    "/F",
//\\    "/R",
//\\    "/I",
//\\    "/",
//\\    "+DF",
//\\    "+D",
//\\    "+F",
//\\    "+",
//\\    "-DF",
//\\    "-D",
//\\    "-F",
//\\    "-",
//\\    "XDF",
//\\    "XD",
//\\    "XF",
//\\    "X+F",
//\\    "X+",
//\\    "=TR",
//\\    "BITS",
//\\    "DUMMY",
//\\    "PERM",
//\\    "TOP",
//\\    "OR",
//\\    "VR",
//\\    "NEV",
//\\    "NOT",
//\\    "FIX",
//\\    "STR",
//\\    "CONT",
//\\    "AND",
//\\    "EXIT",
//\\    "OUT",
//\\    "X",
//\\    "P" <IOM> <ATOF> "Q" <N>,
//\\    "TLOG" <N>,
//\\    "INTQ" <N>,
//\\    "PARQ" <N>,
//\\    "BUSYQ" <N>,
//\\    "MANUALQ" <N>,
//\\    "CTQ" <N>,
//\\    "CLOQ" <N>,
//\\    "SET" <Opt_Plus> <N>,
//\\    "ADVCA" <N>,
//\\    <OCTAL> "/" <OCTAL> "/" <OCTAL>,
//\\    <Opt_Equals> "E" <N> <E_INSTR>,
//\\    "JSE" <N>,
//\\    "JE" <N>,
//\\   ;

case P_UCI:
  if (alt == 0)        {
    T[1] = kw(/*"*@"*/ 57);
    T[2] = NAME(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <APP>
    T[0] = mktuple(phrase /*P_UCI*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"*"*/ 23);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Equals>
    T[3] = NAME(ap+1);
    T[4] = build_ast(A[ap+2], depth+1); // <APP>
    T[0] = mktuple(phrase /*P_UCI*/, alt /*2*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"J"*/ 58);
    T[2] = N(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <Opt_P>
    T[4] = build_ast(A[ap+2], depth+1); // <J_INSTR>
    T[0] = mktuple(phrase /*P_UCI*/, alt /*3*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"SETB"*/ 59);
    T[2] = OCTAL(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"SET"*/ 60);
    T[2] = N(ap+0);
    T[3] = kw(/*"P:"*/ 22);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*5*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 5) {
    T[1] = kw(/*"JS"*/ 61);
    T[2] = N(ap+0);
    T[3] = build_ast(A[ap+1], depth+1); // <Opt_P>
    T[0] = mktuple(phrase /*P_UCI*/, alt /*6*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 6) {
    T[1] = kw(/*"EXIT"*/ 62);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*7*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 7) {
    T[1] = build_ast(A[ap+0], depth+1); // <Opt_Equals>
    T[2] = kw(/*"M"*/ 63);
    T[3] = N(ap+1);
    T[4] = kw(/*"M"*/ 63);
    T[5] = N(ap+2);
    T[6] = build_ast(A[ap+3], depth+1); // <MS_INSTR>
    T[0] = mktuple(phrase /*P_UCI*/, alt /*8*/, /*phrases*/ 6, T /*T[1], T[2], T[3], T[4], T[5], T[6]*/);
  } else if (alt == 8) {
    T[1] = kw(/*"SH"*/ 64);
    T[2] = build_ast(A[ap+0], depth+1); // <SH_INSTR>
    T[0] = mktuple(phrase /*P_UCI*/, alt /*9*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 9) {
    T[1] = kw(/*"="*/ 1);
    T[2] = build_ast(A[ap+0], depth+1); // <QS_INSTR>
    T[0] = mktuple(phrase /*P_UCI*/, alt /*10*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 10) {
    T[1] = kw(/*"Q"*/ 65);
    T[2] = N(ap+0);
    T[3] = kw(/*"TOQ"*/ 66);
    T[4] = N(ap+1);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*11*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 11) {
    T[1] = kw(/*"C"*/ 67);
    T[2] = N(ap+0);
    T[3] = kw(/*"TOQ"*/ 66);
    T[4] = N(ap+1);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*12*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 12) {
    T[1] = kw(/*"I"*/ 68);
    T[2] = N(ap+0);
    T[3] = kw(/*"TOQ"*/ 66);
    T[4] = N(ap+1);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*13*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 13) {
    T[1] = kw(/*"M"*/ 63);
    T[2] = N(ap+0);
    T[3] = kw(/*"TOQ"*/ 66);
    T[4] = N(ap+1);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*14*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 14) {
    T[1] = kw(/*"IM"*/ 69);
    T[2] = N(ap+0);
    T[3] = kw(/*"TOQ"*/ 66);
    T[4] = N(ap+1);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*15*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 15) {
    T[1] = kw(/*"CM"*/ 70);
    T[2] = N(ap+0);
    T[3] = kw(/*"TOQ"*/ 66);
    T[4] = N(ap+1);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*16*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 16) {
    T[1] = kw(/*"CI"*/ 71);
    T[2] = N(ap+0);
    T[3] = kw(/*"TOQ"*/ 66);
    T[4] = N(ap+1);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*17*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 17) {
    T[1] = kw(/*"I"*/ 68);
    T[2] = N(ap+0);
    T[3] = kw(/*"="*/ 1);
    T[4] = build_ast(A[ap+1], depth+1); // <Opt_Plus>
    T[5] = N(ap+2);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*18*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  } else if (alt == 18) {
    T[1] = kw(/*"Q"*/ 65);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*19*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 19) {
    T[1] = kw(/*"C"*/ 67);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*20*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 20) {
    T[1] = kw(/*"I"*/ 68);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*21*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 21) {
    T[1] = kw(/*"M"*/ 63);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*22*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 22) {
    T[1] = kw(/*"NC"*/ 72);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*23*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 23) {
    T[1] = kw(/*"DC"*/ 73);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*24*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 24) {
    T[1] = kw(/*"LINK"*/ 74);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*25*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 25) {
    T[1] = kw(/*"M"*/ 63);
    T[2] = build_ast(A[ap+0], depth+1); // <Plus>
    T[3] = kw(/*"I"*/ 68);
    T[4] = N(ap+1);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*26*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 26) {
    T[1] = kw(/*"X+"*/ 75);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = N(ap+1);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*27*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 27) {
    T[1] = kw(/*"X+C"*/ 76);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*28*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 28) {
    T[1] = kw(/*"ROUNDHF"*/ 77);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*29*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 29) {
    T[1] = kw(/*"ROUNDF"*/ 78);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*30*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 30) {
    T[1] = kw(/*"ROUNDH"*/ 79);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*31*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 31) {
    T[1] = kw(/*"ROUND"*/ 80);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*32*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 32) {
    T[1] = kw(/*"FLOATD"*/ 81);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*33*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 33) {
    T[1] = kw(/*"FLOAT"*/ 82);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*34*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 34) {
    T[1] = kw(/*"ERASE"*/ 83);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*35*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 35) {
    T[1] = kw(/*"REVD"*/ 84);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*36*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 36) {
    T[1] = kw(/*"REV"*/ 85);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*37*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 37) {
    T[1] = kw(/*"ZERO"*/ 86);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*38*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 38) {
    T[1] = kw(/*"DUPD"*/ 87);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*39*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 39) {
    T[1] = kw(/*"DUP"*/ 88);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*40*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 40) {
    T[1] = kw(/*"NEGDF"*/ 89);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*41*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 41) {
    T[1] = kw(/*"NEGF"*/ 90);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*42*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 42) {
    T[1] = kw(/*"NEGD"*/ 91);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*43*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 43) {
    T[1] = kw(/*"NEG"*/ 92);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*44*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 44) {
    T[1] = kw(/*"ABSF"*/ 93);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*45*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 45) {
    T[1] = kw(/*"ABS"*/ 94);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*46*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 46) {
    T[1] = kw(/*"MAXF"*/ 95);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*47*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 47) {
    T[1] = kw(/*"MAX"*/ 96);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*48*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 48) {
    T[1] = kw(/*"SIGNF"*/ 97);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*49*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 49) {
    T[1] = kw(/*"SIGN"*/ 98);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*50*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 50) {
    T[1] = kw(/*"CAB"*/ 99);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*51*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 51) {
    T[1] = kw(/*"FRB"*/ 100);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*52*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 52) {
    T[1] = kw(/*"STAND"*/ 101);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*53*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 53) {
    T[1] = kw(/*"/DF"*/ 102);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*54*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 54) {
    T[1] = kw(/*"/D"*/ 103);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*55*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 55) {
    T[1] = kw(/*"/F"*/ 104);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*56*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 56) {
    T[1] = kw(/*"/R"*/ 105);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*57*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 57) {
    T[1] = kw(/*"/I"*/ 106);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*58*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 58) {
    T[1] = kw(/*"/"*/ 33);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*59*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 59) {
    T[1] = kw(/*"+DF"*/ 107);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*60*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 60) {
    T[1] = kw(/*"+D"*/ 108);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*61*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 61) {
    T[1] = kw(/*"+F"*/ 109);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*62*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 62) {
    T[1] = kw(/*"+"*/ 31);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*63*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 63) {
    T[1] = kw(/*"-DF"*/ 110);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*64*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 64) {
    T[1] = kw(/*"-D"*/ 111);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*65*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 65) {
    T[1] = kw(/*"-F"*/ 112);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*66*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 66) {
    T[1] = kw(/*"-"*/ 32);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*67*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 67) {
    T[1] = kw(/*"XDF"*/ 113);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*68*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 68) {
    T[1] = kw(/*"XD"*/ 114);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*69*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 69) {
    T[1] = kw(/*"XF"*/ 115);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*70*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 70) {
    T[1] = kw(/*"X+F"*/ 116);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*71*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 71) {
    T[1] = kw(/*"X+"*/ 75);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*72*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 72) {
    T[1] = kw(/*"=TR"*/ 117);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*73*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 73) {
    T[1] = kw(/*"BITS"*/ 118);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*74*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 74) {
    T[1] = kw(/*"DUMMY"*/ 119);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*75*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 75) {
    T[1] = kw(/*"PERM"*/ 120);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*76*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 76) {
    T[1] = kw(/*"TOP"*/ 121);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*77*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 77) {
    T[1] = kw(/*"OR"*/ 122);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*78*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 78) {
    T[1] = kw(/*"VR"*/ 123);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*79*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 79) {
    T[1] = kw(/*"NEV"*/ 124);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*80*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 80) {
    T[1] = kw(/*"NOT"*/ 125);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*81*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 81) {
    T[1] = kw(/*"FIX"*/ 126);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*82*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 82) {
    T[1] = kw(/*"STR"*/ 127);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*83*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 83) {
    T[1] = kw(/*"CONT"*/ 128);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*84*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 84) {
    T[1] = kw(/*"AND"*/ 129);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*85*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 85) {
    T[1] = kw(/*"EXIT"*/ 62);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*86*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 86) {
    T[1] = kw(/*"OUT"*/ 130);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*87*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 87) {
    T[1] = kw(/*"X"*/ 131);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*88*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 88) {
    T[1] = kw(/*"P"*/ 132);
    T[2] = build_ast(A[ap+0], depth+1); // <IOM>
    T[3] = build_ast(A[ap+1], depth+1); // <ATOF>
    T[4] = kw(/*"Q"*/ 65);
    T[5] = N(ap+2);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*89*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  } else if (alt == 89) {
    T[1] = kw(/*"TLOG"*/ 133);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*90*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 90) {
    T[1] = kw(/*"INTQ"*/ 134);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*91*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 91) {
    T[1] = kw(/*"PARQ"*/ 135);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*92*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 92) {
    T[1] = kw(/*"BUSYQ"*/ 136);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*93*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 93) {
    T[1] = kw(/*"MANUALQ"*/ 137);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*94*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 94) {
    T[1] = kw(/*"CTQ"*/ 138);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*95*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 95) {
    T[1] = kw(/*"CLOQ"*/ 139);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*96*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 96) {
    T[1] = kw(/*"SET"*/ 60);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = N(ap+1);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*97*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 97) {
    T[1] = kw(/*"ADVCA"*/ 140);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*98*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 98) {
    T[1] = OCTAL(ap+0);
    T[2] = kw(/*"/"*/ 33);
    T[3] = OCTAL(ap+1);
    T[4] = kw(/*"/"*/ 33);
    T[5] = OCTAL(ap+2);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*99*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  } else if (alt == 99) {
    T[1] = build_ast(A[ap+0], depth+1); // <Opt_Equals>
    T[2] = kw(/*"F"*/ 141);
    T[3] = N(ap+1);
    T[4] = build_ast(A[ap+2], depth+1); // <E_INSTR>
    T[0] = mktuple(phrase /*P_UCI*/, alt /*100*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 100) {
    T[1] = kw(/*"JSE"*/ 142);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*101*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 101) {
    T[1] = kw(/*"JE"*/ 143);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UCI*/, alt /*102*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[0] = mktuple(phrase /*P_UCI*/, alt /*103*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<J_INSTR> = 
//\\    "C" <N> "NZS",
//\\    "C" <N> "NZ",
//\\    "C" <N> "Z",
//\\    "=Z",
//\\    "=",
//\\    "#Z",
//\\    "#",
//\\    ">Z",
//\\    ">=Z",
//\\    "<Z",
//\\    "<=Z",
//\\    "V",
//\\    "NV",
//\\    "EN",
//\\    "NEN",
//\\    "EJ",
//\\    "NEJ",
//\\    "TR",
//\\    "NTR",
//\\   ;

case P_J_INSTR:
  if (alt == 0)        {
    T[1] = kw(/*"C"*/ 67);
    T[2] = N(ap+0);
    T[3] = kw(/*"NZS"*/ 144);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"C"*/ 67);
    T[2] = N(ap+0);
    T[3] = kw(/*"NZ"*/ 145);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"C"*/ 67);
    T[2] = N(ap+0);
    T[3] = kw(/*"Z"*/ 146);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*3*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"=Z"*/ 147);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"="*/ 1);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 5) {
    T[1] = kw(/*"#Z"*/ 148);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*6*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 6) {
    T[1] = kw(/*"#"*/ 54);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*7*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 7) {
    T[1] = kw(/*">Z"*/ 149);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*8*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 8) {
    T[1] = kw(/*">=Z"*/ 150);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*9*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 9) {
    T[1] = kw(/*"<Z"*/ 151);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*10*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 10) {
    T[1] = kw(/*"<=Z"*/ 152);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*11*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 11) {
    T[1] = kw(/*"V"*/ 153);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*12*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 12) {
    T[1] = kw(/*"NV"*/ 154);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*13*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 13) {
    T[1] = kw(/*"EN"*/ 155);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*14*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 14) {
    T[1] = kw(/*"NEN"*/ 156);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*15*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 15) {
    T[1] = kw(/*"FJ"*/ 157);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*16*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 16) {
    T[1] = kw(/*"NFJ"*/ 158);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*17*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 17) {
    T[1] = kw(/*"TR"*/ 159);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*18*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 18) {
    T[1] = kw(/*"NTR"*/ 160);
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*19*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[0] = mktuple(phrase /*P_J_INSTR*/, alt /*20*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<MS_INSTR> = 
//\\    "QHN",
//\\    "QH",
//\\    "QN",
//\\    "Q",
//\\    "HN",
//\\    "H",
//\\    "N",
//\\   ;

case P_MS_INSTR:
  if (alt == 0)        {
    T[1] = kw(/*"QHN"*/ 161);
    T[0] = mktuple(phrase /*P_MS_INSTR*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"QH"*/ 162);
    T[0] = mktuple(phrase /*P_MS_INSTR*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"QN"*/ 163);
    T[0] = mktuple(phrase /*P_MS_INSTR*/, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"Q"*/ 65);
    T[0] = mktuple(phrase /*P_MS_INSTR*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"HN"*/ 164);
    T[0] = mktuple(phrase /*P_MS_INSTR*/, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 5) {
    T[1] = kw(/*"H"*/ 165);
    T[0] = mktuple(phrase /*P_MS_INSTR*/, alt /*6*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 6) {
    T[1] = kw(/*"N"*/ 166);
    T[0] = mktuple(phrase /*P_MS_INSTR*/, alt /*7*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[0] = mktuple(phrase /*P_MS_INSTR*/, alt /*8*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<SH_INSTR> = 
//\\    "A" <Opt_Plus> <N>,
//\\    "AD" <Opt_Plus> <N>,
//\\    "L" <Opt_Plus> <N>,
//\\    "LD" <Opt_Plus> <N>,
//\\    "C" <Opt_Plus> <N>,
//\\    "AC" <N>,
//\\    "ADC" <N>,
//\\    "LC" <N>,
//\\    "LDC" <N>,
//\\    "CC" <N>;

case P_SH_INSTR:
  if (alt == 0)        {
    T[1] = kw(/*"A"*/ 167);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = N(ap+1);
    T[0] = mktuple(phrase /*P_SH_INSTR*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"AD"*/ 168);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = N(ap+1);
    T[0] = mktuple(phrase /*P_SH_INSTR*/, alt /*2*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"L"*/ 169);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = N(ap+1);
    T[0] = mktuple(phrase /*P_SH_INSTR*/, alt /*3*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"LD"*/ 170);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = N(ap+1);
    T[0] = mktuple(phrase /*P_SH_INSTR*/, alt /*4*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"C"*/ 67);
    T[2] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[3] = N(ap+1);
    T[0] = mktuple(phrase /*P_SH_INSTR*/, alt /*5*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 5) {
    T[1] = kw(/*"AC"*/ 171);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_SH_INSTR*/, alt /*6*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 6) {
    T[1] = kw(/*"ADC"*/ 172);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_SH_INSTR*/, alt /*7*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 7) {
    T[1] = kw(/*"LC"*/ 173);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_SH_INSTR*/, alt /*8*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 8) {
    T[1] = kw(/*"LDC"*/ 174);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_SH_INSTR*/, alt /*9*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[1] = kw(/*"CC"*/ 175);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_SH_INSTR*/, alt /*10*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  }
  return T[0];



 
//\\ P<QS_INSTR> = 
//\\    "LINK",
//\\    "Q" <N>,
//\\    "C" <N>,
//\\    "I" <N>,
//\\    "M" <N>,
//\\    "RC" <N>,
//\\    "RI" <N>,
//\\    "RM" <N>,
//\\    "+Q" <N>,
//\\    "+C" <N>,
//\\    "+I" <N>,
//\\    "+M" <N>;

case P_QS_INSTR:
  if (alt == 0)        {
    T[1] = kw(/*"LINK"*/ 74);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"Q"*/ 65);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"C"*/ 67);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*3*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"I"*/ 68);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*4*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"M"*/ 63);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*5*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 5) {
    T[1] = kw(/*"RC"*/ 176);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*6*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 6) {
    T[1] = kw(/*"RI"*/ 177);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*7*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 7) {
    T[1] = kw(/*"RM"*/ 178);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*8*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 8) {
    T[1] = kw(/*"+Q"*/ 179);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*9*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 9) {
    T[1] = kw(/*"+C"*/ 180);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*10*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 10) {
    T[1] = kw(/*"+I"*/ 181);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*11*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[1] = kw(/*"+M"*/ 182);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_QS_INSTR*/, alt /*12*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  }
  return T[0];



 
//\\ P<Plus> = 
//\\    "+",
//\\    "-";

case P_Plus:
  if (alt == 0)        {
    T[1] = kw(/*"+"*/ 31);
    T[0] = mktuple(phrase /*P_Plus*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = kw(/*"-"*/ 32);
    T[0] = mktuple(phrase /*P_Plus*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];



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

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



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

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



 
//\\ P<IOM> = 
//\\    "I",
//\\    "O",
//\\    "M";

case P_IOM:
  if (alt == 0)        {
    T[1] = kw(/*"I"*/ 68);
    T[0] = mktuple(phrase /*P_IOM*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"O"*/ 183);
    T[0] = mktuple(phrase /*P_IOM*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = kw(/*"M"*/ 63);
    T[0] = mktuple(phrase /*P_IOM*/, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];



 
//\\ P<ATOF> = 
//\\    "A",
//\\    "B",
//\\    "C",
//\\    "D",
//\\    "E",
//\\    "F";

case P_ATOF:
  if (alt == 0)        {
    T[1] = kw(/*"A"*/ 167);
    T[0] = mktuple(phrase /*P_ATOF*/, alt /*1*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"B"*/ 184);
    T[0] = mktuple(phrase /*P_ATOF*/, alt /*2*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"C"*/ 67);
    T[0] = mktuple(phrase /*P_ATOF*/, alt /*3*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"D"*/ 185);
    T[0] = mktuple(phrase /*P_ATOF*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"E"*/ 186);
    T[0] = mktuple(phrase /*P_ATOF*/, alt /*5*/, /*phrases*/ 1, T /*T[1]*/);
  } else               {
    T[1] = kw(/*"F"*/ 141);
    T[0] = mktuple(phrase /*P_ATOF*/, alt /*6*/, /*phrases*/ 1, T /*T[1]*/);
  }
  return T[0];



 
//\\ P<E_INSTR> = 
//\\    "M" <N> "Q",
//\\    "M" <N>,
//\\   ;

case P_E_INSTR:
  if (alt == 0)        {
    T[1] = kw(/*"M"*/ 63);
    T[2] = N(ap+0);
    T[3] = kw(/*"Q"*/ 65);
    T[0] = mktuple(phrase /*P_E_INSTR*/, alt /*1*/, /*phrases*/ 3, T /*T[1], T[2], T[3]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"M"*/ 63);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_E_INSTR*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else               {
    T[0] = mktuple(phrase /*P_E_INSTR*/, alt /*3*/, /*phrases*/ 0, T /**/);
  }
  return T[0];



 
//\\ P<UI> = 
//\\    <NAME> <APP> <SETMARKER1> <RESTOF_UI>,
//\\    "->" <N>,
//\\    "caption" <CAPTIONTEXT>,
//\\    "return",
//\\    "result" "=" <Opt_Plus> <OPERAND> <RESTOF_EXPR>,
//\\    "stop",
//\\    "->" <NAME> "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> ")",
//\\    "monitor" <N>;

case P_UI:
  if (alt == 0)        {
    T[1] = NAME(ap+0);
    T[2] = build_ast(A[ap+1], depth+1); // <APP>
    T[3] = SETMARKER1(ap+2);
    T[4] = build_ast(A[ap+3], depth+1); // <RESTOF_UI>
    T[0] = mktuple(phrase /*P_UI*/, alt /*1*/, /*phrases*/ 4, T /*T[1], T[2], T[3], T[4]*/);
  } else if (alt == 1) {
    T[1] = kw(/*"->"*/ 25);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UI*/, alt /*2*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 2) {
    T[1] = kw(/*"caption"*/ 187);
    T[2] = CAPTIONTEXT(ap+0);
    T[0] = mktuple(phrase /*P_UI*/, alt /*3*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  } else if (alt == 3) {
    T[1] = kw(/*"return"*/ 188);
    T[0] = mktuple(phrase /*P_UI*/, alt /*4*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 4) {
    T[1] = kw(/*"result"*/ 189);
    T[2] = kw(/*"="*/ 1);
    T[3] = build_ast(A[ap+0], depth+1); // <Opt_Plus>
    T[4] = build_ast(A[ap+1], depth+1); // <OPERAND>
    T[5] = build_ast(A[ap+2], depth+1); // <RESTOF_EXPR>
    T[0] = mktuple(phrase /*P_UI*/, alt /*5*/, /*phrases*/ 5, T /*T[1], T[2], T[3], T[4], T[5]*/);
  } else if (alt == 5) {
    T[1] = kw(/*"stop"*/ 190);
    T[0] = mktuple(phrase /*P_UI*/, alt /*6*/, /*phrases*/ 1, T /*T[1]*/);
  } else if (alt == 6) {
    T[1] = kw(/*"->"*/ 25);
    T[2] = NAME(ap+0);
    T[3] = kw(/*"("*/ 11);
    T[4] = build_ast(A[ap+1], depth+1); // <Opt_Plus>
    T[5] = build_ast(A[ap+2], depth+1); // <OPERAND>
    T[6] = build_ast(A[ap+3], depth+1); // <RESTOF_EXPR>
    T[7] = kw(/*")"*/ 12);
    T[0] = mktuple(phrase /*P_UI*/, alt /*7*/, /*phrases*/ 7, T /*T[1], T[2], T[3], T[4], T[5], T[6], T[7]*/);
  } else               {
    T[1] = kw(/*"monitor"*/ 191);
    T[2] = N(ap+0);
    T[0] = mktuple(phrase /*P_UI*/, alt /*8*/, /*phrases*/ 2, T /*T[1], T[2]*/);
  }
  return T[0];

  case P_EOD:  return FALSE; // %endofprogram of %endoffile should terminate the parsing.  If we hit EOF it's an error.

  }
  fprintf(stderr, "bug: missing case?\n"); exit(1);
  return -1;
}

void print_tuple(int p) {
  int i;
  fprintf(stdout, "%d: [Phrase=%d alt=%d (%d %d) phrases=%d", p, AST[p], AST[p+1], AST[p+2], AST[p+3], AST[p+OVERHEAD]);
  for (i = 1; i <= AST[p+OVERHEAD]; i++) {
    fprintf(stdout, " %d", AST[p+OVERHEAD+i]);
  }
  fprintf(stdout, "]\n");
}

#define SOURCE(p) AST[(p)+OVERHEAD+1], c+AST[(p)+OVERHEAD+2]
#define C_CONST(p) ConstFixupHack(AST[(p)+OVERHEAD+1], c+AST[(p)+OVERHEAD+2])
#define CAPTION(p) CaptionTextFixupHack(AST[(p)+OVERHEAD+1], c+AST[(p)+OVERHEAD+2])
#define P(p,n) AST[(p)+OVERHEAD+(n)]
#define Alt(p) AST[(p)+1]
#define Phrases(p) AST[(p)+OVERHEAD]
#define Phrase(p,n) AST[(p)+OVERHEAD+(n)]

void compile(int p);
void compile_expr(int opt_plus_minus, int operand, int rest_of_expr) {
  // it will need to be more complex than this unless we tweak the AA source.

  compile(opt_plus_minus);
  compile(operand);
  compile(rest_of_expr);
}
void compile_condition(int sc, int rest_of_cond) {
  compile(sc);
  compile(rest_of_cond);
}

void compile(int p)
{
  //fprintf(stdout, "Compile(AST[%d]) Phrase = %d  Alt = %d\n", p, AST[p], AST[p+1]);
  switch (AST[p]) {
  case P_SS:
    switch (AST[p+1]) {
    case 0: //    <UI> <SETMARKER2> <RESTOF_SS1>,
      compile(AST[p+OVERHEAD+1] /*UI*/);
      break;
    case 1: //    "cycle" <NAME> <APP> "=" <Opt_Plus> <OPERAND> <RESTOF_EXPR> "," <Opt_Plus> <OPERAND> <RESTOF_EXPR> "," <Opt_Plus> <OPERAND> <RESTOF_EXPR> <S>,
      fprintf(stdout, "for (");
      compile(P(p,2)); compile(P(p,3)); // <name><app>
      fprintf(stdout, " = ");
      compile_expr(P(p,5), P(p,6), P(p,7)); // <Opt_Plus><OPERAND1><RESTOF_EXPR>
      fprintf(stdout, "; ");
      compile(P(p,2)); compile(P(p,3)); // <name><app>
      fprintf(stdout, " != (");
      compile_expr(P(p,13), P(p,14), P(p,15)); // <Opt_Plus><OPERAND1><RESTOF_EXPR>
      fprintf(stdout, ")+(");
      compile_expr(P(p,9), P(p,10), P(p,11)); // <Opt_Plus><OPERAND1><RESTOF_EXPR>
      fprintf(stdout, "); ");
      compile(P(p,2)); compile(P(p,3)); // <name><app>
      fprintf(stdout, " += ");
      compile_expr(P(p,9), P(p,10), P(p,11)); // <Opt_Plus><OPERAND1><RESTOF_EXPR>
      fprintf(stdout, ") {\n");
      break;
    case 2: //    "repeat" <S>,
      fprintf(stdout, "}\n");
      break;
    case 3: //    <N> ":",
      fprintf(stdout, "l_%.*s:;\n", SOURCE(P(p,1)));
      break;
    case 4: //    <Percent_IU> <SC> <RESTOF_COND> "then" <UI> <S>,
      if (Alt(P(p,1)) == 0) {
        fprintf(stdout, "if (");
        compile_condition(P(p,2),P(p,3));
        fprintf(stdout, ") ");
      } else {
        fprintf(stdout, "if (!(");
        compile_condition(P(p,2),P(p,3));
        fprintf(stdout, ")) ");
      }
      compile(P(p,5));
      break;
    case 5: //    "!" <TEXT>,
      fprintf(stdout, "//%.*s\n", SOURCE(P(p,2)));
      break;
    case 6: //    <TYPE> <NAME> <RESTOF_NAMELIST> <S>,
      {
        int name = P(p,2), rest = P(p,3);
        compile(P(p,1)); fprintf(stdout, " ");
        compile(name); fprintf(stdout, ";\n");
        while (Alt(rest) == 0) {
          //    "," <NAME> <RESTOF_NAMELIST>,
          name = P(rest,2); rest = P(rest, 3);
          compile(P(p,1)); fprintf(stdout, " ");
          compile(name); fprintf(stdout, ";\n");
	}
      }
      break;
    case 7: //    "end" <S>,
      fprintf(stdout, "}\n");
      break;

    case 8: //    <RT> <Opt_Percent_SPEC> <NAME> <FPP> <S>,
      compile(P(p,1));
      compile(P(p,3));
      compile(P(p,4));
      if (Alt(P(p,2)) == 0) fprintf(stdout, ";\n"); else fprintf(stdout, " {\n");
      /*

  // %name parameters have to be handled something like this..,

  int _test(int *x) {
#define test(x) _test(&x)
#define x (*x)
    int J;
    for (J = 1; J != 10+1; J += 1)
    {
      fprintf (stdout, "%d\n", J);
    }
    return x = J;
  }
       */
      break;

    case 9: //    "spec" <NAME> <FPP> <S>,

      // NOT USED IN AA COMPILER.
      // I think this is for the specification of parameters for a procedure which is itself
      // being passed as a parameter.  (Same as old EMAS Imp, before the Imp80 change which
      // was to a more C-like syntax)

      if (Alt(p) == 0) {
        // "(" <FP_DELIMITER> <NAME> <RESTOF_NAMELIST> <RESTOF_FP_LIST> ")",
      }
      fprintf(stdout,";\n");
      break;

    case 10: //    "comment" <TEXT>,
      fprintf(stdout, "//%.*s\n", SOURCE(P(p,2)));
      break;

    case 11: //    <Opt_TYPE> "array" <NAME> <RESTOF_NAMELIST> "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> ":" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_FPP_LIST> ")" <RESTOF_ARRAYLIST> <S>,
      {
        int rest_of_namelist = P(p,4), name = P(p,3), rest_of_arraylist = P(p,15);
        compile(P(p,1));
        compile(name);
        fprintf(stdout, "[(");compile_expr(P(p,10),P(p,11),P(p,12));
        fprintf(stdout, ")-(");compile_expr(P(p,6),P(p,7),P(p,8));
        fprintf(stdout, ")+1];");
        fprintf(stdout, "\n");
        fprintf(stdout, "#define ");compile(name);fprintf(stdout, "(idx) ");compile(name);
	fprintf(stdout, "[(idx)-(");compile_expr(P(p,6),P(p,7),P(p,8));fprintf(stdout, ")]\n");
        fprintf(stdout, "\n");
        while (Alt(rest_of_namelist) == 0) {
          //  "," <NAME> <RESTOF_NAMELIST>,
          name = P(rest_of_namelist, 2); rest_of_namelist = P(rest_of_namelist,3); 
          compile(P(p,1));
          compile(name);
          fprintf(stdout, "[(");compile_expr(P(p,10),P(p,11),P(p,12));
          fprintf(stdout, ")-(");compile_expr(P(p,6),P(p,7),P(p,8));
          fprintf(stdout, ")+1];");
          fprintf(stdout, "\n");
          fprintf(stdout, "#define ");compile(name);fprintf(stdout, "(idx) ");compile(name);
	  fprintf(stdout, "[(idx)-(");compile_expr(P(p,6),P(p,7),P(p,8));fprintf(stdout, ")]\n");
          fprintf(stdout, "\n");
	}
        //  <RESTOF_ARRAYLIST> = "," <NAME> <RESTOF_NAMELIST> "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> ":" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_FPP_LIST> ")" <RESTOF_ARRAYLIST>,
        while (Alt(rest_of_arraylist) == 0) {
          name = P(rest_of_arraylist, 2);
          compile(P(p,1));
          compile(name);
          fprintf(stdout, "[(");compile_expr(P(rest_of_arraylist,9),P(rest_of_arraylist,10),P(rest_of_arraylist,11));
          fprintf(stdout, ")-(");compile_expr(P(rest_of_arraylist,5),P(rest_of_arraylist,6),P(rest_of_arraylist,7));
          fprintf(stdout, ")+1];");
          fprintf(stdout, "\n");
          fprintf(stdout, "#define ");compile(name);fprintf(stdout, "(idx) ");compile(name);
	  fprintf(stdout, "[(idx)-(");compile_expr(P(rest_of_arraylist,5),P(rest_of_arraylist,6),P(rest_of_arraylist,7));fprintf(stdout, ")]\n");
          fprintf(stdout, "\n");
	  rest_of_namelist = P(rest_of_arraylist,3);
          while (Alt(rest_of_namelist) == 0) {
            //  "," <NAME> <RESTOF_NAMELIST>,
            name = P(rest_of_namelist, 2); rest_of_namelist = P(rest_of_namelist,3); 
            compile(P(p,1));
            compile(name);
            fprintf(stdout, "[(");compile_expr(P(rest_of_arraylist,9),P(rest_of_arraylist,10),P(rest_of_arraylist,11));
            fprintf(stdout, ")-(");compile_expr(P(rest_of_arraylist,5),P(rest_of_arraylist,6),P(rest_of_arraylist,7));
            fprintf(stdout, ")+1];");
            fprintf(stdout, "\n");
            fprintf(stdout, "#define ");compile(name);fprintf(stdout, "(idx) ");compile(name);
	    fprintf(stdout, "[(idx)-(");compile_expr(P(rest_of_arraylist,5),P(rest_of_arraylist,6),P(rest_of_arraylist,7));fprintf(stdout, ")]\n");
            fprintf(stdout, "\n");
	  }
          rest_of_arraylist = P(rest_of_arraylist,14);
        }
      }
      break;
    case 12: //    "***A" <S>,
      fprintf(stdout, "\n");
      break;
    case 13: //    "begin" <S>,
      {static int main_begin = 0;
        if (main_begin++ == 0) {
          fprintf(stdout, "#include <stdio.h>\n");
          fprintf(stdout, "\n// This source assumes GCC extensions to allow nested procedures and dynamic array bounds\n\n");

          fprintf(stdout, "void caption(char *s) {\n");
          fprintf(stdout, "  while (*s != '\\0') {\n");
          fprintf(stdout, "    if (*s == '\\\\') *s = '\\n';\n");
          fprintf(stdout, "    if (*s == '_') *s = ' ';\n");
          fprintf(stdout, "    fputc(*s, stdout);\n");
          fprintf(stdout, "    s += 1;\n");
          fprintf(stdout, "  }\n");
          fprintf(stdout, "}\n");
          fprintf(stdout, "int main(int argc, char **argv) {\n");
        } else fprintf(stdout, "{\n");
      }
      break;
    case 14: //    "endofprogram",
      fprintf(stdout, "exit(0);\n");
      fprintf(stdout, "return(0);\n");
      fprintf(stdout, "}\n");
      stop_compiling = TRUE;
      break;
    case 15: //    "uppercasedelimiters" <S>,
      fprintf(stdout, "/* Not implementable */\n");
      break;
    case 16: //    <NAME> "(" <Opt_Plus> <CONST> "):",
      fprintf(stdout, "/* case */ ");
      compile(P(p,1));fprintf(stdout, "_");
      if (Alt(P(p,3))==1) fprintf(stdout, "M_");
      compile(P(p,4));// want it as decimal, not a symbol such as 'X'...
      fprintf(stdout, ":\n");
      break;
    case 17: //    "switch" <NAME> <RESTOF_NAMELIST> "(" <Opt_Plus> <CONST> ":" <CONST> ")" <RESTOF_SWITCHLIST> <S>,
      fprintf(stdout, "// switch table ");
      compile(P(p,2));
      fprintf(stdout, " dumped at end of this block\n");
      if (Alt(P(p,10)) == 0) fprintf(stdout, "// TO DO: RESTOF_SWITCHLIST\n");
      break;
    case 18: //    "compilequeries" <S>,
      fprintf(stdout, "/* Not implemented */\n");
      break;
    case 19: //    "ignorequeries" <S>,
      fprintf(stdout, "/* Not implemented */\n");
      break;
    case 20: //    "mcode" <S>,
      fprintf(stdout, "/* Embedded assembler is allowed */\n");
      break;
    case 21: //    <N> "P:",
      fprintf(stdout, "p_%.*s:\n", SOURCE(P(p,1)));
      break;
    case 22: //    "*" <UCI> <S>,
      compile(P(p,2));
      break;
    case 23: //    "fault" <N> <RESTOF_FN_LIST> "->" <N> <RESTOF_FAULTLIST> <S>,
      fprintf(stdout, "/* signal not implemented */\n");
      break;
    case 24: //    "normaldelimiters" <S>,
      fprintf(stdout, "/* Not implementable */\n");
      break;
    case 25: //    "strings" <S>,
      fprintf(stdout, "/* Not implemented */\n");
      break;
    case 26: //    "endofperm" <S>,
      fprintf(stdout, "\n");
      break;
    case 27: //    "endofmcode" <S>,
      fprintf(stdout, "/* Embedded assembler is no longer allowed */\n");
      break;
    case 28: //    "definecompiler" <S>,
      fprintf(stdout, "/* No-op */\n");
      break;
    case 29: //    <S>,
      break;
    case 30: //    <EOD>;
      fprintf(stdout, "\n");
      break;
    }
    return;
  case P_UI:
    switch (AST[p+1]) {
    case 0: //    <NAME> <APP> <SETMARKER1> <RESTOF_UI>
      {                                   // "=" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <Opt_QUERY>
        // If RESTOF_UI is not empty, it's an assignment to a variable or a map.
        // alt = 0 => assignment
        // alt = 1 => procedure call
	if (AST[P(p,4)+1] == 0) {
          fprintf(stdout, "%.*s", SOURCE(P(p,1)));
          if (AST[P(p,2)+1] == 0) {
            compile(P(p,2));
	    // "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_EXPR_LIST> ")"
            //                                        AA source has no 2D or higher arrays
	  } else {
	    //            fprintf(stdout, "%.*s=...\n", P(P(p,1),1), c+P(P(p,1),2));	 
	    //print_tuple(p);
	    //print_tuple(P(p,1));
          }
          compile(P(p,4));
          fprintf(stdout, ";\n");
	} else /* if (AST[P(p,4)+1] == 1) */ {
	  if (AST[P(p,2)+1] == 0) {
            fprintf(stdout, "%.*s", SOURCE(P(p,1)));
            compile(P(p,2));
            fprintf(stdout, ";\n");
	  } else {
	    fprintf(stdout, "%.*s();\n", SOURCE(P(p,1)));
	  }
	}
      }
      break;
    case 1: //    "->" <N>,
      fprintf(stdout, "goto l_%.*s;\n", SOURCE(P(p,2)));
      break;
    case 2: //    "caption" <CAPTIONTEXT>,
      fprintf(stdout, "caption(\"%s\")\n", CAPTION(P(p,2)));
      break;
    case 3: //    "return",
      fprintf(stdout, "return;\n");
      break;
    case 4: //    "result" "=" <Opt_Plus> <OPERAND> <RESTOF_EXPR>,
            // NOT USED IN AA
      fprintf(stdout, "return ");
      compile_expr(P(p,3), P(p,4), P(p,5));
      fprintf(stdout, ";\n");
      break;
    case 5: //    "stop",
      fprintf(stdout, "exit(0);\n");
      break;
    case 6: //    "->" <NAME> "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> ")",
      fprintf(stdout, "{sw = ");
      compile_expr(P(p,4), P(p,5), P(p,6));
      fprintf(stdout, "; goto goto_sw_%.*s;}\n", SOURCE(P(p,2)));
      break;
    case 7: //    "monitor" <N>;
      fprintf(stdout, "signal();\n");
      break;
    }
    return;

  case P_Opt_Plus:
    if (Alt(p)==2) return;
    fprintf(stdout, "%c", "+-"[Alt(p)]);
    break;

  case P_OPERAND:
    switch (Alt(p)) {
    case 0: //    <NAME> <APP>,
      fprintf(stdout, "%.*s", SOURCE(P(p,1)));
      if (Alt(P(p,2)) == 0) {
        compile(P(p,2));
      }
      fprintf(stdout, " ");
      break;
    case 1: //    <CONST>,
      fprintf(stdout, "%s ", C_CONST(P(p,1)));
      break;
    case 2: //    "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> ")",
            // NEVER USED IN AA COMPILER 
      fprintf(stdout, "( ");
      compile_expr(P(p,2), P(p,3), P(p,4));
      fprintf(stdout, " )");
      break;
    case 3: //    "!" <Opt_Plus> <OPERAND> <RESTOF_EXPR> "!";
      fprintf(stdout, "abs( "); // TO DO: distinguish between real and integer
      compile_expr(P(p,2), P(p,3), P(p,4));
      fprintf(stdout, " ) ");
      break;
    }
    return;

  case P_RESTOF_UI:
    if (Alt(p) == 1) return;
    // "=" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <Opt_QUERY>,
    fprintf(stdout, " = ");
    compile_expr(P(p,2), P(p,3), P(p,4));
    // if (compile_queries) ... print this value at runtime for debugging */
    break;

  case P_RESTOF_EXPR:
    // <OP> <OPERAND> <RESTOF_EXPR>,
    if (Alt(p) == 1) return;
    compile(P(p,1)); compile(P(p,2));
    compile(P(p,3)); // may be null
    break;

  case P_APP: 
    // "(" <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_EXPR_LIST> ")",
    if (Alt(p) == 1) return;
    fprintf(stdout, "(");
    compile_expr(P(p,2), P(p,3), P(p,4));
    compile(P(p,5));
    fprintf(stdout, ")");
    break;

  case P_RESTOF_EXPR_LIST:
    //    "," <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_EXPR_LIST>,
    if (Alt(p) == 1) return;
    fprintf(stdout, ", ");
    compile_expr(P(p,2), P(p,3), P(p,4));
    compile(P(p,5));
    break;

  case P_OP: 
    //    "+",
    //    "-",
    //    "*",
    //    "/",
    //    "^"   NOT USED
    fprintf(stdout, "%c", "+-*/"[Alt(p)]);
    break;

  case P_Opt_QUERY: break;
  case P_Opt_Comma: break;
  case P_Percent_IU: break;
  case P_Opt_Percent_REAL: break;

  case P_TYPE:
    fprintf(stdout, "%s ", Alt(p) == 0 ? "int" : "double");
    break;

  case P_Opt_TYPE:
    if (Alt(p) == 0) { fprintf(stdout, "int "); return; }
     fprintf(stdout, "double ");
     break;

  case P_RT:
    switch (Alt(p)) {
    case 0: //  "routine",
      fprintf(stdout, "void ");
      break;
    case 1: //  "realfn",
      fprintf(stdout, "double");
      break;
    case 2: //  "integerfn",
      fprintf(stdout, "int ");
      break;
    case 3: //  "realmap",
      fprintf(stdout, "double *");
      break;
    case 4: //  "integermap";
      fprintf(stdout, "int *");
      break;
    }
    break;

  case P_FP_DELIMITER:
    switch (Alt(p)) {
    case 0: //    <RT>,
      fprintf(stdout, "void ");
      break;
    case 1: //    "integerarrayname",
      fprintf(stdout, "int **");
      break;
    case 2: //    "integername",
      fprintf(stdout, "int *  /* THIS PARAMETER NEEDS A #define */  ");
      break;
    case 3: //    "integer",
      fprintf(stdout, "int ");
      break;
    case 4: //    <Opt_Percent_REAL> "arrayname",
      fprintf(stdout, "double **");
      break;
    case 5: //    "realname",
      fprintf(stdout, "double *  /* THIS PARAMETER NEEDS A #define */  ");
      break;
    case 6: //    "real",
      fprintf(stdout, "double ");
      break;
    case 7: //    "addr";
      fprintf(stdout, "void *");
      break;
    }
    break;

  case P_FPP:

    // %name parameters (except for <type> %array %name) need to have a couple
    //     of helper macros.  One for the procedure and one for each %name parameter

    //    "(" <FP_DELIMITER> <NAME> <RESTOF_NAMELIST> <RESTOF_FP_LIST> ")",
    {
      int rest_of_namelist = P(p,4), rest_of_fp_list = P(p,5);
      if (Alt(p) != 0) {
        fprintf(stdout, "(void)");
        return;
      }
      fprintf(stdout, "( ");


      compile(P(p,2));
      fprintf(stdout, " ");
      compile(P(p,3));

      while (Alt(rest_of_namelist) == 0) {
        // "," <NAME> <RESTOF_NAMELIST>,
        fprintf(stdout, ", ");
        compile(P(p,2));
        fprintf(stdout, " ");
        compile(P(rest_of_namelist,2));
        rest_of_namelist = P(rest_of_namelist,3);
      }

      while (Alt(rest_of_fp_list)==0) {
        // <Opt_Comma> <FP_DELIMITER> <NAME> <RESTOF_NAMELIST> <RESTOF_FP_LIST>,
        rest_of_namelist = P(rest_of_fp_list,4);
        fprintf(stdout, ", ");
        // fprintf(stdout, "/* TO DO: RESTOF_FP_LIST */");
        compile(P(rest_of_fp_list,2));
        fprintf(stdout, " ");
        compile(P(rest_of_fp_list,3));

        while (Alt(rest_of_namelist) == 0) {
          // "," <NAME> <RESTOF_NAMELIST>,
          fprintf(stdout, ", ");
          compile(P(rest_of_fp_list,2));
          fprintf(stdout, " ");
          compile(P(rest_of_namelist,2));
          rest_of_namelist = P(rest_of_namelist,3);
        }
        rest_of_fp_list = P(rest_of_fp_list,5);
      }

      fprintf(stdout, " )");
    }
    break;

  case P_RESTOF_FP_LIST: break;
  case P_RESTOF_NAMELIST: break;

  case P_SC: 
    { 
      int rest_of_sc;
      //    <Opt_Plus> <OPERAND> <RESTOF_EXPR> <COMP> <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_SC>,
      //    "(" <SC> <RESTOF_COND> ")";
      if (Alt(p) == 1) {
        fprintf(stdout, "("); compile_condition(P(p,2),P(p,3)); fprintf(stdout, ")"); 
        return;
      }
      rest_of_sc = P(p,8);
      //    <Opt_Plus> <OPERAND> <RESTOF_EXPR> <COMP> <Opt_Plus> <OPERAND> <RESTOF_EXPR> <RESTOF_SC>
      compile_expr(P(p,1), P(p,2), P(p,3));
      compile(P(p,4));
      compile_expr(P(p,5), P(p,6), P(p,7));
      if (Alt(rest_of_sc) == 0) {
 
        //  <COMP> <Opt_Plus> <OPERAND> <RESTOF_EXPR>,
        fprintf(stdout, "&& /* (beware side-effects) */");
        compile_expr(P(p,5), P(p,6), P(p,7));
        compile(P(p,8));

        compile(P(rest_of_sc,1));
        compile_expr(P(rest_of_sc,2), P(rest_of_sc,3), P(rest_of_sc,4));
      }
    } 
    break;

  case P_RESTOF_SC:
    // <COMP> <Opt_Plus> <OPERAND> <RESTOF_EXPR>,
    break;

  case P_RESTOF_COND:
    //    "and" <SC> <RESTOF_AND_C>,
    //    "or" <SC> <RESTOF_OR_C>,
    if (Alt(p) == 2) return;
    fprintf(stdout, " %s ", (Alt(p) == 0 ? "&&" : "||"));
    compile(P(p,2));
    compile(P(p,3));
    break;

  case P_RESTOF_AND_C: //\\    "and" <SC> <RESTOF_AND_C>,
  case P_RESTOF_OR_C:  //\\    "or" <SC> <RESTOF_OR_C>,
    if (Alt(p) == 1) return;
    fprintf(stdout, " %s ", (AST[p] == P_RESTOF_AND_C ? "&&" : "||"));
    compile(P(p,2)); compile(P(p,3));
    break;

  case P_Opt_Percent_SPEC: break;
  case P_RESTOF_FPP_LIST: break;
  case P_RESTOF_ARRAYLIST: break;
  case P_RESTOF_SWITCHLIST: break;

  case P_COMP:
    switch (Alt(p)) {
    case 0: //    "=",
      fprintf(stdout, " == "); break;
    case 1: //    ">=",
      fprintf(stdout, " >= "); break;
    case 2: //    ">",
      fprintf(stdout, " > "); break;
    case 3: //    "#",
      fprintf(stdout, " != "); break;
    case 4: //    "<=",
      fprintf(stdout, " <= "); break;
    case 5: //    "<";
      fprintf(stdout, " < "); break;
    }
    break;

  case P_RESTOF_SS1: break;
  case P_RESTOF_FN_LIST: break;
  case P_RESTOF_FAULTLIST: break;

  case P_UCI:
    switch(Alt(p)) {
    case 0: //    "*@" <NAME> <APP>,
      break;
    case 1: //    "*" <Opt_Equals> <NAME> <APP>,
      break;
    case 2: //    "J" <N> <Opt_P> <J_INSTR>,
      break;
    case 3: //    "SETB" <OCTAL>,
      break;
    case 4: //    "SET" <N> "P:",
      break;
    case 5: //    "JS" <N> <Opt_P>,
      break;
    case 7: //    <Opt_Equals> "M" <N> "M" <N> <MS_INSTR>,
      break;
    case 8: //    "SH" <SH_INSTR>,
      break;
    case 9: //    "=" <QS_INSTR>,
      break;
    case 10: //    "Q" <N> "TOQ" <N>,
      break;
    case 11: //    "C" <N> "TOQ" <N>,
      break;
    case 12: //    "I" <N> "TOQ" <N>,
      break;
    case 13: //    "M" <N> "TOQ" <N>,
      break;
    case 14: //    "IM" <N> "TOQ" <N>,
      break;
    case 15: //    "CM" <N> "TOQ" <N>,
      break;
    case 16: //    "CI" <N> "TOQ" <N>,
      break;
    case 17: //    "I" <N> "=" <Opt_Plus> <N>,
      break;

    case 25: //    "M" <Plus> "I" <N>,
      break;
    case 26: //    "X+" <Opt_Plus> <N>,
      break;
    case 27: //    "X+C" <N>,
      break;

    // Need to map these to all-alpha names...
    case 53: //    "/DF",
    case 54: //    "/D",
    case 55: //    "/F",
    case 56: //    "/R",
    case 57: //    "/I",
    case 58: //    "/",
    case 59: //    "+DF",
    case 60: //    "+D",
    case 61: //    "+F",
    case 62: //    "+",
    case 63: //    "-DF",
    case 64: //    "-D",
    case 65: //    "-F",
    case 66: //    "-",
    case 70: //    "X+F",
    case 71: //    "X+",
    case 72: //    "=TR",
      break;

    case 24: //    "LINK",

    case 28: //    "ROUNDHF",
    case 29: //    "ROUNDF",
    case 30: //    "ROUNDH",
    case 31: //    "ROUND",
    case 32: //    "FLOATD",
    case 33: //    "FLOAT",
    case 34: //    "ERASE",
    case 35: //    "REVD",
    case 36: //    "REV",
    case 37: //    "ZERO",
    case 38: //    "DUPD",
    case 39: //    "DUP",
    case 40: //    "NEGDF",
    case 41: //    "NEGF",
    case 42: //    "NEGD",
    case 43: //    "NEG",
    case 44: //    "ABSF",
    case 45: //    "ABS",
    case 46: //    "MAXF",
    case 47: //    "MAX",
    case 48: //    "SIGNF",
    case 49: //    "SIGN",
    case 50: //    "CAB",
    case 51: //    "FRB",
    case 52: //    "STAND",
    case 67: //    "XDF",
    case 68: //    "XD",
    case 69: //    "XF",
    case 73: //    "BITS",
    case 74: //    "DUMMY",
    case 75: //    "PERM",
    case 76: //    "TOP",
    case 77: //    "OR",
    case 78: //    "VR",
    case 79: //    "NEV",
    case 80: //    "NOT",
    case 81: //    "FIX",
    case 82: //    "STR",
    case 83: //    "CONT",
    case 84: //    "AND",
    case 85: //    "EXIT",
    case 86: //    "OUT",
    case 87: //    "X",

      fprintf(stdout, "KDF9_%s();\n", keyword[P(P(p,1),1)]);
      return;

    case 88: //    "P" <IOM> <ATOF> "Q" <N>,
      break;

    case 6: //    "EXIT" <N>,
    case 18: //    "Q" <N>,
    case 19: //    "C" <N>,
    case 20: //    "I" <N>,
    case 21: //    "M" <N>,
    case 22: //    "NC" <N>,
    case 23: //    "DC" <N>,
    case 89: //    "TLOG" <N>,
    case 90: //    "INTQ" <N>,
    case 91: //    "PARQ" <N>,
    case 92: //    "BUSYQ" <N>,
    case 93: //    "MANUALQ" <N>,
    case 94: //    "CTQ" <N>,
    case 95: //    "CLOQ" <N>,
    case 97: //    "ADVCA" <N>,
    case 100: //   "JSE" <N>,
    case 101: //   "JE" <N>,

      fprintf(stdout, "KDF9_%s(", keyword[P(P(p,1),1)]);
      compile(P(p,2));
      fprintf(stdout, ");\n");
      return;

    case 96: //    "SET" <Opt_Plus> <N>,
      break;

    case 98: //    <OCTAL> "/" <OCTAL> "/" <OCTAL>,
      break;
    case 99: //    <Opt_Equals> "E" <N> <E_INSTR>,
      break;

    case 102: //    null asm is treated as an ALIGN directive
      fprintf(stdout, "/* .ALIGN */\n");
      return;
    }
    fprintf(stdout, "/* To do: kdf9 instruction */\n");
    return;

  case P_J_INSTR: break;
  case P_MS_INSTR: break;
  case P_SH_INSTR: break;
  case P_QS_INSTR: break;
  case P_Plus: break;
  case P_Opt_Equals: break;
  case P_Opt_P: break;
  case P_IOM: break;
  case P_ATOF: break;
  case P_E_INSTR: break;
  // bips
  case P_EOD: break;

  case P_NAME: 
    fprintf(stdout, "%.*s", SOURCE(p));
    break;

  case P_N:
    fprintf(stdout, "%.*s", SOURCE(p));
    break;

  case P_OCTAL: break;
  case P_SETMARKER1: break;
  case P_SETMARKER2: break;
  case P_S: break;
  case P_TEXT: break;
  case P_CAPTIONTEXT: break;

  case P_CONST:
    fprintf(stdout, "%s", C_CONST(p));
    break;
  }  
}

int main(int argc, char **argv) {
  FILE *f;
  int ocp;
  int line;
  int entrypt;

  f = fopen("imp9.aapp", "r");
  if (f == NULL) {
    fprintf(stderr, "Please prepare ./filter < imp9.aa > imp9.aapp\n");
  }

  (void)fseek(f, (off_t)0L, SEEK_END);
  fp = (int)ftell(f);
  (void)fseek(f, (off_t)0L, SEEK_SET);
  if (debug_parser) fprintf(stderr, "File length = %d\n", fp);
  c = (char *)malloc(fp);
  fread(c, 1, fp, f);
  ocp = cp = 0;
  line = 1;
  while (parse(P_SS,0)) { // with cp as global state
    entrypt = build_ast(0, 0); 
    fprintf(stdout, "                                                 // %4d  %.*s\n", line, cp-ocp-(c[cp-1]=='\n'?1:0), &c[ocp]);
    compile(entrypt);
    if (stop_compiling || (cp == fp)) break;
    line++; ocp = cp; ap = 0;
  }

//\\ E

  if (!stop_compiling) {
    int p = cp;
    fprintf(stderr, "Failed at imp9.aapp, line %d: \"", line);
    for (;;) {
      if (c[p] == '\n') break;
      if (p == fp) {fprintf(stderr, "<EOF>"); break;}
      fputc(c[p], stderr);
      p += 1;
    }
    fputc('"', stderr); fputc('\n', stderr);
    exit(1);
  }

  /* If we were doing whole-program compilation we would do it here. */

  return 0;
  exit(1);
}


