#ifndef _GRAMMAR_H_
#define _GRAMMAR_H_ 1

#include <wchar.h>

#ifndef TRUE
#define TRUE (0==0)
#endif

#ifndef FALSE
#define FALSE (0!=0)
#endif

typedef int (*parsefn)(void);

#define LARGEST_ALT 14 // Max number of phrases in any Alt: 0 (Reserved), 1:13

#define NEGATED_PHRASE     (1U<<24U)
#define GUARD_PHRASE       (1U<<25U)
#define WHITESPACE_ALLOWED (1U<<26U)
#define GRAMMAR_TYPE_SHIFT 27U
#define GRAMMAR_TYPE_MASK  31U
#define BIP_TYPE         (1U <<27U)
#define PHRASE_TYPE      (2U <<27U)
#define SEMANTIC_TYPE    (3U <<27U)
#define KEYWORD_TYPE     (4U <<27U)
#define CHAR_TYPE        (5U <<27U)
#define UTF32CHAR_TYPE   (6U <<27U)
#define STRING_TYPE      (7U <<27U)
#define UTF32STRING_TYPE (8U <<27U)
#define REGEXP_TYPE      (9U <<27U)
#define OPTION_TYPE      (10U <<27U)
#define COUNT_OF_ALTS    (11U <<27U)
#define COUNT_OF_PHRASES (12U <<27U)
#define ALT_NUMBER       (13U <<27U)
#define INDEX_MASK       0x7FFFFFU
// (We have room for types 1..31U)
#define PhraseType(idx)  ((((idx)>>27U)&31U))


#define BIP_BASE 0
#define PHRASE_BASE 3
#define SEMANTIC_BASE 149
#define AST_BASE 157

#define NUM_BIPS 3
#define NUM_SIMPLE_PHRASES 146
#define NUM_SEMANTIC_PHRASES 8
#define NUM_PHRASES (NUM_BIPS+NUM_SIMPLE_PHRASES+NUM_SEMANTIC_PHRASES)

#define NUM_KEYWORDS 62
#define NUM_REGEXPS 8
#define NUM_GRAMMAR 1076

#define B_eof 0
#define B_ch 1
#define B_nl 2
#define P_XXCall_or_Assign_AUI 3
#define P_PUSHDECS 4
#define P_POPDECS 5
#define P_INITDECS 6
#define P_nls 7
#define P_READLINEP 8
#define P_S 9
#define P_DOWN 10
#define P_UP 11
#define P_SS 12
#define P_BINOP 13
#define P_OP 14
#define P_MONOP 15
#define P_UOP 16
#define P_ASSOP 17
#define P_COMP1 18
#define P_COMP2 19
#define P_VARNAME 20
#define P_NAME 21
#define P_BigCharConst 22
#define P_CharConst 23
#define P_OptExponent 24
#define P_OptDecimal 25
#define P_LITCONST 26
#define P_CONST 27
#define P_N 28
#define P_dq 29
#define P_any 30
#define P_stringchars 31
#define P_ALIASTEXT 32
#define P_semi 33
#define P_Comment 34
#define P_TEXT 35
#define P_Opt_Record_Field 36
#define P_VAR 37
#define P_OPERAND 38
#define P_CONSTVAR 39
#define P_COPERAND 40
#define P_CEXPR 41
#define P_CTORP 42
#define P_STAROREXPR 43
#define P_TORP 44
#define P_EXPR 45
#define P_RESTOFEXPR 46
#define P_RESTOFCEXPR 47
#define P_APP 48
#define P_RESTOFAPP 49
#define P_PC_IU 50
#define P_TOP_LEVEL_CONDITION 51
#define P_CYCPARM 52
#define P_PC_WUF 53
#define P_ALIAS 54
#define P_DECLNAMES 55
#define P_DECLNAME 56
#define P_FULLTYPE 57
#define P_BTYPE 58
#define P_XTYPE 59
#define P_RT 60
#define P_FM 61
#define P_FPDEL 62
#define P_Opt_N_type 63
#define P_Opt_AN_N_type 64
#define P_FPP 65
#define P_Opt_comma 66
#define P_RESTOFFPLIST 67
#define P_ENDLIST 68
#define P_ARRAYFORMAT 69
#define P_RESTOFSC 70
#define P_SC 71
#define P_RESTOFCOND 72
#define P_RESTOFANDC 73
#define P_RESTOFORC 74
#define P_Optional_Assignment 75
#define P_Opt_RtFnMapSpec 76
#define P_VSPECQ 77
#define P_RESTOFBPLIST 78
#define P_BPAIR 79
#define P_RESTOFARLIST 80
#define P_ADECLN 81
#define P_DECLN 82
#define P_OWNDEC 83
#define P_RESTOFOWNDEC 84
#define P_XOWN 85
#define P_CONSTLIST 86
#define P_ExPop 87
#define P_ROCL 88
#define P_REPFACT 89
#define P_RESTOFNLIST 90
#define P_PC_EVENTQ 91
#define P_Opt_EXPR 92
#define P_RESTOFSWLIST 93
#define P_RESTOFREPEAT 94
#define P_FINISHELSEQ 95
#define P_AFTERELSE 96
#define P_ELSEQ 97
#define P_RESTOFIU 98
#define P_Opt_Const_Init 99
#define P_SEX 100
#define P_RFSTMNT 101
#define P_RFREF 102
#define P_RESTOFRFDEC 103
#define P_RFDEC 104
#define P_RFELMNT 105
#define P_ALTRFDEC 106
#define P_ASM 107
#define P_Call_or_Assign_AUI 108
#define P_SWITCHIDX 109
#define P_Goto 110
#define P_return 111
#define P_result 112
#define P_monitor_AUI 113
#define P_stop 114
#define P_signal 115
#define P_exit 116
#define P_continue 117
#define P_Unconditional_Instructions 118
#define P_UI 119
#define P_AUI 120
#define P_UI_BLOCK 121
#define P_NONFINAL_UI 122
#define P_FINAL_UI 123
#define P_More_STATEMENTS 124
#define P_STATEMENTS 125
#define P_Labels 126
#define P_If_or_Unless 127
#define P_Opt_CYCPARM 128
#define P_start_of_cycle 129
#define P_end_of_cycle 130
#define P_regular_declaration 131
#define P_proc_declaration 132
#define P_own_or_external_declaration 133
#define P_on_event_block 134
#define P_record_format_declaration 135
#define P_various_ends 136
#define P_include_file 137
#define P_begin_block 138
#define P_switch_declaration 139
#define P_list_on 140
#define P_else 141
#define P_finish_opt_else 142
#define P_embedded_assembler 143
#define P_trusted 144
#define P_mainep 145
#define P_control 146
#define P_PSEMI 147
#define P_STATEMENT 148
#define S_init 0
#define S_terminate 1
#define S_whitespace 2
#define S_Imp77_stropping 3
#define S_COLON 4
#define S_INCLUDE 5
#define S_LISTON 6
#define S_LISTOFF 7

extern const int bip_map[NUM_BIPS];
extern const int sequential_phrase_no_to_grammar_index[NUM_SIMPLE_PHRASES];
extern const wchar_t *phrasename[NUM_BIPS+NUM_SIMPLE_PHRASES+NUM_SEMANTIC_PHRASES];

extern const wchar_t *semantic_phrasename[NUM_SEMANTIC_PHRASES];
extern const wchar_t *semantic_code[NUM_SEMANTIC_PHRASES];
extern const wchar_t *ast_code[NUM_SIMPLE_PHRASES];
extern const wchar_t *xcomment[NUM_PHRASES];
extern const wchar_t *keyword[NUM_KEYWORDS];
extern const wchar_t *regexps[NUM_REGEXPS];

extern const int gram[NUM_GRAMMAR];
#define G_XXCall_or_Assign_AUI 0
#define G_PUSHDECS 6
#define G_POPDECS 9
#define G_INITDECS 11
#define G_nls 13
#define G_READLINEP 18
#define G_S 22
#define G_DOWN 27
#define G_UP 29
#define G_SS 31
#define G_BINOP 37
#define G_OP 82
#define G_MONOP 85
#define G_UOP 95
#define G_ASSOP 98
#define G_COMP1 110
#define G_COMP2 144
#define G_VARNAME 147
#define G_NAME 151
#define G_BigCharConst 155
#define G_CharConst 158
#define G_OptExponent 165
#define G_OptDecimal 170
#define G_LITCONST 175
#define G_CONST 190
#define G_N 193
#define G_dq 196
#define G_any 199
#define G_stringchars 202
#define G_ALIASTEXT 212
#define G_semi 217
#define G_Comment 220
#define G_TEXT 230
#define G_Opt_Record_Field 236
#define G_VAR 243
#define G_OPERAND 248
#define G_CONSTVAR 257
#define G_COPERAND 260
#define G_CEXPR 269
#define G_CTORP 272
#define G_STAROREXPR 277
#define G_TORP 284
#define G_EXPR 289
#define G_RESTOFEXPR 292
#define G_RESTOFCEXPR 298
#define G_APP 304
#define G_RESTOFAPP 311
#define G_PC_IU 318
#define G_TOP_LEVEL_CONDITION 323
#define G_CYCPARM 327
#define G_PC_WUF 336
#define G_ALIAS 346
#define G_DECLNAMES 351
#define G_DECLNAME 358
#define G_FULLTYPE 361
#define G_BTYPE 365
#define G_XTYPE 370
#define G_RT 399
#define G_FM 405
#define G_FPDEL 412
#define G_Opt_N_type 428
#define G_Opt_AN_N_type 432
#define G_FPP 439
#define G_Opt_comma 448
#define G_RESTOFFPLIST 452
#define G_ENDLIST 461
#define G_ARRAYFORMAT 474
#define G_RESTOFSC 478
#define G_SC 483
#define G_RESTOFCOND 497
#define G_RESTOFANDC 507
#define G_RESTOFORC 513
#define G_Optional_Assignment 519
#define G_Opt_RtFnMapSpec 524
#define G_VSPECQ 528
#define G_RESTOFBPLIST 532
#define G_BPAIR 540
#define G_RESTOFARLIST 548
#define G_ADECLN 553
#define G_DECLN 559
#define G_OWNDEC 568
#define G_RESTOFOWNDEC 583
#define G_XOWN 592
#define G_CONSTLIST 603
#define G_ExPop 613
#define G_ROCL 615
#define G_REPFACT 626
#define G_RESTOFNLIST 632
#define G_PC_EVENTQ 638
#define G_Opt_EXPR 642
#define G_RESTOFSWLIST 647
#define G_RESTOFREPEAT 659
#define G_FINISHELSEQ 664
#define G_AFTERELSE 669
#define G_ELSEQ 678
#define G_RESTOFIU 683
#define G_Opt_Const_Init 693
#define G_SEX 700
#define G_RFSTMNT 712
#define G_RFREF 725
#define G_RESTOFRFDEC 732
#define G_RFDEC 739
#define G_RFELMNT 749
#define G_ALTRFDEC 757
#define G_ASM 764
#define G_Call_or_Assign_AUI 772
#define G_SWITCHIDX 779
#define G_Goto 785
#define G_return 791
#define G_result 794
#define G_monitor_AUI 799
#define G_stop 802
#define G_signal 805
#define G_exit 811
#define G_continue 814
#define G_Unconditional_Instructions 817
#define G_UI 830
#define G_AUI 838
#define G_UI_BLOCK 842
#define G_NONFINAL_UI 850
#define G_FINAL_UI 855
#define G_More_STATEMENTS 870
#define G_STATEMENTS 875
#define G_Labels 880
#define G_If_or_Unless 899
#define G_Opt_CYCPARM 905
#define G_start_of_cycle 909
#define G_end_of_cycle 918
#define G_regular_declaration 923
#define G_proc_declaration 929
#define G_own_or_external_declaration 939
#define G_on_event_block 946
#define G_record_format_declaration 954
#define G_various_ends 961
#define G_include_file 966
#define G_begin_block 971
#define G_switch_declaration 976
#define G_list_on 989
#define G_else 994
#define G_finish_opt_else 998
#define G_embedded_assembler 1003
#define G_trusted 1008
#define G_mainep 1012
#define G_control 1017
#define G_PSEMI 1022
#define G_STATEMENT 1024

extern parsefn parsetime[NUM_SEMANTIC_PHRASES];
extern int parse_init(void);
extern int parse_terminate(void);
extern int parse_whitespace(void);
extern int parse_Imp77_stropping(void);
extern int parse_COLON(void);
extern int parse_INCLUDE(void);
extern int parse_LISTON(void);
extern int parse_LISTOFF(void);

#ifndef SUPPRESS_DATA
const wchar_t *phrasename[NUM_BIPS+NUM_SIMPLE_PHRASES+NUM_SEMANTIC_PHRASES] = {
  /*0+0*/   L"eof" /*0*/,
  /*0+1*/   L"ch" /*1*/,
  /*0+2*/   L"nl" /*2*/,
  /*3+0*/   L"XXCall_or_Assign_AUI",
  /*3+1*/   L"PUSHDECS",
  /*3+2*/   L"POPDECS",
  /*3+3*/   L"INITDECS",
  /*3+4*/   L"nls",
  /*3+5*/   L"READLINEP",
  /*3+6*/   L"S",
  /*3+7*/   L"DOWN",
  /*3+8*/   L"UP",
  /*3+9*/   L"SS",
  /*3+10*/   L"BINOP",
  /*3+11*/   L"OP",
  /*3+12*/   L"MONOP",
  /*3+13*/   L"UOP",
  /*3+14*/   L"ASSOP",
  /*3+15*/   L"COMP1",
  /*3+16*/   L"COMP2",
  /*3+17*/   L"VARNAME",
  /*3+18*/   L"NAME",
  /*3+19*/   L"BigCharConst",
  /*3+20*/   L"CharConst",
  /*3+21*/   L"OptExponent",
  /*3+22*/   L"OptDecimal",
  /*3+23*/   L"LITCONST",
  /*3+24*/   L"CONST",
  /*3+25*/   L"N",
  /*3+26*/   L"dq",
  /*3+27*/   L"any",
  /*3+28*/   L"stringchars",
  /*3+29*/   L"ALIASTEXT",
  /*3+30*/   L"semi",
  /*3+31*/   L"Comment",
  /*3+32*/   L"TEXT",
  /*3+33*/   L"Opt_Record_Field",
  /*3+34*/   L"VAR",
  /*3+35*/   L"OPERAND",
  /*3+36*/   L"CONSTVAR",
  /*3+37*/   L"COPERAND",
  /*3+38*/   L"CEXPR",
  /*3+39*/   L"CTORP",
  /*3+40*/   L"STAROREXPR",
  /*3+41*/   L"TORP",
  /*3+42*/   L"EXPR",
  /*3+43*/   L"RESTOFEXPR",
  /*3+44*/   L"RESTOFCEXPR",
  /*3+45*/   L"APP",
  /*3+46*/   L"RESTOFAPP",
  /*3+47*/   L"PC_IU",
  /*3+48*/   L"TOP_LEVEL_CONDITION",
  /*3+49*/   L"CYCPARM",
  /*3+50*/   L"PC_WUF",
  /*3+51*/   L"ALIAS",
  /*3+52*/   L"DECLNAMES",
  /*3+53*/   L"DECLNAME",
  /*3+54*/   L"FULLTYPE",
  /*3+55*/   L"BTYPE",
  /*3+56*/   L"XTYPE",
  /*3+57*/   L"RT",
  /*3+58*/   L"FM",
  /*3+59*/   L"FPDEL",
  /*3+60*/   L"Opt_N_type",
  /*3+61*/   L"Opt_AN_N_type",
  /*3+62*/   L"FPP",
  /*3+63*/   L"Opt_comma",
  /*3+64*/   L"RESTOFFPLIST",
  /*3+65*/   L"ENDLIST",
  /*3+66*/   L"ARRAYFORMAT",
  /*3+67*/   L"RESTOFSC",
  /*3+68*/   L"SC",
  /*3+69*/   L"RESTOFCOND",
  /*3+70*/   L"RESTOFANDC",
  /*3+71*/   L"RESTOFORC",
  /*3+72*/   L"Optional_Assignment",
  /*3+73*/   L"Opt_RtFnMapSpec",
  /*3+74*/   L"VSPECQ",
  /*3+75*/   L"RESTOFBPLIST",
  /*3+76*/   L"BPAIR",
  /*3+77*/   L"RESTOFARLIST",
  /*3+78*/   L"ADECLN",
  /*3+79*/   L"DECLN",
  /*3+80*/   L"OWNDEC",
  /*3+81*/   L"RESTOFOWNDEC",
  /*3+82*/   L"XOWN",
  /*3+83*/   L"CONSTLIST",
  /*3+84*/   L"ExPop",
  /*3+85*/   L"ROCL",
  /*3+86*/   L"REPFACT",
  /*3+87*/   L"RESTOFNLIST",
  /*3+88*/   L"PC_EVENTQ",
  /*3+89*/   L"Opt_EXPR",
  /*3+90*/   L"RESTOFSWLIST",
  /*3+91*/   L"RESTOFREPEAT",
  /*3+92*/   L"FINISHELSEQ",
  /*3+93*/   L"AFTERELSE",
  /*3+94*/   L"ELSEQ",
  /*3+95*/   L"RESTOFIU",
  /*3+96*/   L"Opt_Const_Init",
  /*3+97*/   L"SEX",
  /*3+98*/   L"RFSTMNT",
  /*3+99*/   L"RFREF",
  /*3+100*/   L"RESTOFRFDEC",
  /*3+101*/   L"RFDEC",
  /*3+102*/   L"RFELMNT",
  /*3+103*/   L"ALTRFDEC",
  /*3+104*/   L"ASM",
  /*3+105*/   L"Call_or_Assign_AUI",
  /*3+106*/   L"SWITCHIDX",
  /*3+107*/   L"Goto",
  /*3+108*/   L"return",
  /*3+109*/   L"result",
  /*3+110*/   L"monitor_AUI",
  /*3+111*/   L"stop",
  /*3+112*/   L"signal",
  /*3+113*/   L"exit",
  /*3+114*/   L"continue",
  /*3+115*/   L"Unconditional_Instructions",
  /*3+116*/   L"UI",
  /*3+117*/   L"AUI",
  /*3+118*/   L"UI_BLOCK",
  /*3+119*/   L"NONFINAL_UI",
  /*3+120*/   L"FINAL_UI",
  /*3+121*/   L"More_STATEMENTS",
  /*3+122*/   L"STATEMENTS",
  /*3+123*/   L"Labels",
  /*3+124*/   L"If_or_Unless",
  /*3+125*/   L"Opt_CYCPARM",
  /*3+126*/   L"start_of_cycle",
  /*3+127*/   L"end_of_cycle",
  /*3+128*/   L"regular_declaration",
  /*3+129*/   L"proc_declaration",
  /*3+130*/   L"own_or_external_declaration",
  /*3+131*/   L"on_event_block",
  /*3+132*/   L"record_format_declaration",
  /*3+133*/   L"various_ends",
  /*3+134*/   L"include_file",
  /*3+135*/   L"begin_block",
  /*3+136*/   L"switch_declaration",
  /*3+137*/   L"list_on",
  /*3+138*/   L"else",
  /*3+139*/   L"finish_opt_else",
  /*3+140*/   L"embedded_assembler",
  /*3+141*/   L"trusted",
  /*3+142*/   L"mainep",
  /*3+143*/   L"control",
  /*3+144*/   L"PSEMI",
  /*3+145*/   L"STATEMENT",
  /*149+0*/   L"init",
  /*149+1*/   L"terminate",
  /*149+2*/   L"whitespace",
  /*149+3*/   L"Imp77_stropping",
  /*149+4*/   L"COLON",
  /*149+5*/   L"INCLUDE",
  /*149+6*/   L"LISTON",
  /*149+7*/   L"LISTOFF",
};
const wchar_t *phrasename_c[NUM_BIPS+NUM_SIMPLE_PHRASES+NUM_SEMANTIC_PHRASES] = {
  /*0+0*/   L"eof" /*0*/,
  /*0+1*/   L"ch" /*1*/,
  /*0+2*/   L"nl" /*2*/,
  /*3+0*/   L"XXCall_or_Assign_AUI",
  /*3+1*/   L"PUSHDECS",
  /*3+2*/   L"POPDECS",
  /*3+3*/   L"INITDECS",
  /*3+4*/   L"nls",
  /*3+5*/   L"READLINEP",
  /*3+6*/   L"S",
  /*3+7*/   L"DOWN",
  /*3+8*/   L"UP",
  /*3+9*/   L"SS",
  /*3+10*/   L"BINOP",
  /*3+11*/   L"OP",
  /*3+12*/   L"MONOP",
  /*3+13*/   L"UOP",
  /*3+14*/   L"ASSOP",
  /*3+15*/   L"COMP1",
  /*3+16*/   L"COMP2",
  /*3+17*/   L"VARNAME",
  /*3+18*/   L"NAME",
  /*3+19*/   L"BigCharConst",
  /*3+20*/   L"CharConst",
  /*3+21*/   L"OptExponent",
  /*3+22*/   L"OptDecimal",
  /*3+23*/   L"LITCONST",
  /*3+24*/   L"CONST",
  /*3+25*/   L"N",
  /*3+26*/   L"dq",
  /*3+27*/   L"any",
  /*3+28*/   L"stringchars",
  /*3+29*/   L"ALIASTEXT",
  /*3+30*/   L"semi",
  /*3+31*/   L"Comment",
  /*3+32*/   L"TEXT",
  /*3+33*/   L"Opt_Record_Field",
  /*3+34*/   L"VAR",
  /*3+35*/   L"OPERAND",
  /*3+36*/   L"CONSTVAR",
  /*3+37*/   L"COPERAND",
  /*3+38*/   L"CEXPR",
  /*3+39*/   L"CTORP",
  /*3+40*/   L"STAROREXPR",
  /*3+41*/   L"TORP",
  /*3+42*/   L"EXPR",
  /*3+43*/   L"RESTOFEXPR",
  /*3+44*/   L"RESTOFCEXPR",
  /*3+45*/   L"APP",
  /*3+46*/   L"RESTOFAPP",
  /*3+47*/   L"PC_IU",
  /*3+48*/   L"TOP_LEVEL_CONDITION",
  /*3+49*/   L"CYCPARM",
  /*3+50*/   L"PC_WUF",
  /*3+51*/   L"ALIAS",
  /*3+52*/   L"DECLNAMES",
  /*3+53*/   L"DECLNAME",
  /*3+54*/   L"FULLTYPE",
  /*3+55*/   L"BTYPE",
  /*3+56*/   L"XTYPE",
  /*3+57*/   L"RT",
  /*3+58*/   L"FM",
  /*3+59*/   L"FPDEL",
  /*3+60*/   L"Opt_N_type",
  /*3+61*/   L"Opt_AN_N_type",
  /*3+62*/   L"FPP",
  /*3+63*/   L"Opt_comma",
  /*3+64*/   L"RESTOFFPLIST",
  /*3+65*/   L"ENDLIST",
  /*3+66*/   L"ARRAYFORMAT",
  /*3+67*/   L"RESTOFSC",
  /*3+68*/   L"SC",
  /*3+69*/   L"RESTOFCOND",
  /*3+70*/   L"RESTOFANDC",
  /*3+71*/   L"RESTOFORC",
  /*3+72*/   L"Optional_Assignment",
  /*3+73*/   L"Opt_RtFnMapSpec",
  /*3+74*/   L"VSPECQ",
  /*3+75*/   L"RESTOFBPLIST",
  /*3+76*/   L"BPAIR",
  /*3+77*/   L"RESTOFARLIST",
  /*3+78*/   L"ADECLN",
  /*3+79*/   L"DECLN",
  /*3+80*/   L"OWNDEC",
  /*3+81*/   L"RESTOFOWNDEC",
  /*3+82*/   L"XOWN",
  /*3+83*/   L"CONSTLIST",
  /*3+84*/   L"ExPop",
  /*3+85*/   L"ROCL",
  /*3+86*/   L"REPFACT",
  /*3+87*/   L"RESTOFNLIST",
  /*3+88*/   L"PC_EVENTQ",
  /*3+89*/   L"Opt_EXPR",
  /*3+90*/   L"RESTOFSWLIST",
  /*3+91*/   L"RESTOFREPEAT",
  /*3+92*/   L"FINISHELSEQ",
  /*3+93*/   L"AFTERELSE",
  /*3+94*/   L"ELSEQ",
  /*3+95*/   L"RESTOFIU",
  /*3+96*/   L"Opt_Const_Init",
  /*3+97*/   L"SEX",
  /*3+98*/   L"RFSTMNT",
  /*3+99*/   L"RFREF",
  /*3+100*/   L"RESTOFRFDEC",
  /*3+101*/   L"RFDEC",
  /*3+102*/   L"RFELMNT",
  /*3+103*/   L"ALTRFDEC",
  /*3+104*/   L"ASM",
  /*3+105*/   L"Call_or_Assign_AUI",
  /*3+106*/   L"SWITCHIDX",
  /*3+107*/   L"Goto",
  /*3+108*/   L"return",
  /*3+109*/   L"result",
  /*3+110*/   L"monitor_AUI",
  /*3+111*/   L"stop",
  /*3+112*/   L"signal",
  /*3+113*/   L"exit",
  /*3+114*/   L"continue",
  /*3+115*/   L"Unconditional_Instructions",
  /*3+116*/   L"UI",
  /*3+117*/   L"AUI",
  /*3+118*/   L"UI_BLOCK",
  /*3+119*/   L"NONFINAL_UI",
  /*3+120*/   L"FINAL_UI",
  /*3+121*/   L"More_STATEMENTS",
  /*3+122*/   L"STATEMENTS",
  /*3+123*/   L"Labels",
  /*3+124*/   L"If_or_Unless",
  /*3+125*/   L"Opt_CYCPARM",
  /*3+126*/   L"start_of_cycle",
  /*3+127*/   L"end_of_cycle",
  /*3+128*/   L"regular_declaration",
  /*3+129*/   L"proc_declaration",
  /*3+130*/   L"own_or_external_declaration",
  /*3+131*/   L"on_event_block",
  /*3+132*/   L"record_format_declaration",
  /*3+133*/   L"various_ends",
  /*3+134*/   L"include_file",
  /*3+135*/   L"begin_block",
  /*3+136*/   L"switch_declaration",
  /*3+137*/   L"list_on",
  /*3+138*/   L"else",
  /*3+139*/   L"finish_opt_else",
  /*3+140*/   L"embedded_assembler",
  /*3+141*/   L"trusted",
  /*3+142*/   L"mainep",
  /*3+143*/   L"control",
  /*3+144*/   L"PSEMI",
  /*3+145*/   L"STATEMENT",
  /*149+0*/   L"init",
  /*149+1*/   L"terminate",
  /*149+2*/   L"whitespace",
  /*149+3*/   L"Imp77_stropping",
  /*149+4*/   L"COLON",
  /*149+5*/   L"INCLUDE",
  /*149+6*/   L"LISTON",
  /*149+7*/   L"LISTOFF",
};
const int bip_map[NUM_BIPS] = {
  /*0*/   0,
  /*1*/   1,
  /*2*/   2,
};
const int sequential_phrase_no_to_grammar_index[NUM_SIMPLE_PHRASES] = {
  G_XXCall_or_Assign_AUI,  /*0*/
  G_PUSHDECS,  /*6*/
  G_POPDECS,  /*9*/
  G_INITDECS,  /*11*/
  G_nls,  /*13*/
  G_READLINEP,  /*18*/
  G_S,  /*22*/
  G_DOWN,  /*27*/
  G_UP,  /*29*/
  G_SS,  /*31*/
  G_BINOP,  /*37*/
  G_OP,  /*82*/
  G_MONOP,  /*85*/
  G_UOP,  /*95*/
  G_ASSOP,  /*98*/
  G_COMP1,  /*110*/
  G_COMP2,  /*144*/
  G_VARNAME,  /*147*/
  G_NAME,  /*151*/
  G_BigCharConst,  /*155*/
  G_CharConst,  /*158*/
  G_OptExponent,  /*165*/
  G_OptDecimal,  /*170*/
  G_LITCONST,  /*175*/
  G_CONST,  /*190*/
  G_N,  /*193*/
  G_dq,  /*196*/
  G_any,  /*199*/
  G_stringchars,  /*202*/
  G_ALIASTEXT,  /*212*/
  G_semi,  /*217*/
  G_Comment,  /*220*/
  G_TEXT,  /*230*/
  G_Opt_Record_Field,  /*236*/
  G_VAR,  /*243*/
  G_OPERAND,  /*248*/
  G_CONSTVAR,  /*257*/
  G_COPERAND,  /*260*/
  G_CEXPR,  /*269*/
  G_CTORP,  /*272*/
  G_STAROREXPR,  /*277*/
  G_TORP,  /*284*/
  G_EXPR,  /*289*/
  G_RESTOFEXPR,  /*292*/
  G_RESTOFCEXPR,  /*298*/
  G_APP,  /*304*/
  G_RESTOFAPP,  /*311*/
  G_PC_IU,  /*318*/
  G_TOP_LEVEL_CONDITION,  /*323*/
  G_CYCPARM,  /*327*/
  G_PC_WUF,  /*336*/
  G_ALIAS,  /*346*/
  G_DECLNAMES,  /*351*/
  G_DECLNAME,  /*358*/
  G_FULLTYPE,  /*361*/
  G_BTYPE,  /*365*/
  G_XTYPE,  /*370*/
  G_RT,  /*399*/
  G_FM,  /*405*/
  G_FPDEL,  /*412*/
  G_Opt_N_type,  /*428*/
  G_Opt_AN_N_type,  /*432*/
  G_FPP,  /*439*/
  G_Opt_comma,  /*448*/
  G_RESTOFFPLIST,  /*452*/
  G_ENDLIST,  /*461*/
  G_ARRAYFORMAT,  /*474*/
  G_RESTOFSC,  /*478*/
  G_SC,  /*483*/
  G_RESTOFCOND,  /*497*/
  G_RESTOFANDC,  /*507*/
  G_RESTOFORC,  /*513*/
  G_Optional_Assignment,  /*519*/
  G_Opt_RtFnMapSpec,  /*524*/
  G_VSPECQ,  /*528*/
  G_RESTOFBPLIST,  /*532*/
  G_BPAIR,  /*540*/
  G_RESTOFARLIST,  /*548*/
  G_ADECLN,  /*553*/
  G_DECLN,  /*559*/
  G_OWNDEC,  /*568*/
  G_RESTOFOWNDEC,  /*583*/
  G_XOWN,  /*592*/
  G_CONSTLIST,  /*603*/
  G_ExPop,  /*613*/
  G_ROCL,  /*615*/
  G_REPFACT,  /*626*/
  G_RESTOFNLIST,  /*632*/
  G_PC_EVENTQ,  /*638*/
  G_Opt_EXPR,  /*642*/
  G_RESTOFSWLIST,  /*647*/
  G_RESTOFREPEAT,  /*659*/
  G_FINISHELSEQ,  /*664*/
  G_AFTERELSE,  /*669*/
  G_ELSEQ,  /*678*/
  G_RESTOFIU,  /*683*/
  G_Opt_Const_Init,  /*693*/
  G_SEX,  /*700*/
  G_RFSTMNT,  /*712*/
  G_RFREF,  /*725*/
  G_RESTOFRFDEC,  /*732*/
  G_RFDEC,  /*739*/
  G_RFELMNT,  /*749*/
  G_ALTRFDEC,  /*757*/
  G_ASM,  /*764*/
  G_Call_or_Assign_AUI,  /*772*/
  G_SWITCHIDX,  /*779*/
  G_Goto,  /*785*/
  G_return,  /*791*/
  G_result,  /*794*/
  G_monitor_AUI,  /*799*/
  G_stop,  /*802*/
  G_signal,  /*805*/
  G_exit,  /*811*/
  G_continue,  /*814*/
  G_Unconditional_Instructions,  /*817*/
  G_UI,  /*830*/
  G_AUI,  /*838*/
  G_UI_BLOCK,  /*842*/
  G_NONFINAL_UI,  /*850*/
  G_FINAL_UI,  /*855*/
  G_More_STATEMENTS,  /*870*/
  G_STATEMENTS,  /*875*/
  G_Labels,  /*880*/
  G_If_or_Unless,  /*899*/
  G_Opt_CYCPARM,  /*905*/
  G_start_of_cycle,  /*909*/
  G_end_of_cycle,  /*918*/
  G_regular_declaration,  /*923*/
  G_proc_declaration,  /*929*/
  G_own_or_external_declaration,  /*939*/
  G_on_event_block,  /*946*/
  G_record_format_declaration,  /*954*/
  G_various_ends,  /*961*/
  G_include_file,  /*966*/
  G_begin_block,  /*971*/
  G_switch_declaration,  /*976*/
  G_list_on,  /*989*/
  G_else,  /*994*/
  G_finish_opt_else,  /*998*/
  G_embedded_assembler,  /*1003*/
  G_trusted,  /*1008*/
  G_mainep,  /*1012*/
  G_control,  /*1017*/
  G_PSEMI,  /*1022*/
  G_STATEMENT,  /*1024*/
};

const wchar_t *semantic_phrasename[NUM_SEMANTIC_PHRASES] = {
  /*0*/   L"init",
  /*1*/   L"terminate",
  /*2*/   L"whitespace",
  /*3*/   L"Imp77_stropping",
  /*4*/   L"COLON",
  /*5*/   L"INCLUDE",
  /*6*/   L"LISTON",
  /*7*/   L"LISTOFF",
};

const wchar_t *semantic_code[NUM_SEMANTIC_PHRASES] = {
  /*0*/   L"\n"
             "#ifdef IN_PARSER // regen etc use this too but don't need a lot of what uparse.c needs.\n"
             "  // perform any initialisation required by the parse-time semantic routines.\n"
             "  // Note that for now, we have no way of declaring data outside of\n"
             "  // those procedures.  Obviously this will have to change.\n"
             "\n"
             "  // LINE RECONSTRUCTION *might* GO HERE.  But probably not.\n"
             "  \n"
             "  // initially default scope is at the level appropriate for perms\n"
             "  \n"
             "  debug_scope = 0;\n"
             "  debug_ast = 0;\n"
             "  debug_ctrl_stack = 0;\n"
             "  debug_compiler = 0;\n"
             "  debug_declarations = 0;\n"
             "  debug_torp = 0;\n"
             "\n"
             "  //push_scope_level();\n"
             "  // Declare perms, prims here\n"
             "  //add_entry(\"decls\", \"NEWLINE\", 42); // param can be anything. Usually index into an array of records of the appropriate type.  During initial code creation, we'll just use random tags.\n"
             "  // initial top-level file-level scope, eg for %externalroutines\n"
             "  //push_scope_level();\n"
             "  // ready for externals\n"
             "\n"
             "  //fprintf(stdout, \"\\n// Relies on using gtcpp to preprocess before cleaning up with clang-format\");\n"
             "  fprintf(stdout, \"\\n$define unless(cond) if (!(cond)) \\n$define until(cond) while(!(cond))\\n\");\n"
             "  \n"
             "#endif\n"
             "  return TRUE;\n",
  /*1*/   L"\n"
             "#ifdef IN_PARSER\n"
             "  // perform any final tidy-up required by the parse-time semantic routines.\n"
             "\n"
             "  //pop_scope_level(); // from externals back to perms\n"
             "  //pop_scope_level(); // from perms to none.\n"
             "#endif\n"
             "  return TRUE;\n",
  /*2*/   L"\n"
             "#ifdef IN_PARSER\n"
             "  while (source(TP).ch==' ' || source(TP).ch=='\\t' || source(TP).ch=='\\f') {\n"
             "    TP += 1;\n"
             "  }\n"
             "#endif\n"
             "  return TRUE;\n",
  /*3*/   L"\n"
             "#ifdef IN_PARSER\n"
             "  int debug_stropping = 0;\n"
             "\n"
             "  // The source file has already been read trivially into source().\n"
             "  \n"
             "  // We will copy from source() into temp(), then perform line reconstruction\n"
             "  // on temp(), writing back to source().  The parser will then parse source()\n"
             "  // into atoms according to the grammar.  Initially it will only store the\n"
             "  // reconstructed characters into the atoms, but once it is working, I will\n"
             "  // modify it to also store the unreconsructed source for use in source-to-source\n"
             "  // translations, where whitespace, embedded comments, and indentation is\n"
             "  // desired in the translation, in order to mirror the original file.\n"
             "\n"
             "  // Because unfortunately underlining in Unicode is done by a *following*\n"
             "  // underline joiner character (818) rather than being a single unicode\n"
             "  // code point, it is difficult to use a single-character encoding of a\n"
             "  // stropped keyword letter - what the old Imp compilers would represent\n"
             "  // by adding 128 to the character.  However there *is* an alternive\n"
             "  // source of upper case and lower case letters in the mathematics area!\n"
             "\n"
             "  // A:Z could be encoded as 1D400:1D419 and a:z as 1D41A:1D433 :-)\n"
             "  // but for now I'm encoding keywords in lower case and variables in\n"
             "  // upper case.\n"
             "  \n"
             "  // The 1D400+ encoding looks more or less like ordinary text if it happens\n"
             "  // to be displayed (e.g. during debugging) although there should never be\n"
             "  // any need to display internally-coded keywords to users of the\n"
             "  // compilers built with this parser.\n"
             "\n"
             "  // All arrays are flex and the upper bound is a limit, not a minimum.\n"
             "  DECLARE(SYM, reconstructed, 128000000/*600000*/);\n"
             "#define _SYM(x) WRITE(x,SYM,reconstructed)\n"
             "#define  SYM(x)  READ(x,SYM,reconstructed)\n"
             "\n"
             "  int LASTP, P = 0;\n"
             "  while (source(P).ch != 0 /* WEOF */) {\n"
             "    _SYM(P).ch = source(P).ch;\n"
             "    _SYM(P).start = P; _SYM(P).end = P+1;\n"
             "    P += 1;\n"
             "  }\n"
             "  _SYM(P).ch = 0 /* WEOF */;\n"
             "  _SYM(P).start = P; _SYM(P).end = P; // no chars for EOF\n"
             "  LASTP = P;\n"
             "  \n"
             "  if (debug_stropping) {\n"
             "    int I;\n"
             "    fprintf(stderr, \"source() moved to SYM(0:%d) = \\\"\", LASTP);\n"
             "    for (I = 0; I < LASTP; I++) {\n"
             "      /*if (SYM(I).ch != 0)*/ fprintf(stderr, \"%lc\", SYM(I).ch);\n"
             "    }\n"
             "    if (SYM(LASTP).ch != 0) fprintf(stderr, \"[%d]\", SYM(LASTP).ch);\n"
             "    fprintf(stderr, \"\\\";\\n\");\n"
             "  };\n"
             "\n"
             "  int FP = 0, PP = 0; // Fetch Pointer, Put Pointer.\n"
             "\n"
             "#define DONE() \\\n"
             "        do {                                                                      \\\n"
             "            FP -= 1; /* the terminating 0*/                                       \\\n"
             "            _source(PP).ch = 0;                                                   \\\n"
             "            _source(PP).end = SYM(FP).end;                                        \\\n"
             "            if (debug_stropping) {                                                \\\n"
             "              int I;                                                              \\\n"
             "              fprintf(stderr, \"SYM(0:%d) moved to source(0:%d) = \\\"\", FP, PP);    \\\n"
             "              for (I = 0; I < PP; I++) {                                          \\\n"
             "                if (source(I).ch != 0) fprintf(stderr, \"%lc\", source(I).ch);      \\\n"
             "              }                                                                   \\\n"
             "              if (source(PP).ch != 0) fprintf(stderr, \"[%d]\", source(PP).ch);     \\\n"
             "              fprintf(stderr, \"\\\";\\n\");                                           \\\n"
             "            }                                                                     \\\n"
             "            return TRUE;                                                          \\\n"
             "        } while (0)\n"
             "\n"
             "  wint_t WC;\n"
             "\n"
             "  // NOTE THAT WITH THIS IMP77 GRAMMAR, '\\n' IS NOT WHITESPACE.  LINE ENDINGS ARE EXPLICITLY\n"
             "  // ENTERED IN THE GRAMMAR.  (See the phrases <T>, and <NL_opt>.\n"
             "  \n"
             "  // uparse.c has been modified so that its implicit whitespace skipping no longer skips '\\n'.\n"
             "  // (The algol60 parser in contrast treats all \\n's the same as spaces)\n"
             "  \n"
             "  // HOW TO HANDLE ' IN A PARSED COMMENT?\n"
             "  //\n"
             "  // %COMMENT A ' MESSES UP!\n"
             "  //\n"
             "  // because it keeps scanning until a closing quote.  However if you don't scan between quotes,\n"
             "  // line reconstruction will lose spaces within strings!\n"
             "  //\n"
             "  // You can't just end a quoted string at a newline because embedded newlines are allowed.\n"
             "  // And I checked Imp77 - it allows a single quote ch in a comment.\n"
             "\n"
             "  // If line reconstruction were being done on the fly then it could be modified if we knew we were\n"
             "  // in a comment, but since we're doing it all in advance, the only option to handle this appears\n"
             "  // to be that whenever we're in a comment, we throw away all the following line reconstruction and\n"
             "  // re-do it, with that comment handled differently.\n"
             "\n"
             "  // Or bite the bullet and work out how to do line reconstruction on the fly (which my previous\n"
             "  // imptoc did eventually manage using the 'demandload' call. So *every* fetch via TP would have\n"
             "  // to be recoded as a procedure call, with on-the-fly line reconstruction, and either a way to\n"
             "  // undo it if backtracking or simply never doing it any farther past TP and undoing it on backtracking.\n"
             "\n"
             "  // What a can of worms just to handle badly designed comments.  TO DO.\n"
             "\n"
             "#define CHECK_EOF(x) do if ((x) == 0) DONE(); else { _source(PP).end = SYM(FP-1).end; } while (0)\n"
             "\n"
             "  // PP is the 'current' slot we are writing into.\n"
             "  _source(PP).start = SYM(FP).start;\n"
             "\n"
             "  for (;;) {\n"
             "\n"
             "    _source(PP).end = SYM(FP).end; // Keep updated.\n"
             "    WC = SYM(FP++).ch; CHECK_EOF(WC);\n"
             "\n"
             "    if (WC == '%') { // We found a keyword.  It will always be read up to the last character of the keyword.\n"
             "\n"
             "      for (;;) {\n"
             "        WC = SYM(FP++).ch; CHECK_EOF(WC);\n"
             "        if (WC == '%') {\n"
             "\n"
             "        } else if (!isalpha(WC)) {\n"
             "          // It's possible to have a bunch of '%' signs and *no* keyword characters.\n"
             "          --FP; // point FP back to the non-keyword character, not as currently, the one past that.\n"
             "          break;    \n"
             "        } else { // isalpha(WC)\n"
             "          if (isupper(WC)) WC = tolower(WC);\n"
             "          _source(PP).end = SYM(FP-1).end;\n"
             "          _source(PP++).ch = WC; // | 128\n"
             "          _source(PP).start = SYM(FP).start;\n"
             "        }\n"
             "      }\n"
             "      continue;\n"
             "    }\n"
             "\n"
             "    else if (WC == '{') {\n"
             "\n"
             "      for (;;) {\n"
             "        WC = SYM(FP++).ch; CHECK_EOF(WC);\n"
             "\n"
             "        if (WC == '\\n') {\n"
             "          --FP; /* re-read the \\n as a significant character */\n"
             "          // _source(PP).end = SYM(FP-1).end; // point FP back to the newline\n"
             "          break;\n"
             "        }\n"
             "        if (WC == '}') {  // Not sure if \\n should be gobbled for {this style\n"
             "          break; // but still looking.\n"
             "        }\n"
             "      }\n"
             "      continue;\n"
             "    }\n"
             "\n"
             "    else if (WC == '\\'') {\n"
             "      _source(PP++).ch = WC;\n"
             "      for (;;) {\n"
             "        WC = SYM(FP++).ch; CHECK_EOF(WC);\n"
             "        if (WC == '\\'') {\n"
             "          // peek ahead:\n"
             "          int Peek = SYM(FP).ch; CHECK_EOF(Peek);\n"
             "          if (Peek == '\\'') { // doubled 's\n"
             "            _source(PP++).ch = WC;\n"
             "            _source(PP++).ch = Peek;\n"
             "            FP++;\n"
             "          } else {\n"
             "            _source(PP).ch = WC;\n"
             "            _source(PP).end = SYM(FP-1).end; // Leave Peek for later.\n"
             "            PP++;\n"
             "            break;\n"
             "          }\n"
             "        } else {\n"
             "          _source(PP++).ch = WC;\n"
             "        }\n"
             "      }\n"
             "      continue;\n"
             "    }\n"
             "\n"
             "    else if (WC == '\"') { // TO DO: Update ' and \" items in imp77 as well\n"
             "      _source(PP++).ch = WC;\n"
             "      for (;;) {\n"
             "        WC = SYM(FP++).ch; CHECK_EOF(WC);\n"
             "        if (WC == '\"') {\n"
             "          // peek ahead:\n"
             "          int Peek = SYM(FP).ch; CHECK_EOF(Peek);\n"
             "          if (Peek == '\"') { // doubled \"s\n"
             "            _source(PP++).ch = WC;\n"
             "            _source(PP++).ch = Peek;\n"
             "            FP++;\n"
             "          } else {\n"
             "            _source(PP).ch = WC;\n"
             "            _source(PP).end = SYM(FP-1).end; // Leave Peek for later.\n"
             "            PP++;\n"
             "            break;\n"
             "          }\n"
             "        } else {\n"
             "          _source(PP++).ch = WC;\n"
             "        }\n"
             "      }\n"
             "      continue;\n"
             "    }\n"
             "\n"
             "    else if (WC == ' ' || WC == '\\t' || WC == '\\f') {  // use iswblank(WC) instead?\n"
             "\n"
             "      continue;\n"
             "    }\n"
             "\n"
             "\n"
             "\n"
             "\n"
             "    else {\n"
             "      // everything else just returns one significant non-space character. This includes '\\n'.\n"
             "\n"
             "      if ((WC == '\\n') && ((PP>1) && (source(PP-1).ch == 'c'))) {  // BEWARE WHEN CHANGING STROPPING ENCODING: Looking for a preceding '%C' ...\n"
             "        if (PP>0) _source(PP-1).ch = ' '; // remove the '%c'\n"
             "        _source(PP++).ch = ' '; // remove the newline\n"
             "\n"
             "        // This is the only place where we gobble spaces *after* a token rather than before.\n"
             "        // It may be cleaner to set a 'continuation' flag and gobble them before the next\n"
             "        // symbol fetch rather than do it here in a lookahead.  Esp. wrt to reconstituting source\n"
             "        // from the array for the listing file etc etc.\n"
             "        // BUT FOR NOW, %C IS HANDLED BY THS HACK:\n"
             "\n"
             "        int Lookahead = FP;\n"
             "        while (SYM(Lookahead).ch == '\\n' || SYM(Lookahead).ch == ' ' || SYM(Lookahead).ch == '\\t' || SYM(Lookahead).ch == '\\f') { // Use iswblank()?\n"
             "          // No worries about  '{...}' - this behaviour seems to be identical to Imp77's\n"
             "          _SYM(Lookahead).ch = ' ';   // gobble following newlines and whitespace before next significant character.\n"
             "          Lookahead++;\n"
             "        }\n"
             "        continue;\n"
             "      }\n"
             "\n"
             "      if (iswalpha(WC) && iswlower(WC)) {\n"
             "        WC = towupper(WC);  // ALSO TEMPORARY\n"
             "      }\n"
             "      _source(PP++).ch = WC;\n"
             "      continue;\n"
             "    }\n"
             "\n"
             "\n"
             "    // Still skipping whitespace ...\n"
             "\n"
             "  }\n"
             "\n"
             "  DONE();\n"
             "  P = 0;\n"
             "  while (source(P).ch != 0) {\n"
             "    if (debug_stropping) fprintf(stderr, \"%d: ch='%lc'  start=%d:end=%d\\n\", P, source(P).ch, source(P).start, source(P).end);\n"
             "    P++;\n"
             "  }\n"
             "\n"
             "#undef DONE\n"
             "#endif\n"
             "  return TRUE;\n",
  /*4*/   L"\n"
             "  // Noting that we have just seen a label at parse time allows us\n"
             "  // to handle an immediately-following comment differently, i.e.\n"
             "  // by avoiding the line reconstruction (if doing so on the fly)\n"
             "  // and thus preserving the text of the comment for output by a\n"
             "  // source-to-source translator.\n"
             "  //ColonFlag = 1; // Note that <COLON> occurs last in its list of alternatives so if it is\n"
             "                 // executed at all, the parse is going to be successful.\n"
             "                 // We should then reset ColonFlag at the point where it is tested (for the comments)\n"
             "  return TRUE;\n",
  /*5*/   L"\n"
             "  // We almost certainly need to handle include files at parse time (with a stack of\n"
             "  // input files, as I'm doing in takeon.c)\n"
             "  return TRUE;\n",
  /*6*/   L"\n"
             "  // listing control has to be done at parse time\n"
             "  // (unless there is a *major* restructuring)\n"
             "  return TRUE;\n",
  /*7*/   L"\n"
             "  return TRUE;\n",
};

parsefn parsetime[NUM_SEMANTIC_PHRASES] = {
  /*0*/   &parse_init,
  /*1*/   &parse_terminate,
  /*2*/   &parse_whitespace,
  /*3*/   &parse_Imp77_stropping,
  /*4*/   &parse_COLON,
  /*5*/   &parse_INCLUDE,
  /*6*/   &parse_LISTON,
  /*7*/   &parse_LISTOFF,
};

// Comments are stored so that they can be re-inserted, should
// we need to regenerate a grammar.g file from this header file.
const wchar_t *xcomment[NUM_PHRASES] = {
  /*  0*/   NULL,
  /*  1*/   NULL,
  /*  2*/   NULL,
  /*  3*/   NULL,
  /*  4*/   NULL,
  /*  5*/   NULL,
  /*  6*/   NULL,
  /*  7*/   NULL,
  /*  8*/   NULL,
  /*  9*/   NULL,
  /* 10*/   NULL,
  /* 11*/   NULL,
  /* 12*/   NULL,
  /* 13*/   NULL,
  /* 14*/   NULL,
  /* 15*/   NULL,
  /* 16*/   NULL,
  /* 17*/   NULL,
  /* 18*/   NULL,
  /* 19*/   NULL,
  /* 20*/   NULL,
  /* 21*/   NULL,
  /* 22*/   NULL,
  /* 23*/   NULL,
  /* 24*/   NULL,
  /* 25*/   NULL,
  /* 26*/   NULL,
  /* 27*/   NULL,
  /* 28*/   NULL,
  /* 29*/   NULL,
  /* 30*/   NULL,
  /* 31*/   NULL,
  /* 32*/   NULL,
  /* 33*/   NULL,
  /* 34*/   NULL,
  /* 35*/   NULL,
  /* 36*/   NULL,
  /* 37*/   NULL,
  /* 38*/   NULL,
  /* 39*/   NULL,
  /* 40*/   NULL,
  /* 41*/   NULL,
  /* 42*/   NULL,
  /* 43*/   NULL,
  /* 44*/   NULL,
  /* 45*/   NULL,
  /* 46*/   NULL,
  /* 47*/   NULL,
  /* 48*/   NULL,
  /* 49*/   NULL,
  /* 50*/   NULL,
  /* 51*/   NULL,
  /* 52*/   NULL,
  /* 53*/   NULL,
  /* 54*/   NULL,
  /* 55*/   NULL,
  /* 56*/   NULL,
  /* 57*/   NULL,
  /* 58*/   NULL,
  /* 59*/   NULL,
  /* 60*/   NULL,
  /* 61*/   NULL,
  /* 62*/   NULL,
  /* 63*/   NULL,
  /* 64*/   NULL,
  /* 65*/   NULL,
  /* 66*/   NULL,
  /* 67*/   NULL,
  /* 68*/   NULL,
  /* 69*/   NULL,
  /* 70*/   NULL,
  /* 71*/   NULL,
  /* 72*/   NULL,
  /* 73*/   NULL,
  /* 74*/   NULL,
  /* 75*/   NULL,
  /* 76*/   NULL,
  /* 77*/   NULL,
  /* 78*/   NULL,
  /* 79*/   NULL,
  /* 80*/   NULL,
  /* 81*/   NULL,
  /* 82*/   NULL,
  /* 83*/   NULL,
  /* 84*/   NULL,
  /* 85*/   NULL,
  /* 86*/   NULL,
  /* 87*/   NULL,
  /* 88*/   NULL,
  /* 89*/   NULL,
  /* 90*/   NULL,
  /* 91*/   NULL,
  /* 92*/   NULL,
  /* 93*/   NULL,
  /* 94*/   NULL,
  /* 95*/   NULL,
  /* 96*/   NULL,
  /* 97*/   NULL,
  /* 98*/   NULL,
  /* 99*/   NULL,
  /*100*/   NULL,
  /*101*/   NULL,
  /*102*/   NULL,
  /*103*/   NULL,
  /*104*/   NULL,
  /*105*/   NULL,
  /*106*/   NULL,
  /*107*/   NULL,
  /*108*/   NULL,
  /*109*/   NULL,
  /*110*/   NULL,
  /*111*/   NULL,
  /*112*/   NULL,
  /*113*/   NULL,
  /*114*/   NULL,
  /*115*/   NULL,
  /*116*/   NULL,
  /*117*/   NULL,
  /*118*/   NULL,
  /*119*/   NULL,
  /*120*/   NULL,
  /*121*/   NULL,
  /*122*/   NULL,
  /*123*/   NULL,
  /*124*/   NULL,
  /*125*/   NULL,
  /*126*/   NULL,
  /*127*/   NULL,
  /*128*/   NULL,
  /*129*/   NULL,
  /*130*/   NULL,
  /*131*/   NULL,
  /*132*/   NULL,
  /*133*/   NULL,
  /*134*/   NULL,
  /*135*/   NULL,
  /*136*/   NULL,
  /*137*/   NULL,
  /*138*/   NULL,
  /*139*/   NULL,
  /*140*/   NULL,
  /*141*/   NULL,
  /*142*/   NULL,
  /*143*/   NULL,
  /*144*/   NULL,
  /*145*/   NULL,
  /*146*/   NULL,
  /*147*/   NULL,
  /*148*/   NULL,
  /*149*/   NULL,
  /*150*/   NULL,
  /*151*/   NULL,
  /*152*/   NULL,
  /*153*/   NULL,
  /*154*/   NULL,
  /*155*/   NULL,
  /*156*/   NULL,
};
const wchar_t *ast_code[NUM_SIMPLE_PHRASES] = {
  /*XXCall_or_Assign_AUI*/   L"\n"
             "  {\n"
             "\n"
             "    int Ass = compile(P(4), depth+1); // P<Optional_Assignment> = <ASSOP><EXPR>, ''\n"
             "    \n"
             "    if (P_alt(Ass) == 0) { // Alt=0 ASSIGNMENT\n"
             "\n"
             "      // TO DO: under development\n"
             "      int LHS = compile(P(1), depth+1);\n"
             "      int VarIDX = P_P(LHS,1);\n"
             "      if (VarIDX == -1) {\n"
             "        fprintf(stderr, \"* NAME NOT SET: %s\\n\", SVTag); // exit(1);\n"
             "      }\n"
             "      int TypeIDX = VarDecl[VarIDX].type;\n"
             "\n"
             "      if (TypeDecl[TypeIDX].Proc == MAP) {\n"
             "        // If the LHS is a %map,\n"
             "        //   If <Opt_Record_Field> is present,\n"
             "        //     access the field via LHS(APP)->field\n"
             "        //   otherwise\n"
             "        //     Indirect through the LHS to assign the value, i.e.  *LHS(APP) = RHS\n"
             "        fprintf(stdout, \"/*LHS is %%map*/\");\n"
             "      } else if (TypeDecl[TypeIDX].IsArray == ARRAY) {\n"
             "        int IsName = TypeDecl[TypeIDX].NameInfo == ARRAYNAME;\n"
             "        int IsRecord = TypeDecl[TypeIDX].Basetype == RECORD;\n"
             "        // Similarly, if the LHS is an array:\n"
             "        //  If the LHS is a recordarray, then <Opt_Record_Field> may be applied.\n"
             "        //    (with \".\" vs \"->\" depending on %name)\n"
             "        //  otherwise\n"
             "        //    <Opt_Record_Field> must be empty\n"
             "        //    VARNAME(APP) is evaluated as an LHS destination.\n"
             "        //    If the LHS destination is a %name\n"
             "        //      If the assignment operator is '=='\n"
             "        //        then \"LHS = ...\"\n"
             "        //      otherwise\n"
             "        //        \"*LHS = ...\"\n"
             "        //    otherwise\n"
             "        //      \"LHS = ...\"\n"
             "        if (IsName && IsRecord) {\n"
             "          fprintf(stdout, \"/*LHS is %%recordname array*/\");\n"
             "        } else if (IsName) {\n"
             "          fprintf(stdout, \"/*LHS is some atom %%name array*/\");\n"
             "        } else if (IsRecord) {\n"
             "          fprintf(stdout, \"/*LHS is %%record array*/\");\n"
             "        } else {\n"
             "          //fprintf(stdout, \"/*LHS is some atom array*/\");\n"
             "          t[1] = VarIDX;\n"
             "          t[2] = -1; // DIM info for each dimension - for adjusting base offset when indexing. Not being used due to $define[][] macros.\n"
             "                     // We also want to know number of dims in order to check the number of indices given. Skipping for now.  TO DO.\n"
             "          t[3] = P(2); // <APP>\n"
             "          LHS = P_mktuple(AST_ARRAYACCESS, 0, 3, t); // Simple array access\n"
             "        }\n"
             "      } else if (/* IS <APP> PRESENT? */0) {\n"
             "        fprintf(stderr, \"* ERROR: %s(...) DOES NOT TAKE PARAMETERS?\\n\", SVTag);\n"
             "      }\n"
             "\n"
             "      // Now assign RHS to LHS:\n"
             "      \n"
             "      // Some of this code might want to be factored out to support P<VAR> which will\n"
             "      // duplicate much of what is being described here.\n"
             "\n"
             "      // Tests for invalid type combinations will be needed as well as type casts\n"
             "      // where allowed (and esp. for \"<-\" jam transfers)\n"
             "\n"
             "      // LHS = <VARNAME><APP><Opt_Record_Field>;\n"
             "      // Using the struct here would reduce the risk of putting a value in the wrong field!\n"
             "      t[1] = P_P(Ass,1); // ASSOP\n"
             "      t[2] = LHS;        // LHS\n"
             "      t[3] = P_P(Ass,2); // RHS\n"
             "      generate_c(P_mktuple(AST_ASSIGN, 0, 3, t), depth+1);\n"
             "      \n"
             "    } else { // Alt=1 PROCEDURE CALL\n"
             "\n"
             "      // simple procedure call.  This is probably the easiest one to implement so I'll\n"
             "      // tackle it first.  The only 'fancy' feature needed here is pairing off the\n"
             "      // actual parameters with the formal parameters, type checking them, casting\n"
             "      // if necessary, and causing an error if there are too many or too few actual\n"
             "      // parameters.\n"
             "      \n"
             "      // extern int handle_ast_phrase(int Ph, int depth);\n"
             "      // (void)handle_ast_phrase(compile(P(1), depth+1), depth+1); // <VARNAME> returns AST_RVALUE\n"
             "\n"
             "\n"
             "      int RValue = compile(P(1), depth+1); // A P_mktuple(AST_RVALUE, {VarIDX})\n"
             "      int VarIDX = P_P(RValue, 1);\n"
             "      int VTag = VarDecl[VarIDX].varname;\n"
             "      char *s = Tag2Str(VTag);\n"
             "      //fprintf(stderr, \"Debug VAR: VarIDX returned was %d for %s\\n\", VarIDX, s);\n"
             "      PushVar(RValue);\n"
             "      int TypeIDX = VarDecl[VarIDX].type;\n"
             "      //DebugVarIDX(VarIDX);\n"
             "\n"
             "      int param = TypeDecl[TypeIDX].parms;\n"
             "      if (param == -1) {\n"
             "        // fprintf(stderr, \"** NO PARAMETERS\\n\");\n"
             "      } else {\n"
             "        for (;;) {\n"
             "          // fprintf(stderr, \"** PARAMETER is %d\\n\", param);\n"
             "          param = TypeDecl[param].parms;\n"
             "          if (param == -1) break;\n"
             "        }\n"
             "      }\n"
             "\n"
             "      \n"
             "      // Now we have a linked list of parameters and P(2) which is P<APP> = '('<EXPR><RESTOFAPP>')', ''\n"
             "      //                                                      with P<RESTOFAPP> = ','<READLINEP><EXPR><RESTOFAPP>, ''\n"
             "      // so (TO DO) evaluate each parameter in turn, with <EXPR> in the context of the parameter type.\n"
             "\n"
             "#ifdef NEVER\n"
             "      fprintf(stdout, \"%s(\", s);\n"
             "      generate_c(compile(P(2), depth+1), depth+1);\n"
             "      fprintf(stdout, \")\");\n"
             "#else\n"
             "      t[1] = VarIDX;\n"
             "      t[2] = param;\n"
             "      t[3] = P(2);\n"
             "      int ProcCall = P_mktuple(AST_PROC_CALL, 0, 3, t);   // This could be preferred if it worked. Which at the moment it seems not to.\n"
             "      generate_c(ProcCall, depth+1);\n"
             "#endif\n"
             "    }\n"
             "    return -1;\n"
             "  }\n",
  /*PUSHDECS*/   L"\n"
             "  PushDecl(42);\n"
             "  PushDecl(Object);\n"
             "  PushDecl(Basetype);\n"
             "  PushDecl(Signedness);\n"
             "  PushDecl(Precision);\n"
             "  PushDecl(Proc);\n"
             "  PushDecl(NameInfo);\n"
             "  PushDecl(Spec);\n"
             "  PushDecl(IsArray);\n"
             "  PushDecl(Area);\n"
             "  PushDecl(Linkage);\n"
             "  return -1;\n",
  /*POPDECS*/   L"\n"
             "  Linkage = PopDecl();\n"
             "  Area = PopDecl();\n"
             "  IsArray = PopDecl();\n"
             "  Spec = PopDecl();\n"
             "  NameInfo = PopDecl();\n"
             "  Proc = PopDecl();\n"
             "  Precision = PopDecl();\n"
             "  Signedness = PopDecl();\n"
             "  Basetype = PopDecl();\n"
             "  Object = PopDecl();\n"
             "  {int check = PopDecl(); if (check != 42) fprintf(stderr, \"* Error: Unbalanced Decl stack\\n\"); }\n"
             "  return -1;\n",
  /*INITDECS*/   L"\n"
             "  Object     = UNINIT_OBJECT;\n"
             "  Basetype   = UNINIT_BASETYPE;\n"
             "  Signedness = UNINIT_SIGNEDNESS;\n"
             "  Precision  = UNINIT_PRECISION;\n"
             "  Proc       = UNINIT_PROC;\n"
             "  NameInfo   = NO_NAME;           // UNINIT_AN_N\n"
             "  //IsFormat   = NO_FORMAT;       // UNINIT_ISFORMAT\n"
             "  Spec       = NO_SPEC;           // UNINIT_SPEC\n"
             "  IsArray    = SCALAR;            // UNINIT_ISARRAY\n"
             "  // TO DO: Do I need an \"IS_INITIALISED\" tag as well?  So far, only reason for\n"
             "  //        having one would be to suppress the keyword \"extern\" in declarations\n"
             "  //        such as \"%externalinteger fred = 1\" which would otherwise be declared\n"
             "  //        in C as \"extern int fred = 1;\" rather than \"int fred = 1;\" (at least\n"
             "  //        if declared at the top level.  Placing that declaration within\n"
             "  //        a nested routine is a separate issue and may be a problem. Exbedding\n"
             "  //        that declaration to the top level may not be possible due to scoping rules.)\n"
             "  // NOTE: A data declaration (e.g. %integer I) at the top level of a file of externals\n"
             "  // or before the begin/endofprogram block is an error in Imp77 and I'm guessing in Imp80.\n"
             "  Area       = (ctrl_depth() == 0 ? EXTDATA : STACK);  // UNINIT_AREA\n"
             "  // However a %routine at the same level (as opposed to an %externalroutine) appears to be accepted.\n"
             "  Linkage    = UNINIT_LINKAGE;    // Ditto? Check with ERCC compiler. Or ask Bob.\n"
             "  return -1;\n",
  /*nls*/   L"",
  /*READLINEP*/   L"",
  /*S*/   L"\n"
             "  if (alt == 0) fprintf(stdout, \"\\n\"); \n",
  /*DOWN*/   L"\n"
             "  // unconditionally set in a %begin.  Could just put the 'push_scope_level()' in\n"
             "  // the code for <begin_block> but for now I'll follow the structure of the\n"
             "  // ERCC compilers and grammar.\n"
             "  push_scope_level();\n",
  /*UP*/   L"\n"
             "  // called on %end and %endofprogram\n"
             "  pop_scope_level();\n",
  /*SS*/   L"",
  /*BINOP*/   L"\n"
             "                     \n"
             "     // Phrase is used to convert an OP into a more useful AST phrase.\n"
             "     // (the default for char syms is separate P() items for each char, which is unweildy)\n"
             "\n"
             "     // It would be cleaner to return the OP_xxx enum rather than the string.\n"
             "     // I should do so later.  (The string is decoded in PushBinOp())\n"
             "     \n"
             "     if (alt == 0)               {  //\\\\    '+',\n"
             "       t[1] = wstrtopool(L\"+\");\n"
             "       t[2] = OP_ADD;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 1)        {  //\\\\    '-',\n"
             "       t[1] = wstrtopool(L\"-\");\n"
             "       t[2] = OP_SUB;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 2)        {  //\\\\    '&',\n"
             "       t[1] = wstrtopool(L\"&\");\n"
             "       t[2] = OP_AND;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 3)        {  //\\\\    '*' '*' '*' '*',\n"
             "       t[1] = wstrtopool(L\"****\");\n"
             "       t[2] = OP_IEXP;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "       \n"
             "     } else if (alt == 4)        {  //\\\\    '*' '*',\n"
             "       t[1] = wstrtopool(L\"**\");\n"
             "       t[2] = OP_REXP;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 5)        {  //\\\\    '*',\n"
             "       t[1] = wstrtopool(L\"*\");\n"
             "       t[2] = OP_MULT;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 6)        {  //\\\\    '!' '!',\n"
             "       t[1] = wstrtopool(L\"!!\");\n"
             "       t[2] = OP_EOR;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 7)        {  //\\\\    '!',\n"
             "       t[1] = wstrtopool(L\"!\");\n"
             "       t[2] = OP_OR;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 8)        {  //\\\\    '/' '/',\n"
             "       t[1] = wstrtopool(L\"//\");\n"
             "       t[2] = OP_INTDIV;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 9)        {  //\\\\    '/',\n"
             "       t[1] = wstrtopool(L\"/\");\n"
             "       t[2] = OP_REALDIV;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 10)        {  //\\\\    '>' '>',\n"
             "       t[1] = wstrtopool(L\">>\");\n"
             "       t[2] = OP_RSHIFT;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 11)        {  //\\\\    '<' '<',\n"
             "       t[1] = wstrtopool(L\"<<\");\n"
             "       t[2] = OP_LSHIFT;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 12)        {  //\\\\    '.',\n"
             "       t[1] = wstrtopool(L\".\");\n"
             "       t[2] = OP_CONCAT;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 13)        {  //\\\\    '\\' '\\',\n"
             "       t[1] = wstrtopool(L\"\\\\\\\\\");\n"
             "       t[2] = OP_IEXP;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 14)        {  //\\\\    '\\',\n"
             "       t[1] = wstrtopool(L\"\\\\\");\n"
             "       t[2] = OP_REXP;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else if (alt == 15)        {  //\\\\    '^' '^',\n"
             "       t[1] = wstrtopool(L\"^^\");                                    // NOTE: soap80 does not recognise ^^, only ****\n"
             "       t[2] = OP_IEXP;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     } else                      {  //\\\\    '^';\n"
             "       t[1] = wstrtopool(L\"^\");\n"
             "       t[2] = OP_REXP;\n"
             "       return t[0] = P_mktuple(AST_BINOP, alt, 2/*phrases*/, t);\n"
             "\n"
             "     }\n"
             "     return -1;\n",
  /*OP*/   L"\n"
             "    PushBinOp(compile(P(1), depth+1)); // TORP\n"
             "    return -1;\n",
  /*MONOP*/   L"\n"
             "     if (alt == 4) return -1;\n"
             "  \n"
             "     if (alt == 0)               {  //\\\\    '+',\n"
             "       // return -1; // simpler but generated C would not include the unary +\n"
             "       t[1] = wstrtopool(L\"+\");\n"
             "       t[2] = OP_POS;\n"
             "     } else if (alt == 1)        {  //\\\\    '-',\n"
             "       t[1] = wstrtopool(L\"-\");\n"
             "       t[2] = OP_NEG;\n"
             "     } else if (alt == 2)        {  //\\\\    '\\\\',\n"
             "       t[1] = wstrtopool(L\"\\\\\");\n"
             "       t[2] = OP_NOT;\n"
             "     } else if (alt == 3)        {  //\\\\    '~',\n"
             "       t[1] = wstrtopool(L\"~\");\n"
             "       t[2] = OP_NOT;\n"
             "     }\n"
             "     return t[0] = P_mktuple(AST_MONOP, alt, 2/*phrases*/, t);\n",
  /*UOP*/   L"\n"
             "  {\n"
             "     int Expr = compile(P(1), depth+1);\n"
             "     if (Expr != -1) PushMonOp(Expr); // TORP\n"
             "     return -1;\n"
             "  }\n",
  /*ASSOP*/   L"\n"
             "     if (alt == 0)               {\n"
             "       t[1] = wstrtopool(L\"==\");\n"
             "       t[2] = OP_ASSIGN_ADDR;\n"
             "     } else if (alt == 1)        {\n"
             "       t[1] = wstrtopool(L\"=\");\n"
             "       t[2] = OP_ASSIGN_VALUE;\n"
             "     } else if (alt == 2)        {\n"
             "       t[1] = wstrtopool(L\"<-\");\n"
             "       t[2] = OP_JAM_TRANSFER;\n"
             "     } else if (alt == 3)        {\n"
             "       t[1] = wstrtopool(L\"->\");\n"
             "       t[2] = OP_UNCOND_STR_RESOL;\n"
             "     }\n"
             "     return t[0] = P_mktuple(AST_ASSOP, alt, 1/*phrases*/, t);\n",
  /*COMP1*/   L"\n"
             "  {\n"
             "    // Some work required to distinguish address comparisons and conditional resolution from simple arithmetic comparisons or string comparisons\n"
             "    const char *C_Comp[] = { \"== &\", \">=\", \">\", \"!= &\", \"!=\", \"!=\", \"<=\", \"<\", \"*BADCOMP*\", \"==\", \"!=\", \"!= &\" };\n"
             "    fprintf(stdout, \" %s \", C_Comp[alt]);\n"
             "    return -1; // TO DO: return one of several possible AST_something tuples\n"
             "  }\n",
  /*COMP2*/   L"",
  /*VARNAME*/   L"\n"
             "  {\n"
             "  // We want to return an AST record with the VarDecl contents\n"
             "  // (which includes the TypeDecl information)\n"
             "  VTag = SubPhraseIdx(Ph, 2)&AST_idx_mask;\n"
             "  // Use the scope tools to find it.\n"
             "  if (SVTag != NULL) free(SVTag); // Sorry. Should use Stringpool.\n"
             "  int VarIDX = lookup(\"decl\", SVTag=Tag2Str(VTag));\n"
             "  t[1] = VarIDX;\n"
             "//fprintf(stderr, \"Debug VARNAME: VarIDX returned by looking up %s was %d\\n\", SVTag, VarIDX);\n"
             "  return t[0] = P_mktuple(AST_RVALUE, 0/*alt no*/, 1/*phrases*/, t);\n"
             "  }\n",
  /*NAME*/   L"\n"
             "  Tag = SubPhraseIdx(Ph, 2)&AST_idx_mask; // Set a global for use by <DECLARE>\n"
             "  return -1;\n",
  /*BigCharConst*/   L"",
  /*CharConst*/   L"",
  /*OptExponent*/   L"",
  /*OptDecimal*/   L"",
  /*LITCONST*/   L"\n",
  /*CONST*/   L"  // Pushes an AST_LITERAL:\n"
             "  // PushConst(compile(P(1), depth+1)); // more complex than that but this will do for basic testing during development.\n"
             "\n"
             "  // alt=0: symbolic constant\n"
             "  // alt=1: literal constant\n"
             "  t[1] = compile(P(1), depth+1);\n"
             "  PushConst(P_mktuple(AST_RVALUE, 1/*alt no*/, 1/*phrases*/, t));\n"
             "  \n"
             "  return -1;\n",
  /*N*/   L"",
  /*dq*/   L"",
  /*any*/   L"",
  /*stringchars*/   L"",
  /*ALIASTEXT*/   L"",
  /*semi*/   L"",
  /*Comment*/   L"\n"
             "  return -1; // suppressing extraneous data during development.  Will want it back later.\n",
  /*TEXT*/   L"",
  /*Opt_Record_Field*/   L"\n"
             "  // If APP is present then VARNAME must be an array.\n"
             "  // If it is a record array the Opt_Record_Field may be present,\n"
             "  // otherwise Opt_Record_Field must not be present.\n"
             "  // If APP is not present, then VARNAME can be any field in the parent record.\n"
             "  return -1;\n",
  /*VAR*/   L"\n"
             "  {\n"
             "#ifdef NEVER\n"
             "    // \n"
             "\n"
             "    int RValue = compile(P(1), depth+1); // A P_mktuple(AST_RVALUE, {VarIDX})\n"
             "    if (P_P(RValue,1) == -1) {\n"
             "      fprintf(stderr, \"* NAME NOT SET: %s\\n\", SVTag); // exit(1);\n"
             "    }\n"
             "    \n"
             "    //int VarIDX = P_P(RValue, 1);\n"
             "    //int VTag = VarDecl[VarIDX].varname;\n"
             "\n"
             "    PushVar(RValue);\n"
             "\n"
             "    //DebugVarIDX(VarIDX);\n"
             "\n"
             "    return -1;\n"
             "#else\n"
             "    int Var = Compile_Var(-1, P(1), P(2), P(3), depth+1);\n"
             "    PushVar(Var); // <VAR> is *only* used in context of an <EXPR> so needs TORP\n"
             "    return -1;\n"
             "#endif\n"
             "  }\n",
  /*OPERAND*/   L"\n"
             "\n"
             "  // shunting yard algorithm.  Note need to distinguish between the use of\n"
             "  // VAR and CONST in expressions (which are getting the shunting yard treatment)\n"
             "  // and many other places in the grammar, where they are not.\n"
             "\n"
             "  // NOTE: parentheses in Imp serve two purposes: 1) overriding the precedence of\n"
             "  // operators, and 2) forcing the order of evaluation specifically to avoid\n"
             "  // overflows in intermediate results.  So although we normally output expressions\n"
             "  // using minimal brackets and only insert them when needed due to differences\n"
             "  // between Imp and C precedences, we will leave user-supplied parentheses in place\n"
             "  // when outputting the C version of an expression to explicitly preserve option (2).\n"
             "\n"
             "  if (alt == 2) {  // '('<EXPR>')'\n"
             "    // compile the expr and reduce it to a single irreducible object so it is treated\n"
             "    // like a variable or a constant and its subexpressions are not examined when\n"
             "    // handling C's operator precedence.\n"
             "\n"
             "    // Compiling <EXPR> should return an AST_EXPRESSION\n"
             "\n"
             "    // a + (b + c) was coming out as (a + b + c) - the TORP was picking up\n"
             "    // the \"a +\" that was already on the stack and adding it to the Expr.  What\n"
             "    // was needed was to seal a false bottom on the stack so that Expr is\n"
             "    // constructed independent of anything preceding it. [*** FIXED ***]\n"
             "\n"
             "    t[1] = compile(P(2), depth+1);\n"
             "    int AstTuple = P_mktuple(AST_USER_PARENS, 0, 1, t);\n"
             "               \n"
             "    PushParen(L\"(\"); PushExpr(AstTuple); PushParen(L\")\"); // AstTuple is opaque to the RP code.  It treats it like any atom.\n"
             "    return -1;\n"
             "  }\n"
             "  // otherwise, compile <VAR> or <CONST>, which will push them on the TORP stack\n",
  /*CONSTVAR*/   L"\n"
             "  {\n"
             "  // alt=0: symbolic constant\n"
             "  // alt=1: literal constant\n"
             "//  t[1] = compile(P(1), depth+1);\n"
             "//  PushConst(P_mktuple(AST_RVALUE, 0/*alt no*/, 1/*phrases*/, t));\n"
             "\n"
             "  int ConstVar = compile(P(1), depth+1);\n"
             "  if (P_alt(ConstVar) == 0 && P_P(ConstVar,1) == -1) {\n"
             "    fprintf(stderr, \"* NAME NOT SET: %s\\n\", SVTag); // exit(1);\n"
             "  }\n"
             "\n"
             "  PushConst(ConstVar);\n"
             "  return -1;\n"
             "  }\n",
  /*COPERAND*/   L"",
  /*CEXPR*/   L"\n"
             "  {\n"
             "    // CODE BELOW same as following P<EXPR> but uncommented.\n"
             "    int Expr;\n"
             "    int SaveOperBottom = OperStack_bottom; OperStack_bottom = OperStack_nextfree;\n"
             "    int SaveDataBottom = DataStack_bottom; DataStack_bottom = DataStack_nextfree;\n"
             "    t[2] = compile(P(1), depth+1);\n"
             "    t[1] = ExPop();\n"
             "    DataStack_bottom = SaveDataBottom; OperStack_bottom = SaveOperBottom;\n"
             "\n"
             "    // TO DO: Modify the tuple below to mark it as evaluating to a constant\n"
             "    // compatible with contexts in C that require a constant expression:\n"
             "    // *OR* return AST_CONSTANT_EXPRESSION tuple? (which does not yet exist)\n"
             "    Expr = P_mktuple(AST_EXPRESSION, 0, 2, t); // converts to a single object\n"
             "\n"
             "    return Expr;\n"
             "  }\n"
             "\n",
  /*CTORP*/   L"",
  /*STAROREXPR*/   L"",
  /*TORP*/   L"",
  /*EXPR*/   L"\n"
             "  {\n"
             "    // CODE BELOW same as previous P<CEXPR> but commented.\n"
             "    int Expr;\n"
             "\n"
             "    // Previously I had many calls to <EXPR> duplicating the 'false bottom'\n"
             "    // code below, until I realised I could safely use it *everywhere* and\n"
             "    // therefore placed a single instance here instead.\n"
             "    \n"
             "    int SaveOperBottom = OperStack_bottom; OperStack_bottom = OperStack_nextfree;\n"
             "    int SaveDataBottom = DataStack_bottom; DataStack_bottom = DataStack_nextfree;\n"
             "    t[2] = compile(P(1), depth+1); // walk the CST expression tree to process each atom sequentially left to right, as input to the shunting yard algorithm\n"
             "    t[1] = ExPop();               // now convert the reverse-polish stack back into an AST tree, with precedence now magically applied.\n"
             "    DataStack_bottom = SaveDataBottom;\n"
             "    OperStack_bottom = SaveOperBottom;\n"
             "\n"
             "    Expr = P_mktuple(AST_EXPRESSION, 0, 2, t); // converts to a single object\n"
             "\n"
             "    // We do not print <EXPR>s immediately because a bracketed (<EXPR>) which is a subexpression of a larger <EXPR> has to be reprocessed\n"
             "    // in order to apply operator precedence.  A consequence of this is that <EXPR>s in other contexts will have to be output via generate_c()\n"
             "    // at the point of call.\n"
             "    \n"
             "    return Expr;\n"
             "  }\n",
  /*RESTOFEXPR*/   L"",
  /*RESTOFCEXPR*/   L"",
  /*APP*/   L"\n"
             "  if (alt == 0) {\n"
             "    int Expr = compile(P(2), depth+1);\n"
             "    // drop the '()' which is put back in by AST_PROC_CALL\n"
             "    generate_c(Expr, depth+1);\n"
             "    compile(P(3), depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*RESTOFAPP*/   L"\n"
             "  if (alt == 0) {\n"
             "    fprintf(stdout, \", \");\n"
             "    int Expr = compile(P(3), depth+1);\n"
             "    generate_c(Expr, depth+1);\n"
             "    compile(P(4), depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*PC_IU*/   L"\n"
             "  if (alt == 0) {\n"
             "    fprintf(stdout, \"if \");\n"
             "  } else {\n"
             "    fprintf(stdout, \"unless \");\n"
             "  }\n",
  /*TOP_LEVEL_CONDITION*/   L"\n"
             "  fprintf(stdout, \" (\");\n"
             "  compile(P(1), depth+1); compile(P(2), depth+1);\n"
             "  fprintf(stdout, \") \");\n"
             "  return -1;\n",
  /*CYCPARM*/   L"\n"
             "  // %for J = I, -1, 1\n"
             "  // for (J = I; J < 1; J += -1)\n"
             "  // if the step is positive use '<', if negative use '>', if unknown use '!='...\n"
             "  \n"
             "  fprintf(stdout, \"for (\");\n"
             "  int Control = compile(P(1), depth+1);\n"
             "  // TO DO: check type of Control and also that it is not a literal constant! (P_alt(Control) == ?)\n"
             "  if (P_P(Control,1) == -1) {\n"
             "    fprintf(stderr, \"* NAME NOT SET: %s\\n\", SVTag); // exit(1);\n"
             "  }\n"
             "  generate_c(Control, depth+1);\n"
             "\n"
             "  int Expr1 = compile(P(3), depth+1);\n"
             "  int Expr2 = compile(P(5), depth+1);\n"
             "  int Expr3 = compile(P(7), depth+1);\n"
             "\n"
             "  fprintf(stdout, \" = \");\n"
             "  generate_c(Expr1, depth+1);\n"
             "  fprintf(stdout, \"; \");\n"
             "  generate_c(compile(P(1), depth+1), depth+1);\n"
             "  fprintf(stdout, \" != \");\n"
             "  generate_c(Expr3, depth+1);\n"
             "  fprintf(stdout, \"; \");\n"
             "  generate_c(compile(P(1), depth+1), depth+1);\n"
             "  fprintf(stdout, \" += \");\n"
             "  generate_c(Expr2, depth+1);\n"
             "  fprintf(stdout, \") \");\n"
             "  return -1;\n",
  /*PC_WUF*/   L"\n"
             "  if (alt == 0) {\n"
             "    fprintf(stdout, \"while \"); compile(P(2), depth+1);\n"
             "  } else if (alt == 1) {\n"
             "    fprintf(stdout, \"/*TO DO*/until \"); compile(P(2), depth+1);\n"
             "  } else if (alt == 2) {\n"
             "    compile(P(2), depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*ALIAS*/   L"",
  /*DECLNAMES*/   L"\n"
             "  if (alt == 0) {\n"
             "    //fprintf(stdout, \", \");\n"
             "    compile(P(3), depth+1);\n"
             "    compile(P(4), depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*DECLNAME*/   L"",
  /*FULLTYPE*/   L"",
  /*BTYPE*/   L"\n"
             "  Basetype = (alt == 0 ? FLOAT : INTEGER);\n",
  /*XTYPE*/   L"\n"
             "  switch (alt) {\n"
             "  case 0: Signedness = SIGNED;   Precision = WORD;     Basetype = INTEGER;     break; // integer\n"
             "  case 1: Signedness = SIGNED;   Precision = WORD;     Basetype = FLOAT;       break; // real\n"
             "  case 2: Signedness = SIGNED;   Precision = QUADWORD;                         break; // long long (integer | real)\n"
             "  case 3: Signedness = SIGNED;   Precision = LONGWORD;                         break; // long (integer | real)\n"
             "  case 4: Signedness = SIGNED;   Precision = BYTE;     Basetype = INTEGER;     break; // byte (integer)?   (no %mite in this variant of Imp)\n"
             "  case 5: Signedness = SIGNED;   Precision = COMPOUND; Basetype = STRINGTYPE;  break; // string\n"
             "  case 6: Signedness = UNSIGNED; Precision = SHORT;    Basetype = INTEGER;     break; // half (integer)?\n"
             "  case 7: Signedness = SIGNED;   Precision = SHORT;    Basetype = INTEGER;     break; // short (integer)?\n"
             "  case 8: Signedness = SIGNED;   Precision = COMPOUND; Basetype = RECORD;      break; // record\n"
             "  }\n"
             "  if (debug_declarations > 1) fprintf(stderr, \"[ Sign=%d Prec=%d Type=%d ]\", Signedness, Precision, Basetype); \n",
  /*RT*/   L"\n"
             "  if (alt == 0) {\n"
             "    Proc = ROUTINE;\n"
             "    if (debug_declarations > 1) fprintf(stderr, \"[Proc=%d]\", Proc);\n"
             "  }\n",
  /*FM*/   L"\n"
             "  if (alt == 1) Proc = MAP; else Proc = FN;\n"
             "  if (debug_declarations > 1) fprintf(stderr, \"[Proc=%d]\", Proc);\n",
  /*FPDEL*/   L"\n"
             "  // Need to check I set up Object = here correctly.  Was a bit of a rush late one night.\n"
             "  Area = PARAMETER;\n"
             "  if (alt == 0) {\n"
             "    // <XTYPE><Opt_AN_N_type><DECLNAME><DECLNAMES>,\n"
             "    Object = VAR;\n"
             "    compile(P(1), depth+1); // <<XTYPE>\n"
             "    compile(P(2), depth+1); // <Opt_AN_N_type>\n"
             "    compile(P(3), depth+1); // <DECLNAME> \n"
             "    (void)Declaration(depth+1, FALSE);\n"
             "    {\n"
             "      int MoreDecls = P(4);  // ',' <READLINEP><DECLNAME> <DECLNAMES>, '' {\n"
             "      while (P_alt(MoreDecls) == 0) {\n"
             "        fprintf(stdout, \", /*a*/\");\n"
             "        compile(P_P(MoreDecls, 3), depth+1); // <DECLNAME>\n"
             "        (void)Declaration(depth+1, TRUE);\n"
             "        MoreDecls = P_P(MoreDecls, 4);\n"
             "      }\n"
             "    }\n"
             "    return -1;\n"
             "  } else if (alt == 1) {\n"
             "    // TO DO: Parameter list of a procedure parameter probably needs some more work\n"
             "    // <RT><Opt_N_type><DECLNAME><DECLNAMES><FPP>\n"
             "    Object = CODE; // TO DO: Or should this be VAR?  Not yet tested.\n"
             "    compile(P(1), depth+1); // <RT>\n"
             "    compile(P(2), depth+1); // <Opt_N_type>\n"
             "    compile(P(5), depth+1); // <FPP>           Reordered so FPP is handled before names\n"
             "    compile(P(3), depth+1); // <DECLNAME> \n"
             "    (void)Declaration(depth+1, FALSE);\n"
             "    {\n"
             "      int MoreDecls = P(4);  // ',' <READLINEP><DECLNAME> <DECLNAMES>, '' {\n"
             "      while (P_alt(MoreDecls) == 0) {\n"
             "        fprintf(stdout, \", /*b*/\");\n"
             "        compile(P_P(MoreDecls, 3), depth+1); // <DECLNAME>\n"
             "        (void)Declaration(depth+1, TRUE);\n"
             "        MoreDecls = P_P(MoreDecls, 4);\n"
             "      }\n"
             "    }\n"
             "    return -1;\n"
             "  } else if (alt == 2) {    // \"name\"<DECLNAME><DECLNAMES>\n"
             "    Object = VAR;\n"
             "    Basetype = GENERIC;\n"
             "    NameInfo = OBJECTNAME;\n"
             "    //IsFormat = UNINIT_ISFORMAT;\n"
             "    Spec = NO_SPEC;\n"
             "    //Signedness = UNINIT_SIGNEDNESS;\n"
             "    //Precision = UNINIT_PRECISION; // or maybe COMPOUND\n"
             "    //Proc = UNINIT_PROC;\n"
             "    //IsArray = UNINIT_ISARRAY;\n"
             "    //Linkage = UNINIT_LINKAGE;\n"
             "    compile(P(2), depth+1); // <DECLNAME>\n"
             "    (void)Declaration(depth+1, FALSE);\n"
             "    {\n"
             "      int MoreDecls = P(4);  // ',' <READLINEP><DECLNAME> <DECLNAMES>, '' {\n"
             "      while (P_alt(MoreDecls) == 0) {\n"
             "        fprintf(stdout, \", /*c*/\");\n"
             "        compile(P_P(MoreDecls, 3), depth+1); // <DECLNAME>\n"
             "        (void)Declaration(depth+1, TRUE);\n"
             "        MoreDecls = P_P(MoreDecls, 4);\n"
             "      }\n"
             "    }\n"
             "    return -1;\n"
             "  }\n",
  /*Opt_N_type*/   L"",
  /*Opt_AN_N_type*/   L"\n"
             "  switch (alt) {\n"
             "  case 0: NameInfo = ARRAYNAME;  break;\n"
             "  case 1: NameInfo = OBJECTNAME; break;\n"
             "  case 2: NameInfo = NO_NAME;     break;\n"
             "  }\n"
             "  if (debug_declarations > 1) fprintf(stderr, \"[NameInfo=%d]\", NameInfo);\n",
  /*FPP*/   L"\n"
             "  if (alt == 1) fprintf(stdout, \"void\"); // proc with no parameters\n"
             "  Area = PARAMETER;\n",
  /*Opt_comma*/   L"",
  /*RESTOFFPLIST*/   L"\n"
             "  if (alt == 0) fprintf(stdout, \", \");\n",
  /*ENDLIST*/   L"\n"
             "                      \n"
             "  // Need a routine to unwind the control stack and show what was expected.\n"
             "  \n"
             "  if (alt == 0) {\n"
             "    // end of program\n"
             "    if (ctrl_depth() != 1) {\n"
             "      fprintf(stderr, \"\\n* Spurious %%ENDOFPROGRAM\\n\"); exit(1);\n"
             "    }\n"
             "    int EXPECTED = pop_ctrl();\n"
             "    if (EXPECTED != ENDOFPROGRAM) {\n"
             "      fprintf(stderr, \"\\n* %%ENDOFPROGRAM not expected here (expecting %s)\\n\",\n"
             "             ctrl_debug[EXPECTED]); exit(1);\n"
             "    }\n"
             "    if (debug_compiler) fprintf(stderr, \"[end of program]\");\n"
             "    fprintf(stdout, \"\\n  exit(0);\\n} /* End of program */\\n\");\n"
             "  } else if (alt == 1) {\n"
             "    // end of perm\n"
             "    if (debug_compiler) fprintf(stderr, \"[end of perm]\");\n"
             "  } else if (alt == 2) {\n"
             "    // end of file\n"
             "    if (ctrl_depth() != 0) { // might not be the case for an unbalanced %include file...\n"
             "      fprintf(stderr, \"\\n* Spurious %%ENDOFFILE\\n\"); exit(1);\n"
             "    }\n"
             "    if (debug_compiler) fprintf(stderr, \"[end of file]\");\n"
             "  } else if (alt == 3) {\n"
             "    // end of list\n"
             "    if (debug_compiler) fprintf(stderr, \"[end of list]\");\n"
             "  } else if (alt == 4) {\n"
             "    // %end (begin or Rt/Fn/Map)\n"
             "    if (ctrl_depth() == 0) {\n"
             "      fprintf(stderr, \"\\n* Spurious %%END\\n\"); exit(1);\n"
             "    }\n"
             "    int EXPECTED = pop_ctrl();\n"
             "    if (EXPECTED != END) {\n"
             "      fprintf(stderr, \"\\n* %%END not expected here (expecting %s)\\n\",\n"
             "              ctrl_debug[EXPECTED]); exit(1);\n"
             "    }\n"
             "    if (debug_compiler) fprintf(stderr, \"[end of 'begin' block]\");\n"
             "    fprintf(stdout, \"\\n}; /* End of Rt/Fn/Map */\\n\");\n"
             "  }\n",
  /*ARRAYFORMAT*/   L"\n"
             "  if (alt == 0) Object = ARRAYFORMAT;\n"
             "  //IsFormat = (alt == 0 ? IS_FORMAT : NO_FORMAT );\n"
             "  //if (debug_declarations > 1) fprintf(stderr, \"[format=%d]\", IsFormat);\n",
  /*RESTOFSC*/   L"\n"
             "  return -1; // lt the parent level handle it.\n",
  /*SC*/   L" // %not is '!' in C\n"
             "  if (alt == 0) {\n"
             "    int Expr1 = compile(P(1), depth+1);\n"
             "    generate_c(Expr1, depth+1);          // TO DO: <EXPR>s need false bottom!\n"
             "    compile(P(2), depth+1);\n"
             "    int Expr2 = compile(P(3), depth+1);\n"
             "    generate_c(Expr2, depth+1);\n"
             "    int RestofSC = P(4);\n"
             "    if (P_alt(RestofSC) == 0) {\n"
             "      int Comp2 = P_P(RestofSC, 1);\n"
             "      int Expr3 = P_P(RestofSC, 2);\n"
             "      fprintf(stdout, \" && \");\n"
             "      generate_c(Expr2, depth+1);\n"
             "      compile(Comp2, depth+1);\n"
             "      Expr3 = compile(Expr3, depth+1);\n"
             "      generate_c(Expr3, depth+1);\n"
             "    }\n"
             "    compile(P(4), depth+1); // RESTOFSC\n"
             "  } else if (alt == 1) {\n"
             "    compile(P(2), depth+1); // SC\n"
             "    compile(P(3), depth+1); // RESTOFCOND\n"
             "  } else {                  // NOT SC\n"
             "    fprintf(stdout, \"!\");  // not sure about priorities for booleans\n"
             "    fprintf(stdout, \"(\");\n"
             "    compile(P(2), depth+1);\n"
             "    fprintf(stdout, \")\");\n"
             "  }\n"
             "  return -1;\n",
  /*RESTOFCOND*/   L"\n"
             "  // TO DO: Only one of them needs to have () added around the other, because the\n"
             "  //        operator precedences of && and || in C are not equal. (&& is higher than || so we need () around \"and\" SC's in a RESTOFORC.)\n"
             "  if (alt == 0) {\n"
             "    fprintf(stdout, \" && \");\n"
             "    compile(P(2), depth+1);\n"
             "  } else if (alt == 1) {\n"
             "    fprintf(stdout, \" || \");\n"
             "    compile(P(2), depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*RESTOFANDC*/   L"\n"
             "  if (alt == 0) {\n"
             "    fprintf(stdout, \" && \");\n"
             "    compile(P(2), depth+1);\n"
             "    compile(P(3), depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*RESTOFORC*/   L"\n"
             "  if (alt == 0) {\n"
             "    fprintf(stdout, \" || \");\n"
             "    compile(P(2), depth+1);     // NEED () AROUND THE <SC> IF IT CONTAINS AN \"&&\"\n"
             "    compile(P(3), depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*Optional_Assignment*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, (alt == 1 ? \"[procedure call]\" : \"[assignment]\"));\n",
  /*Opt_RtFnMapSpec*/   L"\n"
             "  if (alt == 0) {\n"
             "    Spec = SPEC;\n"
             "  } else if (alt == 1) {\n"
             "    // Procedures of all kinds require a %end\n"
             "    push_ctrl(END); // we will probably later distinguish between END and PROCEND etc.\n"
             "    Spec = NO_SPEC;\n"
             "  }\n"
             "  if (debug_declarations > 1) fprintf(stderr, \"[Spec=%d]\", Spec);\n",
  /*VSPECQ*/   L"\n"
             "  if (alt == 0) Spec = SPEC;\n"
             "  if (debug_declarations > 1) fprintf(stderr, \"[Spec=%d]\", Spec);\n",
  /*RESTOFBPLIST*/   L"\n"
             "  if (alt == 0) {\n"
             "  int LowIDX = compile(P(2), depth+1);\n"
             "  int HighIDX = compile(P(4), depth+1);\n"
             "  AddDims(LowIDX, HighIDX);\n"
             "  compile(P(5), depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*BPAIR*/   L"\n"
             "  {\n"
             "  // TO DO: list of upper/lower bounds\n"
             "  int LowIDX = compile(P(2), depth+1);\n"
             "  int HighIDX = compile(P(4), depth+1);\n"
             "  AddDims(LowIDX, HighIDX);\n"
             "  compile(P(5), depth+1);\n"
             "  // We now have ArrayDims of pairs of Low:High on the Dims stack, ready for Declaration(depth+1, ) to use.\n"
             "  }\n"
             "  return -1;\n",
  /*RESTOFARLIST*/   L"\n"
             "  if (alt == 0) compile(P(2), depth+1);\n"
             "  return -1;\n",
  /*ADECLN*/   L"\n"
             "    ArrayDims = 0; compile(P(3), depth+1); // <BPAIR>\n"
             "    compile(P(1), depth+1); // <DECLNAME>\n"
             "    (void)Declaration(depth+1, FALSE);\n"
             "    //fprintf(stdout, \";\\n\");\n"
             "    {\n"
             "      int MoreDecls = P(2);  // P<DECLNAMES> = ',' <READLINEP><DECLNAME> <DECLNAMES>, ''\n"
             "      while (P_alt(MoreDecls) == 0) {\n"
             "        //fprintf(stdout, \", /*e*/\");\n"
             "        compile(P_P(MoreDecls, 3), depth+1); // <DECLNAME>\n"
             "        (void)Declaration(depth+1, FALSE); // for now.  Syntax of multiples is complex.\n"
             "        //fprintf(stdout, \";\\n\");\n"
             "        MoreDecls = P_P(MoreDecls, 4); // <DECLNAMES>\n"
             "      }\n"
             "    }\n"
             "    // more array declarations on the same line are effectively independent in terms of bounds (but not type, area etc)\n"
             "    compile(P(4), depth+1);\n"
             "    return -1;\n",
  /*DECLN*/   L"\n"
             "  if (alt == 0) {\n"
             "    compile(P(1), depth+1);\n"
             "    compile(P(2), depth+1);\n"
             "    (void)Declaration(depth+1, FALSE);\n"
             "    {\n"
             "      int MoreDecls = P(3);  // ',' <READLINEP><DECLNAME> <DECLNAMES>, '' {\n"
             "      while (P_alt(MoreDecls) == 0) {\n"
             "        fprintf(stdout, \"; /*d*/\");\n"
             "        compile(P_P(MoreDecls, 3), depth+1); // <DECLNAME>\n"
             "        (void)Declaration(depth+1, TRUE);\n"
             "        MoreDecls = P_P(MoreDecls, 4);\n"
             "      }\n"
             "    }\n"
             "    fprintf(stdout, \";\\n\");\n"
             "    return -1;\n"
             "  } else if (alt == 1) {\n"
             "    IsArray = ARRAY;\n"
             "    compile(P(2), depth+1);\n"
             "    compile(P(3), depth+1);\n"
             "    return -1;\n"
             "  }\n",
  /*OWNDEC*/   L"\n"
             "  if (debug_declarations > 1) fprintf(stderr, \"[IsArray=%d]\", IsArray);\n"
             "  if (alt == 0) {\n"
             "    compile(P(1), depth+1); // <Opt_AN_N_type>\n"
             "    compile(P(2), depth+1); // <VSPECQ>\n"
             "    compile(P(3), depth+1); // <DECLNAME>\n"
             "    compile(P(4), depth+1); // <ALIAS>\n"
             "    compile(P(5), depth+1); // <Opt_Const_Init>\n"
             "    \n"
             "    (void)Declaration(depth+1, FALSE); fprintf(stdout, \";\\n\");\n"
             "    \n"
             "    compile(P(6), depth+1); // <RESTOFOWNDEC>\n"
             "  } else if (alt == 1) {\n"
             "    IsArray = ARRAY; // Must be set to SCALAR somewhere for default.\n"
             "    compile(P(2), depth+1); // <ARRAYFORMAT>\n"
             "    compile(P(3), depth+1); // <DECLNAME>\n"
             "    compile(P(4), depth+1); // <ALIAS>\n"
             "    ArrayDims = 0; compile(P(5), depth+1); // <BPAIR>\n"
             "    compile(P(6), depth+1); // <CONSTLIST>\n"
             "    (void)Declaration(depth+1, FALSE); fprintf(stdout, \";\\n\");\n"
             "  }\n",
  /*RESTOFOWNDEC*/   L"\n"
             "  if (alt == 0) {\n"
             "    // only for formatting... compile(P(2), depth+1); // <READLINEP>\n"
             "    compile(P(3), depth+1); // <DECLNAME>\n"
             "    compile(P(4), depth+1); // <ALIAS>\n"
             "    compile(P(5), depth+1); // <Opt_Const_Init>\n"
             "    (void)Declaration(depth+1, FALSE);\n"
             "    fprintf(stdout, \"; \");\n"
             "    \n"
             "    compile(P(6), depth+1); //<RESTOFOWNDEC>\n"
             "  } else if (alt == 1) {\n"
             "  }\n"
             "  return -1;\n",
  /*XOWN*/   L"\n"
             "  switch (alt) {\n"
             "  case 0: Area = OWN;                    break;\n"
             "  case 1: Area = EXTDATA;                break;\n"
             "  case 2: Area = EXTDATA;  Spec = SPEC;  break;\n"
             "  case 3: Area = CONSTANT;               break;\n"
             "  case 4: Area = CONSTANT;               break;\n"
             "  }\n"
             "  if (debug_declarations > 1) fprintf(stderr, \"[Area=%d]\", Area );\n",
  /*CONSTLIST*/   L"",
  /*ExPop*/   L"\n"
             "  (void)ExPop(); // quick hack because <EXPR> code was generating a *huge* stack, with each initialised array element being on the stack :-/\n",
  /*ROCL*/   L"",
  /*REPFACT*/   L"",
  /*RESTOFNLIST*/   L"",
  /*PC_EVENTQ*/   L"",
  /*Opt_EXPR*/   L"\n"
             "  if (alt == 0) {\n"
             "    fprintf(stdout, \", \");\n"
             "    generate_c(compile(P(2), depth+1), depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*RESTOFSWLIST*/   L"\n"
             "  if (alt == 0) {\n"
             "    compile(P(5), depth+1); // <EXPR> LOW\n"
             "    compile(P(7), depth+1); // <EXPR> HIGH\n"
             "    compile(P(2), depth+1); // <DECLNAME>\n"
             "    (void)Declaration(depth+1, FALSE);\n"
             "    {\n"
             "      int MoreDecls = P(3);  // ',' <READLINEP><DECLNAME> <DECLNAMES>, '' {\n"
             "      while (P_alt(MoreDecls) == 0) {\n"
             "        fprintf(stdout, \", /*f*/\");\n"
             "        compile(P_P(MoreDecls, 3), depth+1); // <DECLNAME>\n"
             "        (void)Declaration(depth+1, FALSE);\n"
             "        MoreDecls = P_P(MoreDecls, 4);\n"
             "      }\n"
             "    }\n"
             "\n"
             "    compile(P(9), depth+1); // <RESTOFSWLIST>\n"
             "  } else if (alt == 1) {\n"
             "  }\n"
             "  return -1;  \n",
  /*RESTOFREPEAT*/   L"\n"
             "  {\n"
             "  int EXPECTED = pop_ctrl();\n"
             "  if (EXPECTED != REPEAT && EXPECTED != REPEATUNTIL) {\n"
             "    fprintf(stderr, \"\\n* %%REPEAT not expected here (expecting %s)\\n\", ctrl_debug[EXPECTED]); exit(1);\n"
             "  }\n"
             "\n"
             "  if (EXPECTED == REPEATUNTIL) {\n"
             "    // if this was a %cycle ... %repeat with a possible %until after it, the\n"
             "    // %cycle could have been emitted as \"do {\" and this code could be either \") until (cond)\" or \"} while (1)\"\n"
             "    if (alt == 0) {\n"
             "      fprintf(stdout, \"} until \");\n"
             "      compile(P(2), depth+1);\n"
             "      fprintf(stdout, \";\");\n"
             "      if (debug_compiler) fprintf(stderr, \"[until condition]\");\n"
             "    } else if (alt == 1) {\n"
             "      fprintf(stdout, \"} while (1);\");\n"
             "    }\n"
             "  } else if (EXPECTED == REPEAT) {\n"
             "    if (alt == 0) {\n"
             "      fprintf(stderr, \"* %%UNTIL is not allowed at the end of this cycle.\\n\"); exit(1);\n"
             "    }\n"
             "    fprintf(stdout, \"}\"); // no semicolon\n"
             "  }\n"
             "  return -1;\n"
             "  }\n",
  /*FINISHELSEQ*/   L"\n"
             "  {\n"
             "    int EXPECTED = pop_ctrl();\n"
             "\n"
             "    if (alt == 0) {\n"
             "      fprintf(stdout, \" else \");\n"
             "      if (debug_compiler) fprintf(stderr, \"[FINISHELSEQ]\");\n"
             "    } else fprintf(stdout, \"\\n\"); // following a %finish\n"
             "  }\n"
             "  // recurse on AFTERELSE\n",
  /*AFTERELSE*/   L"\n"
             "  if (alt == 0) {\n"
             "    push_ctrl(FINISH);\n"
             "    fprintf(stdout, \"{\\n\");\n"
             "    if (debug_compiler) fprintf(stderr, \"[afterelse: start]\");\n"
             "    return -1;\n"
             "  } else if (alt == 1) {\n"
             "    //push_ctrl(FINISHELSE);\n"
             "    if (debug_compiler) fprintf(stderr, \"[afterelse: if or unless <COND> start]\");\n"
             "    compile(P(1), depth+1);\n"
             "    compile(P(2), depth+1);\n"
             "    compile(P(3), depth+1);\n"
             "    return -1;\n"
             "  } else {\n"
             "    if (debug_compiler) fprintf(stderr, \"[afterelse: <UI>]\");\n"
             "    // recurse\n"
             "  }\n"
             "  // recursively handle alt 2\n",
  /*ELSEQ*/   L"\n"
             "  if (alt == 0) {\n"
             "    fprintf(stdout, \" else \");\n"
             "    if (debug_compiler) fprintf(stderr, \"[ELSEQ]\");\n"
             "    // recurse\n"
             "  }\n",
  /*RESTOFIU*/   L"\n"
             "  if (alt < 2) {\n"
             "    push_ctrl(FINISHELSE);\n"
             "    fprintf(stdout, \" {\\n\");\n"
             "    if (debug_compiler) fprintf(stderr, \"[then start]\");\n"
             "    return -1;\n"
             "  } else {\n"
             "    if (debug_compiler) fprintf(stderr, \"[then UI]\");\n"
             "    // recursively handle the rest\n"
             "  }\n",
  /*Opt_Const_Init*/   L"",
  /*SEX*/   L"\n"
             "  Linkage = alt+1;\n"
             "  // %routine without one of the above is auto if nested but not sure what at external level if no %external keyword.\n"
             "  if (debug_declarations > 1) fprintf(stderr, \"[Linkage=%d]\", Linkage);\n",
  /*RFSTMNT*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[record format statement]\");\n",
  /*RFREF*/   L"",
  /*RESTOFRFDEC*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[more record format declarations]\");\n",
  /*RFDEC*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[record format declaration]\");\n",
  /*RFELMNT*/   L"\n"
             "  // a declaration of a record field - more restrictive in what it can be compared to regular declarations\n"
             "  if (debug_compiler) fprintf(stderr, \"[record format element]\");\n",
  /*ALTRFDEC*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[alternative record format declaration]\");\n",
  /*ASM*/   L"",
  /*Call_or_Assign_AUI*/   L"\n"
             "  // All other occurances of <VAR> are in the context of an <EXPR> which\n"
             "  // goes through the TORP process to handle operator priority, so the\n"
             "  // result of compiling a <VAR> is -1 with the return of the real result\n"
             "  // being postponed until an <EXPR> returns.\n"
             "  // This phrase here where <VAR> is used as an LHS or as a procedure call\n"
             "  // needs special handling.  This is why the two calls below take P(1)\n"
             "  // rather than compile(P(1))\n"
             "\n"
             "  //fprintf(stderr, \"P(1): \"); Diagnose(P(1));\n"
             "  //fprintf(stderr, \"Before compile(P(1)), DataStack_nextfree=%d\\n\", DataStack_nextfree);\n"
             "  compile(P(1), depth+1); // Pushes VAR\n"
             "  //fprintf(stderr, \"After compile(P(1)), DataStack_nextfree=%d\\n\", DataStack_nextfree);\n"
             "  Op_or_Data TOSPop = DataStack(--DataStack_nextfree); ; // NOT ExPop()\n"
             "  if (TOSPop.type != 'D') {\n"
             "    fprintf(stderr, \"** Internal error in %s at line %d\\n\", __FILE__, __LINE__); exit(1);\n"
             "  }\n"
             "  int Var = TOSPop.idx; // GETTING -1\n"
             "  //fprintf(stderr, \"Popped \"); Diagnose(Var);\n"
             "  if (alt == 0) {\n"
             "    int Assop = compile(P(2), depth+1);\n"
             "    int Expr = compile(P(3), depth+1);\n"
             "    int Assign = Mk_AST_assignment(Var, Assop, Expr, depth);\n"
             "    generate_c(Assign, depth+1);\n"
             "  } else {\n"
             "    int Call = Mk_AST_procedure_call(Var, depth);\n"
             "    generate_c(Call, depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*SWITCHIDX*/   L"\n"
             "  if (alt == 0) {\n"
             "    return compile(P(2), depth+1); // AST_EXPR tuple.\n"
             "  } else {\n"
             "    return -1;\n"
             "  }\n",
  /*Goto*/   L"  // CHANGED FROM <APP> TO NEW <SWITCHIDX> to restrict to *one* index.\n"
             "  if (debug_compiler) fprintf(stderr, \"[go to]\");\n"
             "  fprintf(stdout, \"goto \");\n"
             "  int SWIdx = compile(P(4), depth+1);\n"
             "  if (SWIdx != -1) {\n"
             "    // switch label destination\n"
             "    //generate_c(compile(P(3), depth+1), depth+1);\n"
             "    int SwitchName = compile(P(3), depth+1); // VARNAME\n"
             "    if (P_P(SwitchName,1) == -1) {\n"
             "      fprintf(stdout, \"* ERROR: %%switch %s NOT DECLARED\\n\", SVTag); // exit(1);\n"
             "    }\n"
             "    fprintf(stdout, \"%s\", SVTag);\n"
             "    fprintf(stdout, \"[\");\n"
             "    generate_c(SWIdx, depth+1);\n"
             "    fprintf(stdout, \"]\");\n"
             "  } else {\n"
             "    // plain goto\n"
             "    //generate_c(compile(P(3), depth+1), depth+1);\n"
             "    int Label = compile(P(3), depth+1);\n"
             "    if (P_P(Label,1) == -1) {\n"
             "      // Simple Label has not yet been defined.  Add it to the name table as a %spec so it can be faulted if missing at the end of the program.\n"
             "    }\n"
             "    fprintf(stdout, \"%s\", SVTag);\n"
             "  }\n"
             "  return -1;\n",
  /*return*/   L"\n"
             "  fprintf(stdout, \"return\");\n"
             "  if (debug_compiler) fprintf(stderr, \"[return]\");\n",
  /*result*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[result]\");\n"
             "\n"
             "  fprintf(stdout, \"return \");\n"
             "  // Assop will modify the result, possibly with a cast (for <-) or removing an indirection (for ==)\n"
             "\n"
             "  // TO DO: possibly needs a new AST_RESULT tuple similar to AST_ASSIGN\n"
             "\n"
             "  int Expr = compile(P(3), depth+1);\n"
             "  generate_c(Expr, depth+1);\n"
             "\n"
             "  return -1;\n",
  /*monitor_AUI*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[print diagnostics]\");\n"
             "  fprintf(stdout, \"assert(FALSE)\");\n"
             "  // drop through to handle <AUI> for now? NO! TO DO: Add return -1;\n",
  /*stop*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[stop program]\");\n"
             "  fprintf(stdout, \"exit(0)\");\n"
             "  return -1;\n",
  /*signal*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[signal event]\");\n"
             "  fprintf(stdout, \"_imp_signal(\");\n"
             "  compile(P(2), depth+1);\n"
             "  fprintf(stdout, \", \");\n"
             "  compile(P(3), depth+1);\n"
             "  if (0) { // if <OPXPR> is not the null alt\n"
             "    fprintf(stdout, \", \");\n"
             "    compile(P(4), depth+1);\n"
             "    fprintf(stdout, \")\");\n"
             "  }\n"
             "  return -1;\n",
  /*exit*/   L"\n"
             "  fprintf(stdout, \"break\");\n"
             "  if (debug_compiler) fprintf(stderr, \"[exit from cycle]\");\n",
  /*continue*/   L"\n"
             "  fprintf(stdout, \"continue\");\n"
             "  if (debug_compiler) fprintf(stderr, \"[continue at end of cycle]\");\n",
  /*Unconditional_Instructions*/   L"\n"
             "  if (alt == 0) {\n"
             "    compile(P(1), depth+1); // <UI> must be encapsulated in a {...} block if more that 1 statement\n"
             "    compile(P(2), depth+1);\n"
             "  } else if (alt == 1) { // PC_IU is just \"if\" or \"unless\"\n"
             "    compile(P(2), depth+1);\n"
             "    compile(P(3), depth+1);\n"
             "    compile(P(1), depth+1);\n"
             "    compile(P(4), depth+1);\n"
             "  } else if (alt == 2) { // but PC_WUF is a full while/until/for condition\n"
             "    compile(P(2), depth+1);\n"
             "    compile(P(1), depth+1);\n"
             "    compile(P(3), depth+1);\n"
             "  }\n"
             "  return -1;\n",
  /*UI*/   L"\n"
             "  if (alt == 0) {\n"
             "    compile(P(1), depth+1); fprintf(stdout, \"; \");\n"
             "    compile(P(2), depth+1);\n"
             "    return -1;\n"
             "  } else {\n"
             "    compile(P(1), depth+1);\n"
             "    fprintf(stdout, \"; \");\n"
             "  }\n"
             "  return -1;\n",
  /*AUI*/   L"\n",
  /*UI_BLOCK*/   L"\n"
             "  if (alt == 0) {\n"
             "    fprintf(stdout, \"{ \");\n"
             "    compile(P(1), depth+1); fprintf(stdout, \"; \");\n"
             "    compile(P(2), depth+1);\n"
             "    fprintf(stdout, \" }\");\n"
             "    return -1;\n"
             "  } else {\n"
             "    compile(P(1), depth+1); fprintf(stdout, \"; \");\n"
             "  }\n"
             "  return -1;\n",
  /*NONFINAL_UI*/   L"",
  /*FINAL_UI*/   L"",
  /*More_STATEMENTS*/   L"",
  /*STATEMENTS*/   L"",
  /*Labels*/   L"\n"
             "\n"
             "  // MAYBE USE <VARNAME> RATHER THAN <DECLNAME> and handle declaration here rather than in Declaration(depth+1, ) since labels\n"
             "  // need to be handled a bit differently from variables?  Yeah, making that change...\n"
             "  \n"
             "  if (debug_compiler || debug_declarations) fprintf(stderr, \"[label]\");\n"
             "  int LabelTag;\n"
             "  int SwitchName = compile(P(1), depth+1); LabelTag = VTag;\n"
             "  if (alt < 2 && P_P(SwitchName, 1) == -1) {\n"
             "    fprintf(stderr, \"* ERROR: %%switch %s NOT DECLARED\\n\", SVTag); // exit(1);\n"
             "  //} else if (alt < 2 && P_P(SwitchName, 1) != -1) {\n"
             "  //  fprintf(stderr, \"* ERROR: SWITCH LABEL %d SET TWICE\\n\", TO DO!); // exit(1);\n"
             "  } else if (alt == 2 && P_P(SwitchName, 1) != -1) {\n"
             "    fprintf(stderr, \"* ERROR: LABEL %s SET TWICE\\n\", SVTag); // exit(1);\n"
             "  }\n"
             "  if (alt == 0) {\n"
             "    Object = VAR; // SWITCHDEFN;  no, SWITCHDEFN is for %switch fred(1:10)\n"
             "    Basetype = SWITCHLABEL;\n"
             "    fprintf(stdout, \"%s_default:\", Tag2Str(LabelTag));\n"
             "  }  else if (alt == 1) {\n"
             "    Object = VAR; // SWITCHDEFN;\n"
             "    Basetype = SWITCHLABEL;\n"
             "    fprintf(stdout, \"%s_\", Tag2Str(LabelTag));\n"
             "    generate_c(compile(P(3), depth+1), depth+1); // NO: needs to be a decimal constant with special handling for negative numbers.\n"
             "    fprintf(stdout, \":\");\n"
             "  } else {\n"
             "    Object = VAR; // LABELDEFN; no, LABELDEFN is for %label Fred\n"
             "    Basetype = JUMPLABEL;\n"
             "    fprintf(stdout, \"%s: \", Tag2Str(LabelTag));  // TO DO: This outputs a ' ' after the tag.  We should suppress the space at the\n"
             "                                                 // point where it was added and add any needed spaces at the point of instantiation.\n"
             "  }\n"
             "  // PENDING! (TO DO) - the declaration code for actual labels (rather than declaration of labels) is currently\n"
             "  // non-existent and calling Declaration(depth+1, ) below outputs random crap.  I'm not 100% sure that I should even\n"
             "  // be using the 'Declaration(depth+1, )' method to handle the labels themselves.  Maybe it would be more sensible to\n"
             "  // put that code here in the grammar where the labels are instanced.\n"
             "  \n"
             "  // TO DO: (void)Declaration(depth+1, FALSE);\n"
             "  \n"
             "  return -1;\n"
             "\n",
  /*If_or_Unless*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[if or unless]\");\n",
  /*Opt_CYCPARM*/   L"\n"
             "  if (alt == 0) {\n"
             "    push_ctrl(REPEAT); // for loop\n"
             "    compile(P(1), depth+1);\n"
             "  } else if (alt == 1) {\n"
             "    push_ctrl(REPEATUNTIL); // plain %cycle\n"
             "    fprintf(stdout, \"do \");\n"
             "  }\n"
             "  return -1;\n",
  /*start_of_cycle*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[cycle]\");\n"
             "\n"
             "  if (alt == 0) {\n"
             "    compile(P(2), depth+1);  // if <Opt_CYCPARM> was empty, we should push_ctrl(REPEATUNTIL);, otherwise...\n"
             "  } else {\n"
             "    push_ctrl(REPEAT);       // %until not allowed after %repeat\n"
             "    compile(P(1), depth+1);\n"
             "  }\n"
             "  fprintf(stdout, \"{\\n\");\n"
             "  return -1;\n",
  /*end_of_cycle*/   L"\n"
             "  // <RESTOFREPEAT> handles the control stack and whether a %until is allowed\n"
             "  compile(P(2), depth+1);\n"
             "  compile(P(3), depth+1);\n"
             "  if (debug_compiler) fprintf(stderr, \"[repeat]\");\n"
             "  return -1;\n",
  /*regular_declaration*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[auto declaration]\");\n"
             "  compile(P(1), depth+1); Object = VAR;\n"
             "  compile(P(2), depth+1);\n"
             "  compile(P(3), depth+1);\n"
             "  compile(P(4), depth+1);\n"
             "  return -1;\n",
  /*proc_declaration*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[procedure declaration]\");\n"
             "\n"
             "  compile(P(1), depth+1);  Object = CODE;\n"
             "\n"
             "  compile(P(2), depth+1); // SEX\n"
             "  compile(P(3), depth+1); // RT\n"
             "  compile(P(4), depth+1); // Set up Spec and flag for <DOWN?>\n"
             "  compile(P(6), depth+1); // ALIAS\n"
             "  compile(P(5), depth+1); // DECLNAME reordered so name handled after params set up\n"
             "                          // (but work to be done to associate param list with Rt)\n"
             "\n"
             "  ParentVarIDX = Declaration(depth+1, FALSE); // BUT TO DO: NEEDS MORE WORK\n"
             "  ParentTypeIDX = VarDecl[ParentVarIDX].type;\n"
             "  \n"
             "  fprintf(stdout, \"(\");\n"
             "  push_scope_level(); // popped at end of param list if a spec, otherwise on %end of routine\n"
             "  compile(P(7), depth+1); // FPP (or void if none)\n"
             "  fprintf(stdout, \")\");\n"
             "  if (Spec == SPEC) {\n"
             "    pop_scope_level();\n"
             "    fprintf(stdout, \";\\n\");\n"
             "  } else {\n"
             "    // pop scope level on %end of procedure.\n"
             "    // Parameters are now declared as if within procedure body.\n"
             "    fprintf(stdout, \" {\\n\");\n"
             "  }\n"
             "  return -1;\n",
  /*own_or_external_declaration*/   L"\n"
             "  // if (debug_compiler) fprintf(stderr, \"[own/external/const declaration]\");\n"
             "\n"
             "  compile(P(1), depth+1);   Object = VAR;\n"
             "\n"
             "  compile(P(2), depth+1);\n"
             "  compile(P(3), depth+1);\n"
             "  compile(P(4), depth+1);\n"
             "  compile(P(5), depth+1);\n"
             "  return -1;\n",
  /*on_event_block*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[on event block]\");\n"
             "  fprintf(stdout, \"if (_imp_onevent(/*to do*/)) {\\n\");\n"
             "  push_ctrl(FINISH);\n",
  /*record_format_declaration*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[record format declaration]\");\n"
             "  //IsFormat = IS_FORMAT; // THIS APPEARS TO HAVE BE OVERRIDDEN BY THE TIME IT IS PRINTED.\n"
             "  Object = RECORDFORMAT;\n",
  /*various_ends*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[end of something]\");\n",
  /*include_file*/   L"\n"
             "  // TO DO: not handled in previous imptoc - it was assumed that incuded files could be translated separately\n"
             "  // but that is not correct.  Compilation of include files depends on what has gone before.  So they have to\n"
             "  // be translated in the context of the parent file, so as well as pushing the input file on the include stack,\n"
             "  // we have to switch output to the .h.tmp version of the .inc file, and switch back to the current context on EOF\n"
             "  // (the mechanics of handling include files was already worked out for takeon where .g files can contain I<...> )\n"
             "  // Note that include files will probably be handled like C and allow a search path via a -I option.\n"
             "  if (debug_compiler) fprintf(stderr, \"[push an include file]\");\n"
             "  fprintf(stdout, \"\\n#include \\\"...\\\"\\n\");\n",
  /*begin_block*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[begin block]\");\n"
             "  if (ctrl_depth() == 0) {\n"
             "    push_ctrl(ENDOFPROGRAM);\n"
             "    fprintf(stdout, \"\\n#include <imp_perms.h>\\nint main(int argc, char **argv) {\\n\");\n"
             "  } else {\n"
             "    push_ctrl(END);\n"
             "    fprintf(stdout, \"\\n{\\n\");\n"
             "  }\n",
  /*switch_declaration*/   L"\n"
             "  if (debug_declarations > 1) fprintf(stderr, \"[switch declaration]\");\n"
             "  // Will require *either* exbedded code at end of scope block with actual switch statement and gotos,\n"
             "  // *or* we have to backpatch this declaration with assignment of an array of labels (in the style &&labname)\n"
             "  // *or* we generate *all* labels at the point of declaration but output the unused ones at the end of\n"
             "  // the scope block with a jump to the default if given, or an error message if not. (i.e. the BADSWITCH()\n"
             "  // code from before)\n"
             "  // We do at a minimum require a hook between closing a scope and executing pending code.\n"
             "\n"
             "  compile(P(1), depth+1);   Object = SWITCHDEFN;\n"
             "\n"
             "  compile(P(6), depth+1); // Bounds pair LOW\n"
             "  compile(P(8), depth+1); //             HIGH\n"
             "  compile(P(3), depth+1); // NAME\n"
             "\n"
             "// TO DO:\n"
             "  (void)Declaration(depth+1, FALSE);\n"
             "\n"
             "  compile(P(4), depth+1); // NAMES\n"
             "  compile(P(10), depth+1); // RESTOFSWLIST\n"
             "  compile(P(11), depth+1); // S\n"
             "  return -1;\n",
  /*list_on*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[turn on listing]\");\n",
  /*else*/   L"\n"
             "  {\n"
             "    if (debug_compiler) fprintf(stderr, \"[(finish) else (start)]\");\n"
             "    int EXPECTED = pop_ctrl();\n"
             "    if (EXPECTED == ELSE || EXPECTED == FINISHELSE) {\n"
             "      push_ctrl(FINISH);\n"
             "      fprintf(stdout, \"} else {\");           // NOTE: a plain \"%else\" represents \"%finish %else %start\"\n"
             "    } else {\n"
             "      // TO DO:\n"
             "      \n"
             "      // And today's exercise is... try to remember how to extract the line/column from the \"else\" symbol\n"
             "      // to report the error better :-/\n"
             "      \n"
             "      fprintf(stderr, \"\\n* Spurious %%ELSE\\n\"); exit(1);\n"
             "    }\n"
             "  }\n",
  /*finish_opt_else*/   L"\n"
             "  {\n"
             "    if (ctrl_depth() == 0) {\n"
             "      fprintf(stderr, \"\\n* Spurious %%FINISH\\n\"); exit(1); // at least until we get around to handling ERCC conditional compilation tests\n"
             "    }\n"
             "    int EXPECTED = pop_ctrl();\n"
             "    fprintf(stdout, \"\\n}\");\n"
             "    if (EXPECTED == FINISH) {\n"
             "      push_ctrl(ELSE);\n"
             "    } else if (EXPECTED == FINISHELSE) {\n"
             "      push_ctrl(ELSE);\n"
             "    } else {\n"
             "      fprintf(stderr, \"\\n* %%FINISH not expected (expecting %s)\\n\", ctrl_debug[EXPECTED]); exit(1);\n"
             "    }\n"
             "    // recurse on FINISHELSEQ\n"
             "  }\n"
             "  if (debug_compiler) fprintf(stderr, \"[finish]\");\n",
  /*embedded_assembler*/   L"\n"
             "  fprintf(stdout, \"asm(/*to do*/)\");\n"
             "  if (debug_compiler) fprintf(stderr, \"[embedded assembly code]\");\n",
  /*trusted*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[trusted program pragma]\");\n",
  /*mainep*/   L"\n"
             "  if (debug_compiler) fprintf(stderr, \"[use this routine for main()]\");\n"
             "\n"
             "// TO DO: Declaration()\n"
             "\n",
  /*control*/   L"\n"
             "  // pragma?\n"
             "  if (debug_compiler) fprintf(stderr, \"[%%control - fine control over compiler options]\");\n",
  /*PSEMI*/   L" // print a semicolon after certain statements. This is for C's benefit.\n"
             "  fprintf(stdout, \"/*5*/; \");\n",
  /*STATEMENT*/   L"",
};

const wchar_t *keyword[NUM_KEYWORDS] = {
  /*  0*/   L"comment",
  /*  1*/   L"if",
  /*  2*/   L"unless",
  /*  3*/   L"while",
  /*  4*/   L"until",
  /*  5*/   L"for",
  /*  6*/   L"alias",
  /*  7*/   L"integer",
  /*  8*/   L"real",
  /*  9*/   L"long",
  /* 10*/   L"byte",
  /* 11*/   L"string",
  /* 12*/   L"half",
  /* 13*/   L"short",
  /* 14*/   L"record",
  /* 15*/   L"routine",
  /* 16*/   L"fn",
  /* 17*/   L"map",
  /* 18*/   L"function",
  /* 19*/   L"name",
  /* 20*/   L"array",
  /* 21*/   L"ofprogram",
  /* 22*/   L"ofperm",
  /* 23*/   L"offile",
  /* 24*/   L"oflist",
  /* 25*/   L"format",
  /* 26*/   L"not",
  /* 27*/   L"and",
  /* 28*/   L"or",
  /* 29*/   L"spec",
  /* 30*/   L"own",
  /* 31*/   L"external",
  /* 32*/   L"extrinsic",
  /* 33*/   L"constant",
  /* 34*/   L"const",
  /* 35*/   L"event",
  /* 36*/   L"else",
  /* 37*/   L"start",
  /* 38*/   L"then",
  /* 39*/   L"system",
  /* 40*/   L"dynamic",
  /* 41*/   L"prim",
  /* 42*/   L"perm",
  /* 43*/   L"return",
  /* 44*/   L"result",
  /* 45*/   L"monitor",
  /* 46*/   L"stop",
  /* 47*/   L"signal",
  /* 48*/   L"exit",
  /* 49*/   L"continue",
  /* 50*/   L"cycle",
  /* 51*/   L"repeat",
  /* 52*/   L"on",
  /* 53*/   L"end",
  /* 54*/   L"include",
  /* 55*/   L"begin",
  /* 56*/   L"switch",
  /* 57*/   L"list",
  /* 58*/   L"finish",
  /* 59*/   L"trustedprogram",
  /* 60*/   L"mainep",
  /* 61*/   L"control",
};
const wchar_t *regexps[NUM_REGEXPS] = {
  /*0*/   L"^[A-Z][A-Z0-9]*",
  /*1*/   L"^'([^\']|'')*'",
  /*2*/   L"^''''",
  /*3*/   L"^''",
  /*4*/   L"^'.'",
  /*5*/   L"^[MBKXRH]",
  /*6*/   L"^[0-9][0-9]*",
  /*7*/   L"^.",
};
const int gram[NUM_GRAMMAR /* 1076 */] = {

// P<XXCall_or_Assign_AUI> = ...;
  /*  0*/ COUNT_OF_ALTS    | 0x000001,
  /*  1*/ COUNT_OF_PHRASES | 0x000004,
  /*  2*/ PHRASE_TYPE      | G_VARNAME,
  /*  3*/ PHRASE_TYPE      | G_APP,
  /*  4*/ PHRASE_TYPE      | G_Opt_Record_Field,
  /*  5*/ PHRASE_TYPE      | G_Optional_Assignment,

// P<PUSHDECS> = ...;
  /*  6*/ COUNT_OF_ALTS    | 0x000001,
  /*  7*/ COUNT_OF_PHRASES | 0x000001,
  /*  8*/ PHRASE_TYPE      | G_INITDECS,

// P<POPDECS> = ...;
  /*  9*/ COUNT_OF_ALTS    | 0x000001,
  /* 10*/ COUNT_OF_PHRASES | 0x000000,

// P<INITDECS> = ...;
  /* 11*/ COUNT_OF_ALTS    | 0x000001,
  /* 12*/ COUNT_OF_PHRASES | 0x000000,

// P<nls> = ...;
  /* 13*/ COUNT_OF_ALTS    | 0x000002,
  /* 14*/ COUNT_OF_PHRASES | 0x000002,
  /* 15*/ BIP_TYPE         | B_nl,
  /* 16*/ PHRASE_TYPE      | G_nls,
  /* 17*/ COUNT_OF_PHRASES | 0x000000,

// P<READLINEP> = ...;
  /* 18*/ COUNT_OF_ALTS    | 0x000002,
  /* 19*/ COUNT_OF_PHRASES | 0x000001,
  /* 20*/ PHRASE_TYPE      | G_nls,
  /* 21*/ COUNT_OF_PHRASES | 0x000000,

// P<S> = ...;
  /* 22*/ COUNT_OF_ALTS    | 0x000002,
  /* 23*/ COUNT_OF_PHRASES | 0x000001,
  /* 24*/ BIP_TYPE         | B_nl,
  /* 25*/ COUNT_OF_PHRASES | 0x000001,
  /* 26*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003b,  /* ';' */

// P<DOWN> = ...;
  /* 27*/ COUNT_OF_ALTS    | 0x000001,
  /* 28*/ COUNT_OF_PHRASES | 0x000000,

// P<UP> = ...;
  /* 29*/ COUNT_OF_ALTS    | 0x000001,
  /* 30*/ COUNT_OF_PHRASES | 0x000000,

// P<SS> = ...;
  /* 31*/ COUNT_OF_ALTS    | 0x000001,
  /* 32*/ COUNT_OF_PHRASES | 0x000004,
  /* 33*/ SEMANTIC_TYPE    | S_init,
  /* 34*/ SEMANTIC_TYPE    | S_Imp77_stropping,
  /* 35*/ PHRASE_TYPE      | G_STATEMENTS,
  /* 36*/ SEMANTIC_TYPE    | S_terminate,

// P<BINOP> = ...;
  /* 37*/ COUNT_OF_ALTS    | 0x000011,
  /* 38*/ COUNT_OF_PHRASES | 0x000001,
  /* 39*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002b,  /* '+' */
  /* 40*/ COUNT_OF_PHRASES | 0x000001,
  /* 41*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002d,  /* '-' */
  /* 42*/ COUNT_OF_PHRASES | 0x000001,
  /* 43*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000026,  /* '&' */
  /* 44*/ COUNT_OF_PHRASES | 0x000004,
  /* 45*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002a,  /* '*' */
  /* 46*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002a,  /* '*' */
  /* 47*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002a,  /* '*' */
  /* 48*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002a,  /* '*' */
  /* 49*/ COUNT_OF_PHRASES | 0x000002,
  /* 50*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002a,  /* '*' */
  /* 51*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002a,  /* '*' */
  /* 52*/ COUNT_OF_PHRASES | 0x000001,
  /* 53*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002a,  /* '*' */
  /* 54*/ COUNT_OF_PHRASES | 0x000002,
  /* 55*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000021,  /* '!' */
  /* 56*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000021,  /* '!' */
  /* 57*/ COUNT_OF_PHRASES | 0x000001,
  /* 58*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000021,  /* '!' */
  /* 59*/ COUNT_OF_PHRASES | 0x000002,
  /* 60*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002f,  /* '/' */
  /* 61*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002f,  /* '/' */
  /* 62*/ COUNT_OF_PHRASES | 0x000001,
  /* 63*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002f,  /* '/' */
  /* 64*/ COUNT_OF_PHRASES | 0x000002,
  /* 65*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003e,  /* '>' */
  /* 66*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003e,  /* '>' */
  /* 67*/ COUNT_OF_PHRASES | 0x000002,
  /* 68*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003c,  /* '<' */
  /* 69*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003c,  /* '<' */
  /* 70*/ COUNT_OF_PHRASES | 0x000001,
  /* 71*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002e,  /* '.' */
  /* 72*/ COUNT_OF_PHRASES | 0x000002,
  /* 73*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00005c,  /* '\' */
  /* 74*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00005c,  /* '\' */
  /* 75*/ COUNT_OF_PHRASES | 0x000001,
  /* 76*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00005c,  /* '\' */
  /* 77*/ COUNT_OF_PHRASES | 0x000002,
  /* 78*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00005e,  /* '^' */
  /* 79*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00005e,  /* '^' */
  /* 80*/ COUNT_OF_PHRASES | 0x000001,
  /* 81*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00005e,  /* '^' */

// P<OP> = ...;
  /* 82*/ COUNT_OF_ALTS    | 0x000001,
  /* 83*/ COUNT_OF_PHRASES | 0x000001,
  /* 84*/ PHRASE_TYPE      | G_BINOP,

// P<MONOP> = ...;
  /* 85*/ COUNT_OF_ALTS    | 0x000005,
  /* 86*/ COUNT_OF_PHRASES | 0x000001,
  /* 87*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002b,  /* '+' */
  /* 88*/ COUNT_OF_PHRASES | 0x000001,
  /* 89*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002d,  /* '-' */
  /* 90*/ COUNT_OF_PHRASES | 0x000001,
  /* 91*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00005c,  /* '\' */
  /* 92*/ COUNT_OF_PHRASES | 0x000001,
  /* 93*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00007e,  /* '~' */
  /* 94*/ COUNT_OF_PHRASES | 0x000000,

// P<UOP> = ...;
  /* 95*/ COUNT_OF_ALTS    | 0x000001,
  /* 96*/ COUNT_OF_PHRASES | 0x000001,
  /* 97*/ PHRASE_TYPE      | G_MONOP,

// P<ASSOP> = ...;
  /* 98*/ COUNT_OF_ALTS    | 0x000004,
  /* 99*/ COUNT_OF_PHRASES | 0x000002,
  /*100*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*101*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*102*/ COUNT_OF_PHRASES | 0x000001,
  /*103*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*104*/ COUNT_OF_PHRASES | 0x000002,
  /*105*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003c,  /* '<' */
  /*106*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002d,  /* '-' */
  /*107*/ COUNT_OF_PHRASES | 0x000002,
  /*108*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002d,  /* '-' */
  /*109*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003e,  /* '>' */

// P<COMP1> = ...;
  /*110*/ COUNT_OF_ALTS    | 0x00000c,
  /*111*/ COUNT_OF_PHRASES | 0x000002,
  /*112*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*113*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*114*/ COUNT_OF_PHRASES | 0x000002,
  /*115*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003e,  /* '>' */
  /*116*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*117*/ COUNT_OF_PHRASES | 0x000001,
  /*118*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003e,  /* '>' */
  /*119*/ COUNT_OF_PHRASES | 0x000002,
  /*120*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000023,  /* '#' */
  /*121*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000023,  /* '#' */
  /*122*/ COUNT_OF_PHRASES | 0x000002,
  /*123*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00005c,  /* '\' */
  /*124*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*125*/ COUNT_OF_PHRASES | 0x000002,
  /*126*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003c,  /* '<' */
  /*127*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003e,  /* '>' */
  /*128*/ COUNT_OF_PHRASES | 0x000002,
  /*129*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003c,  /* '<' */
  /*130*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*131*/ COUNT_OF_PHRASES | 0x000001,
  /*132*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003c,  /* '<' */
  /*133*/ COUNT_OF_PHRASES | 0x000002,
  /*134*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002d,  /* '-' */
  /*135*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003e,  /* '>' */
  /*136*/ COUNT_OF_PHRASES | 0x000001,
  /*137*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*138*/ COUNT_OF_PHRASES | 0x000001,
  /*139*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000023,  /* '#' */
  /*140*/ COUNT_OF_PHRASES | 0x000003,
  /*141*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00005c,  /* '\' */
  /*142*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*143*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */

// P<COMP2> = ...;
  /*144*/ COUNT_OF_ALTS    | 0x000001,
  /*145*/ COUNT_OF_PHRASES | 0x000001,
  /*146*/ PHRASE_TYPE      | G_COMP1,

// P<VARNAME> = ...;
  /*147*/ COUNT_OF_ALTS    | 0x000001,
  /*148*/ COUNT_OF_PHRASES | 0x000002,
  /*149*/ PHRASE_TYPE      | NEGATED_PHRASE     | G_CONST,
  /*150*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000000,  /* ^[A-Z][A-Z0-9]* */

// P<NAME> = ...;
  /*151*/ COUNT_OF_ALTS    | 0x000001,
  /*152*/ COUNT_OF_PHRASES | 0x000002,
  /*153*/ PHRASE_TYPE      | NEGATED_PHRASE     | G_CONST,
  /*154*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000000,  /* ^[A-Z][A-Z0-9]* */

// P<BigCharConst> = ...;
  /*155*/ COUNT_OF_ALTS    | 0x000001,
  /*156*/ COUNT_OF_PHRASES | 0x000001,
  /*157*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000001,  /* ^'([^\']|'')*' */

// P<CharConst> = ...;
  /*158*/ COUNT_OF_ALTS    | 0x000003,
  /*159*/ COUNT_OF_PHRASES | 0x000001,
  /*160*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000002,  /* ^'''' */
  /*161*/ COUNT_OF_PHRASES | 0x000001,
  /*162*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000003,  /* ^'' */
  /*163*/ COUNT_OF_PHRASES | 0x000001,
  /*164*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000004,  /* ^'.' */

// P<OptExponent> = ...;
  /*165*/ COUNT_OF_ALTS    | 0x000002,
  /*166*/ COUNT_OF_PHRASES | 0x000002,
  /*167*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000040,  /* '@' */
  /*168*/ PHRASE_TYPE      | G_N,
  /*169*/ COUNT_OF_PHRASES | 0x000000,

// P<OptDecimal> = ...;
  /*170*/ COUNT_OF_ALTS    | 0x000002,
  /*171*/ COUNT_OF_PHRASES | 0x000002,
  /*172*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002e,  /* '.' */
  /*173*/ PHRASE_TYPE      | G_N,
  /*174*/ COUNT_OF_PHRASES | 0x000000,

// P<LITCONST> = ...;
  /*175*/ COUNT_OF_ALTS    | 0x000005,
  /*176*/ COUNT_OF_PHRASES | 0x000003,
  /*177*/ PHRASE_TYPE      | G_N,
  /*178*/ PHRASE_TYPE      | G_OptDecimal,
  /*179*/ PHRASE_TYPE      | G_OptExponent,
  /*180*/ COUNT_OF_PHRASES | 0x000001,
  /*181*/ PHRASE_TYPE      | G_CharConst,
  /*182*/ COUNT_OF_PHRASES | 0x000001,
  /*183*/ PHRASE_TYPE      | G_ALIASTEXT,
  /*184*/ COUNT_OF_PHRASES | 0x000002,
  /*185*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000045,  /* 'E' */
  /*186*/ PHRASE_TYPE      | G_ALIASTEXT,
  /*187*/ COUNT_OF_PHRASES | 0x000002,
  /*188*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000005,  /* ^[MBKXRH] */
  /*189*/ PHRASE_TYPE      | G_BigCharConst,

// P<CONST> = ...;
  /*190*/ COUNT_OF_ALTS    | 0x000001,
  /*191*/ COUNT_OF_PHRASES | 0x000001,
  /*192*/ PHRASE_TYPE      | G_LITCONST,

// P<N> = ...;
  /*193*/ COUNT_OF_ALTS    | 0x000001,
  /*194*/ COUNT_OF_PHRASES | 0x000001,
  /*195*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000006,  /* ^[0-9][0-9]* */

// P<dq> = ...;
  /*196*/ COUNT_OF_ALTS    | 0x000001,
  /*197*/ COUNT_OF_PHRASES | 0x000001,
  /*198*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000022,  /* '"' */

// P<any> = ...;
  /*199*/ COUNT_OF_ALTS    | 0x000001,
  /*200*/ COUNT_OF_PHRASES | 0x000001,
  /*201*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000007,  /* ^. */

// P<stringchars> = ...;
  /*202*/ COUNT_OF_ALTS    | 0x000003,
  /*203*/ COUNT_OF_PHRASES | 0x000003,
  /*204*/ PHRASE_TYPE      | G_dq,
  /*205*/ PHRASE_TYPE      | G_dq,
  /*206*/ PHRASE_TYPE      | G_stringchars,
  /*207*/ COUNT_OF_PHRASES | 0x000003,
  /*208*/ PHRASE_TYPE      | NEGATED_PHRASE     | G_dq,
  /*209*/ PHRASE_TYPE      | G_any,
  /*210*/ PHRASE_TYPE      | G_stringchars,
  /*211*/ COUNT_OF_PHRASES | 0x000000,

// P<ALIASTEXT> = ...;
  /*212*/ COUNT_OF_ALTS    | 0x000001,
  /*213*/ COUNT_OF_PHRASES | 0x000003,
  /*214*/ PHRASE_TYPE      | G_dq,
  /*215*/ PHRASE_TYPE      | G_stringchars,
  /*216*/ PHRASE_TYPE      | G_dq,

// P<semi> = ...;
  /*217*/ COUNT_OF_ALTS    | 0x000001,
  /*218*/ COUNT_OF_PHRASES | 0x000001,
  /*219*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003b,  /* ';' */

// P<Comment> = ...;
  /*220*/ COUNT_OF_ALTS    | 0x000003,
  /*221*/ COUNT_OF_PHRASES | 0x000002,
  /*222*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000021,  /* '!' */
  /*223*/ PHRASE_TYPE      | G_TEXT,
  /*224*/ COUNT_OF_PHRASES | 0x000002,
  /*225*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00007c,  /* '|' */
  /*226*/ PHRASE_TYPE      | G_TEXT,
  /*227*/ COUNT_OF_PHRASES | 0x000002,
  /*228*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000000,  /* comment */
  /*229*/ PHRASE_TYPE      | G_TEXT,

// P<TEXT> = ...;
  /*230*/ COUNT_OF_ALTS    | 0x000002,
  /*231*/ COUNT_OF_PHRASES | 0x000003,
  /*232*/ PHRASE_TYPE      | NEGATED_PHRASE     | G_S,
  /*233*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000007,  /* ^. */
  /*234*/ PHRASE_TYPE      | G_TEXT,
  /*235*/ COUNT_OF_PHRASES | 0x000000,

// P<Opt_Record_Field> = ...;
  /*236*/ COUNT_OF_ALTS    | 0x000002,
  /*237*/ COUNT_OF_PHRASES | 0x000004,
  /*238*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00005f,  /* '_' */
  /*239*/ PHRASE_TYPE      | G_VARNAME,
  /*240*/ PHRASE_TYPE      | G_APP,
  /*241*/ PHRASE_TYPE      | G_Opt_Record_Field,
  /*242*/ COUNT_OF_PHRASES | 0x000000,

// P<VAR> = ...;
  /*243*/ COUNT_OF_ALTS    | 0x000001,
  /*244*/ COUNT_OF_PHRASES | 0x000003,
  /*245*/ PHRASE_TYPE      | G_VARNAME,
  /*246*/ PHRASE_TYPE      | G_APP,
  /*247*/ PHRASE_TYPE      | G_Opt_Record_Field,

// P<OPERAND> = ...;
  /*248*/ COUNT_OF_ALTS    | 0x000003,
  /*249*/ COUNT_OF_PHRASES | 0x000001,
  /*250*/ PHRASE_TYPE      | G_VAR,
  /*251*/ COUNT_OF_PHRASES | 0x000001,
  /*252*/ PHRASE_TYPE      | G_CONST,
  /*253*/ COUNT_OF_PHRASES | 0x000003,
  /*254*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*255*/ PHRASE_TYPE      | G_EXPR,
  /*256*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */

// P<CONSTVAR> = ...;
  /*257*/ COUNT_OF_ALTS    | 0x000001,
  /*258*/ COUNT_OF_PHRASES | 0x000001,
  /*259*/ PHRASE_TYPE      | G_VARNAME,

// P<COPERAND> = ...;
  /*260*/ COUNT_OF_ALTS    | 0x000003,
  /*261*/ COUNT_OF_PHRASES | 0x000001,
  /*262*/ PHRASE_TYPE      | G_CONSTVAR,
  /*263*/ COUNT_OF_PHRASES | 0x000001,
  /*264*/ PHRASE_TYPE      | G_CONST,
  /*265*/ COUNT_OF_PHRASES | 0x000003,
  /*266*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*267*/ PHRASE_TYPE      | G_CEXPR,
  /*268*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */

// P<CEXPR> = ...;
  /*269*/ COUNT_OF_ALTS    | 0x000001,
  /*270*/ COUNT_OF_PHRASES | 0x000001,
  /*271*/ PHRASE_TYPE      | G_CTORP,

// P<CTORP> = ...;
  /*272*/ COUNT_OF_ALTS    | 0x000001,
  /*273*/ COUNT_OF_PHRASES | 0x000003,
  /*274*/ PHRASE_TYPE      | G_UOP,
  /*275*/ PHRASE_TYPE      | G_COPERAND,
  /*276*/ PHRASE_TYPE      | G_RESTOFCEXPR,

// P<STAROREXPR> = ...;
  /*277*/ COUNT_OF_ALTS    | 0x000002,
  /*278*/ COUNT_OF_PHRASES | 0x000003,
  /*279*/ PHRASE_TYPE      | G_UOP,
  /*280*/ PHRASE_TYPE      | G_COPERAND,
  /*281*/ PHRASE_TYPE      | G_RESTOFCEXPR,
  /*282*/ COUNT_OF_PHRASES | 0x000001,
  /*283*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002a,  /* '*' */

// P<TORP> = ...;
  /*284*/ COUNT_OF_ALTS    | 0x000001,
  /*285*/ COUNT_OF_PHRASES | 0x000003,
  /*286*/ PHRASE_TYPE      | G_UOP,
  /*287*/ PHRASE_TYPE      | G_OPERAND,
  /*288*/ PHRASE_TYPE      | G_RESTOFEXPR,

// P<EXPR> = ...;
  /*289*/ COUNT_OF_ALTS    | 0x000001,
  /*290*/ COUNT_OF_PHRASES | 0x000001,
  /*291*/ PHRASE_TYPE      | G_TORP,

// P<RESTOFEXPR> = ...;
  /*292*/ COUNT_OF_ALTS    | 0x000002,
  /*293*/ COUNT_OF_PHRASES | 0x000003,
  /*294*/ PHRASE_TYPE      | G_OP,
  /*295*/ PHRASE_TYPE      | G_OPERAND,
  /*296*/ PHRASE_TYPE      | G_RESTOFEXPR,
  /*297*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFCEXPR> = ...;
  /*298*/ COUNT_OF_ALTS    | 0x000002,
  /*299*/ COUNT_OF_PHRASES | 0x000003,
  /*300*/ PHRASE_TYPE      | G_OP,
  /*301*/ PHRASE_TYPE      | G_COPERAND,
  /*302*/ PHRASE_TYPE      | G_RESTOFCEXPR,
  /*303*/ COUNT_OF_PHRASES | 0x000000,

// P<APP> = ...;
  /*304*/ COUNT_OF_ALTS    | 0x000002,
  /*305*/ COUNT_OF_PHRASES | 0x000004,
  /*306*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*307*/ PHRASE_TYPE      | G_EXPR,
  /*308*/ PHRASE_TYPE      | G_RESTOFAPP,
  /*309*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */
  /*310*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFAPP> = ...;
  /*311*/ COUNT_OF_ALTS    | 0x000002,
  /*312*/ COUNT_OF_PHRASES | 0x000004,
  /*313*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*314*/ PHRASE_TYPE      | G_READLINEP,
  /*315*/ PHRASE_TYPE      | G_EXPR,
  /*316*/ PHRASE_TYPE      | G_RESTOFAPP,
  /*317*/ COUNT_OF_PHRASES | 0x000000,

// P<PC_IU> = ...;
  /*318*/ COUNT_OF_ALTS    | 0x000002,
  /*319*/ COUNT_OF_PHRASES | 0x000001,
  /*320*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000001,  /* if */
  /*321*/ COUNT_OF_PHRASES | 0x000001,
  /*322*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000002,  /* unless */

// P<TOP_LEVEL_CONDITION> = ...;
  /*323*/ COUNT_OF_ALTS    | 0x000001,
  /*324*/ COUNT_OF_PHRASES | 0x000002,
  /*325*/ PHRASE_TYPE      | G_SC,
  /*326*/ PHRASE_TYPE      | G_RESTOFCOND,

// P<CYCPARM> = ...;
  /*327*/ COUNT_OF_ALTS    | 0x000001,
  /*328*/ COUNT_OF_PHRASES | 0x000007,
  /*329*/ PHRASE_TYPE      | G_VARNAME,
  /*330*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*331*/ PHRASE_TYPE      | G_EXPR,
  /*332*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*333*/ PHRASE_TYPE      | G_EXPR,
  /*334*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*335*/ PHRASE_TYPE      | G_EXPR,

// P<PC_WUF> = ...;
  /*336*/ COUNT_OF_ALTS    | 0x000003,
  /*337*/ COUNT_OF_PHRASES | 0x000002,
  /*338*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000003,  /* while */
  /*339*/ PHRASE_TYPE      | G_TOP_LEVEL_CONDITION,
  /*340*/ COUNT_OF_PHRASES | 0x000002,
  /*341*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000004,  /* until */
  /*342*/ PHRASE_TYPE      | G_TOP_LEVEL_CONDITION,
  /*343*/ COUNT_OF_PHRASES | 0x000002,
  /*344*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000005,  /* for */
  /*345*/ PHRASE_TYPE      | G_CYCPARM,

// P<ALIAS> = ...;
  /*346*/ COUNT_OF_ALTS    | 0x000002,
  /*347*/ COUNT_OF_PHRASES | 0x000002,
  /*348*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000006,  /* alias */
  /*349*/ PHRASE_TYPE      | G_ALIASTEXT,
  /*350*/ COUNT_OF_PHRASES | 0x000000,

// P<DECLNAMES> = ...;
  /*351*/ COUNT_OF_ALTS    | 0x000002,
  /*352*/ COUNT_OF_PHRASES | 0x000004,
  /*353*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*354*/ PHRASE_TYPE      | G_READLINEP,
  /*355*/ PHRASE_TYPE      | G_DECLNAME,
  /*356*/ PHRASE_TYPE      | G_DECLNAMES,
  /*357*/ COUNT_OF_PHRASES | 0x000000,

// P<DECLNAME> = ...;
  /*358*/ COUNT_OF_ALTS    | 0x000001,
  /*359*/ COUNT_OF_PHRASES | 0x000001,
  /*360*/ PHRASE_TYPE      | G_NAME,

// P<FULLTYPE> = ...;
  /*361*/ COUNT_OF_ALTS    | 0x000002,
  /*362*/ COUNT_OF_PHRASES | 0x000001,
  /*363*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000007,  /* integer */
  /*364*/ COUNT_OF_PHRASES | 0x000000,

// P<BTYPE> = ...;
  /*365*/ COUNT_OF_ALTS    | 0x000002,
  /*366*/ COUNT_OF_PHRASES | 0x000001,
  /*367*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000008,  /* real */
  /*368*/ COUNT_OF_PHRASES | 0x000001,
  /*369*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000007,  /* integer */

// P<XTYPE> = ...;
  /*370*/ COUNT_OF_ALTS    | 0x000009,
  /*371*/ COUNT_OF_PHRASES | 0x000001,
  /*372*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000007,  /* integer */
  /*373*/ COUNT_OF_PHRASES | 0x000001,
  /*374*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000008,  /* real */
  /*375*/ COUNT_OF_PHRASES | 0x000003,
  /*376*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000009,  /* long */
  /*377*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000009,  /* long */
  /*378*/ PHRASE_TYPE      | G_BTYPE,
  /*379*/ COUNT_OF_PHRASES | 0x000002,
  /*380*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000009,  /* long */
  /*381*/ PHRASE_TYPE      | G_BTYPE,
  /*382*/ COUNT_OF_PHRASES | 0x000002,
  /*383*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00000a,  /* byte */
  /*384*/ PHRASE_TYPE      | G_FULLTYPE,
  /*385*/ COUNT_OF_PHRASES | 0x000002,
  /*386*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00000b,  /* string */
  /*387*/ PHRASE_TYPE      | G_REPFACT,
  /*388*/ COUNT_OF_PHRASES | 0x000002,
  /*389*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00000c,  /* half */
  /*390*/ PHRASE_TYPE      | G_FULLTYPE,
  /*391*/ COUNT_OF_PHRASES | 0x000002,
  /*392*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00000d,  /* short */
  /*393*/ PHRASE_TYPE      | G_FULLTYPE,
  /*394*/ COUNT_OF_PHRASES | 0x000004,
  /*395*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00000e,  /* record */
  /*396*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*397*/ PHRASE_TYPE      | G_RFREF,
  /*398*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */

// P<RT> = ...;
  /*399*/ COUNT_OF_ALTS    | 0x000002,
  /*400*/ COUNT_OF_PHRASES | 0x000001,
  /*401*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00000f,  /* routine */
  /*402*/ COUNT_OF_PHRASES | 0x000002,
  /*403*/ PHRASE_TYPE      | G_XTYPE,
  /*404*/ PHRASE_TYPE      | G_FM,

// P<FM> = ...;
  /*405*/ COUNT_OF_ALTS    | 0x000003,
  /*406*/ COUNT_OF_PHRASES | 0x000001,
  /*407*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000010,  /* fn */
  /*408*/ COUNT_OF_PHRASES | 0x000001,
  /*409*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000011,  /* map */
  /*410*/ COUNT_OF_PHRASES | 0x000001,
  /*411*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000012,  /* function */

// P<FPDEL> = ...;
  /*412*/ COUNT_OF_ALTS    | 0x000003,
  /*413*/ COUNT_OF_PHRASES | 0x000004,
  /*414*/ PHRASE_TYPE      | G_XTYPE,
  /*415*/ PHRASE_TYPE      | G_Opt_AN_N_type,
  /*416*/ PHRASE_TYPE      | G_DECLNAME,
  /*417*/ PHRASE_TYPE      | G_DECLNAMES,
  /*418*/ COUNT_OF_PHRASES | 0x000005,
  /*419*/ PHRASE_TYPE      | G_RT,
  /*420*/ PHRASE_TYPE      | G_Opt_N_type,
  /*421*/ PHRASE_TYPE      | G_DECLNAME,
  /*422*/ PHRASE_TYPE      | G_DECLNAMES,
  /*423*/ PHRASE_TYPE      | G_FPP,
  /*424*/ COUNT_OF_PHRASES | 0x000003,
  /*425*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000013,  /* name */
  /*426*/ PHRASE_TYPE      | G_DECLNAME,
  /*427*/ PHRASE_TYPE      | G_DECLNAMES,

// P<Opt_N_type> = ...;
  /*428*/ COUNT_OF_ALTS    | 0x000002,
  /*429*/ COUNT_OF_PHRASES | 0x000001,
  /*430*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000013,  /* name */
  /*431*/ COUNT_OF_PHRASES | 0x000000,

// P<Opt_AN_N_type> = ...;
  /*432*/ COUNT_OF_ALTS    | 0x000003,
  /*433*/ COUNT_OF_PHRASES | 0x000002,
  /*434*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000014,  /* array */
  /*435*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000013,  /* name */
  /*436*/ COUNT_OF_PHRASES | 0x000001,
  /*437*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000013,  /* name */
  /*438*/ COUNT_OF_PHRASES | 0x000000,

// P<FPP> = ...;
  /*439*/ COUNT_OF_ALTS    | 0x000002,
  /*440*/ COUNT_OF_PHRASES | 0x000006,
  /*441*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*442*/ PHRASE_TYPE      | G_PUSHDECS,
  /*443*/ PHRASE_TYPE      | G_FPDEL,
  /*444*/ PHRASE_TYPE      | G_POPDECS,
  /*445*/ PHRASE_TYPE      | G_RESTOFFPLIST,
  /*446*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */
  /*447*/ COUNT_OF_PHRASES | 0x000000,

// P<Opt_comma> = ...;
  /*448*/ COUNT_OF_ALTS    | 0x000002,
  /*449*/ COUNT_OF_PHRASES | 0x000001,
  /*450*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*451*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFFPLIST> = ...;
  /*452*/ COUNT_OF_ALTS    | 0x000002,
  /*453*/ COUNT_OF_PHRASES | 0x000006,
  /*454*/ PHRASE_TYPE      | G_Opt_comma,
  /*455*/ PHRASE_TYPE      | G_READLINEP,
  /*456*/ PHRASE_TYPE      | G_PUSHDECS,
  /*457*/ PHRASE_TYPE      | G_FPDEL,
  /*458*/ PHRASE_TYPE      | G_POPDECS,
  /*459*/ PHRASE_TYPE      | G_RESTOFFPLIST,
  /*460*/ COUNT_OF_PHRASES | 0x000000,

// P<ENDLIST> = ...;
  /*461*/ COUNT_OF_ALTS    | 0x000005,
  /*462*/ COUNT_OF_PHRASES | 0x000002,
  /*463*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000015,  /* ofprogram */
  /*464*/ PHRASE_TYPE      | G_UP,
  /*465*/ COUNT_OF_PHRASES | 0x000001,
  /*466*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000016,  /* ofperm */
  /*467*/ COUNT_OF_PHRASES | 0x000001,
  /*468*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000017,  /* offile */
  /*469*/ COUNT_OF_PHRASES | 0x000002,
  /*470*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000018,  /* oflist */
  /*471*/ SEMANTIC_TYPE    | S_LISTOFF,
  /*472*/ COUNT_OF_PHRASES | 0x000001,
  /*473*/ PHRASE_TYPE      | G_UP,

// P<ARRAYFORMAT> = ...;
  /*474*/ COUNT_OF_ALTS    | 0x000002,
  /*475*/ COUNT_OF_PHRASES | 0x000001,
  /*476*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000019,  /* format */
  /*477*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFSC> = ...;
  /*478*/ COUNT_OF_ALTS    | 0x000002,
  /*479*/ COUNT_OF_PHRASES | 0x000002,
  /*480*/ PHRASE_TYPE      | G_COMP2,
  /*481*/ PHRASE_TYPE      | G_EXPR,
  /*482*/ COUNT_OF_PHRASES | 0x000000,

// P<SC> = ...;
  /*483*/ COUNT_OF_ALTS    | 0x000003,
  /*484*/ COUNT_OF_PHRASES | 0x000004,
  /*485*/ PHRASE_TYPE      | G_EXPR,
  /*486*/ PHRASE_TYPE      | G_COMP1,
  /*487*/ PHRASE_TYPE      | G_EXPR,
  /*488*/ PHRASE_TYPE      | G_RESTOFSC,
  /*489*/ COUNT_OF_PHRASES | 0x000004,
  /*490*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*491*/ PHRASE_TYPE      | G_SC,
  /*492*/ PHRASE_TYPE      | G_RESTOFCOND,
  /*493*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */
  /*494*/ COUNT_OF_PHRASES | 0x000002,
  /*495*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001a,  /* not */
  /*496*/ PHRASE_TYPE      | G_SC,

// P<RESTOFCOND> = ...;
  /*497*/ COUNT_OF_ALTS    | 0x000003,
  /*498*/ COUNT_OF_PHRASES | 0x000003,
  /*499*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001b,  /* and */
  /*500*/ PHRASE_TYPE      | G_SC,
  /*501*/ PHRASE_TYPE      | G_RESTOFANDC,
  /*502*/ COUNT_OF_PHRASES | 0x000003,
  /*503*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001c,  /* or */
  /*504*/ PHRASE_TYPE      | G_SC,
  /*505*/ PHRASE_TYPE      | G_RESTOFORC,
  /*506*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFANDC> = ...;
  /*507*/ COUNT_OF_ALTS    | 0x000002,
  /*508*/ COUNT_OF_PHRASES | 0x000003,
  /*509*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001b,  /* and */
  /*510*/ PHRASE_TYPE      | G_SC,
  /*511*/ PHRASE_TYPE      | G_RESTOFANDC,
  /*512*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFORC> = ...;
  /*513*/ COUNT_OF_ALTS    | 0x000002,
  /*514*/ COUNT_OF_PHRASES | 0x000003,
  /*515*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001c,  /* or */
  /*516*/ PHRASE_TYPE      | G_SC,
  /*517*/ PHRASE_TYPE      | G_RESTOFORC,
  /*518*/ COUNT_OF_PHRASES | 0x000000,

// P<Optional_Assignment> = ...;
  /*519*/ COUNT_OF_ALTS    | 0x000002,
  /*520*/ COUNT_OF_PHRASES | 0x000002,
  /*521*/ PHRASE_TYPE      | G_ASSOP,
  /*522*/ PHRASE_TYPE      | G_EXPR,
  /*523*/ COUNT_OF_PHRASES | 0x000000,

// P<Opt_RtFnMapSpec> = ...;
  /*524*/ COUNT_OF_ALTS    | 0x000002,
  /*525*/ COUNT_OF_PHRASES | 0x000001,
  /*526*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001d,  /* spec */
  /*527*/ COUNT_OF_PHRASES | 0x000000,

// P<VSPECQ> = ...;
  /*528*/ COUNT_OF_ALTS    | 0x000002,
  /*529*/ COUNT_OF_PHRASES | 0x000001,
  /*530*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001d,  /* spec */
  /*531*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFBPLIST> = ...;
  /*532*/ COUNT_OF_ALTS    | 0x000002,
  /*533*/ COUNT_OF_PHRASES | 0x000005,
  /*534*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*535*/ PHRASE_TYPE      | G_EXPR,
  /*536*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003a,  /* ':' */
  /*537*/ PHRASE_TYPE      | G_EXPR,
  /*538*/ PHRASE_TYPE      | G_RESTOFBPLIST,
  /*539*/ COUNT_OF_PHRASES | 0x000000,

// P<BPAIR> = ...;
  /*540*/ COUNT_OF_ALTS    | 0x000001,
  /*541*/ COUNT_OF_PHRASES | 0x000006,
  /*542*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*543*/ PHRASE_TYPE      | G_EXPR,
  /*544*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003a,  /* ':' */
  /*545*/ PHRASE_TYPE      | G_EXPR,
  /*546*/ PHRASE_TYPE      | G_RESTOFBPLIST,
  /*547*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */

// P<RESTOFARLIST> = ...;
  /*548*/ COUNT_OF_ALTS    | 0x000002,
  /*549*/ COUNT_OF_PHRASES | 0x000002,
  /*550*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*551*/ PHRASE_TYPE      | G_ADECLN,
  /*552*/ COUNT_OF_PHRASES | 0x000000,

// P<ADECLN> = ...;
  /*553*/ COUNT_OF_ALTS    | 0x000001,
  /*554*/ COUNT_OF_PHRASES | 0x000004,
  /*555*/ PHRASE_TYPE      | G_DECLNAME,
  /*556*/ PHRASE_TYPE      | G_DECLNAMES,
  /*557*/ PHRASE_TYPE      | G_BPAIR,
  /*558*/ PHRASE_TYPE      | G_RESTOFARLIST,

// P<DECLN> = ...;
  /*559*/ COUNT_OF_ALTS    | 0x000002,
  /*560*/ COUNT_OF_PHRASES | 0x000003,
  /*561*/ PHRASE_TYPE      | G_Opt_AN_N_type,
  /*562*/ PHRASE_TYPE      | G_DECLNAME,
  /*563*/ PHRASE_TYPE      | G_DECLNAMES,
  /*564*/ COUNT_OF_PHRASES | 0x000003,
  /*565*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000014,  /* array */
  /*566*/ PHRASE_TYPE      | G_ARRAYFORMAT,
  /*567*/ PHRASE_TYPE      | G_ADECLN,

// P<OWNDEC> = ...;
  /*568*/ COUNT_OF_ALTS    | 0x000002,
  /*569*/ COUNT_OF_PHRASES | 0x000006,
  /*570*/ PHRASE_TYPE      | G_Opt_AN_N_type,
  /*571*/ PHRASE_TYPE      | G_VSPECQ,
  /*572*/ PHRASE_TYPE      | G_DECLNAME,
  /*573*/ PHRASE_TYPE      | G_ALIAS,
  /*574*/ PHRASE_TYPE      | G_Opt_Const_Init,
  /*575*/ PHRASE_TYPE      | G_RESTOFOWNDEC,
  /*576*/ COUNT_OF_PHRASES | 0x000006,
  /*577*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000014,  /* array */
  /*578*/ PHRASE_TYPE      | G_ARRAYFORMAT,
  /*579*/ PHRASE_TYPE      | G_DECLNAME,
  /*580*/ PHRASE_TYPE      | G_ALIAS,
  /*581*/ PHRASE_TYPE      | G_BPAIR,
  /*582*/ PHRASE_TYPE      | G_CONSTLIST,

// P<RESTOFOWNDEC> = ...;
  /*583*/ COUNT_OF_ALTS    | 0x000002,
  /*584*/ COUNT_OF_PHRASES | 0x000006,
  /*585*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*586*/ PHRASE_TYPE      | G_READLINEP,
  /*587*/ PHRASE_TYPE      | G_DECLNAME,
  /*588*/ PHRASE_TYPE      | G_ALIAS,
  /*589*/ PHRASE_TYPE      | G_Opt_Const_Init,
  /*590*/ PHRASE_TYPE      | G_RESTOFOWNDEC,
  /*591*/ COUNT_OF_PHRASES | 0x000000,

// P<XOWN> = ...;
  /*592*/ COUNT_OF_ALTS    | 0x000005,
  /*593*/ COUNT_OF_PHRASES | 0x000001,
  /*594*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001e,  /* own */
  /*595*/ COUNT_OF_PHRASES | 0x000001,
  /*596*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001f,  /* external */
  /*597*/ COUNT_OF_PHRASES | 0x000001,
  /*598*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000020,  /* extrinsic */
  /*599*/ COUNT_OF_PHRASES | 0x000001,
  /*600*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000021,  /* constant */
  /*601*/ COUNT_OF_PHRASES | 0x000001,
  /*602*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000022,  /* const */

// P<CONSTLIST> = ...;
  /*603*/ COUNT_OF_ALTS    | 0x000002,
  /*604*/ COUNT_OF_PHRASES | 0x000007,
  /*605*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*606*/ PHRASE_TYPE      | G_READLINEP,
  /*607*/ PHRASE_TYPE      | G_UOP,
  /*608*/ PHRASE_TYPE      | G_COPERAND,
  /*609*/ PHRASE_TYPE      | G_RESTOFCEXPR,
  /*610*/ PHRASE_TYPE      | G_REPFACT,
  /*611*/ PHRASE_TYPE      | G_ROCL,
  /*612*/ COUNT_OF_PHRASES | 0x000000,

// P<ExPop> = ...;
  /*613*/ COUNT_OF_ALTS    | 0x000001,
  /*614*/ COUNT_OF_PHRASES | 0x000000,

// P<ROCL> = ...;
  /*615*/ COUNT_OF_ALTS    | 0x000002,
  /*616*/ COUNT_OF_PHRASES | 0x000008,
  /*617*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*618*/ PHRASE_TYPE      | G_ExPop,
  /*619*/ PHRASE_TYPE      | G_READLINEP,
  /*620*/ PHRASE_TYPE      | G_UOP,
  /*621*/ PHRASE_TYPE      | G_COPERAND,
  /*622*/ PHRASE_TYPE      | G_RESTOFCEXPR,
  /*623*/ PHRASE_TYPE      | G_REPFACT,
  /*624*/ PHRASE_TYPE      | G_ROCL,
  /*625*/ COUNT_OF_PHRASES | 0x000000,

// P<REPFACT> = ...;
  /*626*/ COUNT_OF_ALTS    | 0x000002,
  /*627*/ COUNT_OF_PHRASES | 0x000003,
  /*628*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*629*/ PHRASE_TYPE      | G_STAROREXPR,
  /*630*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */
  /*631*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFNLIST> = ...;
  /*632*/ COUNT_OF_ALTS    | 0x000002,
  /*633*/ COUNT_OF_PHRASES | 0x000003,
  /*634*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*635*/ PHRASE_TYPE      | G_CEXPR,
  /*636*/ PHRASE_TYPE      | G_RESTOFNLIST,
  /*637*/ COUNT_OF_PHRASES | 0x000000,

// P<PC_EVENTQ> = ...;
  /*638*/ COUNT_OF_ALTS    | 0x000002,
  /*639*/ COUNT_OF_PHRASES | 0x000001,
  /*640*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000023,  /* event */
  /*641*/ COUNT_OF_PHRASES | 0x000000,

// P<Opt_EXPR> = ...;
  /*642*/ COUNT_OF_ALTS    | 0x000002,
  /*643*/ COUNT_OF_PHRASES | 0x000002,
  /*644*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*645*/ PHRASE_TYPE      | G_EXPR,
  /*646*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFSWLIST> = ...;
  /*647*/ COUNT_OF_ALTS    | 0x000002,
  /*648*/ COUNT_OF_PHRASES | 0x000009,
  /*649*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*650*/ PHRASE_TYPE      | G_DECLNAME,
  /*651*/ PHRASE_TYPE      | G_DECLNAMES,
  /*652*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*653*/ PHRASE_TYPE      | G_EXPR,
  /*654*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003a,  /* ':' */
  /*655*/ PHRASE_TYPE      | G_EXPR,
  /*656*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */
  /*657*/ PHRASE_TYPE      | G_RESTOFSWLIST,
  /*658*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFREPEAT> = ...;
  /*659*/ COUNT_OF_ALTS    | 0x000002,
  /*660*/ COUNT_OF_PHRASES | 0x000002,
  /*661*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000004,  /* until */
  /*662*/ PHRASE_TYPE      | G_TOP_LEVEL_CONDITION,
  /*663*/ COUNT_OF_PHRASES | 0x000000,

// P<FINISHELSEQ> = ...;
  /*664*/ COUNT_OF_ALTS    | 0x000002,
  /*665*/ COUNT_OF_PHRASES | 0x000002,
  /*666*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000024,  /* else */
  /*667*/ PHRASE_TYPE      | G_AFTERELSE,
  /*668*/ COUNT_OF_PHRASES | 0x000000,

// P<AFTERELSE> = ...;
  /*669*/ COUNT_OF_ALTS    | 0x000003,
  /*670*/ COUNT_OF_PHRASES | 0x000001,
  /*671*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000025,  /* start */
  /*672*/ COUNT_OF_PHRASES | 0x000003,
  /*673*/ PHRASE_TYPE      | G_PC_IU,
  /*674*/ PHRASE_TYPE      | G_TOP_LEVEL_CONDITION,
  /*675*/ PHRASE_TYPE      | G_RESTOFIU,
  /*676*/ COUNT_OF_PHRASES | 0x000001,
  /*677*/ PHRASE_TYPE      | G_UI_BLOCK,

// P<ELSEQ> = ...;
  /*678*/ COUNT_OF_ALTS    | 0x000002,
  /*679*/ COUNT_OF_PHRASES | 0x000002,
  /*680*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000024,  /* else */
  /*681*/ PHRASE_TYPE      | G_AFTERELSE,
  /*682*/ COUNT_OF_PHRASES | 0x000000,

// P<RESTOFIU> = ...;
  /*683*/ COUNT_OF_ALTS    | 0x000003,
  /*684*/ COUNT_OF_PHRASES | 0x000001,
  /*685*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000025,  /* start */
  /*686*/ COUNT_OF_PHRASES | 0x000002,
  /*687*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000026,  /* then */
  /*688*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000025,  /* start */
  /*689*/ COUNT_OF_PHRASES | 0x000003,
  /*690*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000026,  /* then */
  /*691*/ PHRASE_TYPE      | G_UI_BLOCK,
  /*692*/ PHRASE_TYPE      | G_ELSEQ,

// P<Opt_Const_Init> = ...;
  /*693*/ COUNT_OF_ALTS    | 0x000002,
  /*694*/ COUNT_OF_PHRASES | 0x000004,
  /*695*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003d,  /* '=' */
  /*696*/ PHRASE_TYPE      | G_UOP,
  /*697*/ PHRASE_TYPE      | G_COPERAND,
  /*698*/ PHRASE_TYPE      | G_RESTOFCEXPR,
  /*699*/ COUNT_OF_PHRASES | 0x000000,

// P<SEX> = ...;
  /*700*/ COUNT_OF_ALTS    | 0x000006,
  /*701*/ COUNT_OF_PHRASES | 0x000001,
  /*702*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001f,  /* external */
  /*703*/ COUNT_OF_PHRASES | 0x000001,
  /*704*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000027,  /* system */
  /*705*/ COUNT_OF_PHRASES | 0x000001,
  /*706*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000028,  /* dynamic */
  /*707*/ COUNT_OF_PHRASES | 0x000001,
  /*708*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000029,  /* prim */
  /*709*/ COUNT_OF_PHRASES | 0x000001,
  /*710*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00002a,  /* perm */
  /*711*/ COUNT_OF_PHRASES | 0x000000,

// P<RFSTMNT> = ...;
  /*712*/ COUNT_OF_ALTS    | 0x000002,
  /*713*/ COUNT_OF_PHRASES | 0x000002,
  /*714*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001d,  /* spec */
  /*715*/ PHRASE_TYPE      | G_DECLNAME,
  /*716*/ COUNT_OF_PHRASES | 0x000008,
  /*717*/ PHRASE_TYPE      | G_DECLNAME,
  /*718*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*719*/ PHRASE_TYPE      | G_PUSHDECS,
  /*720*/ PHRASE_TYPE      | G_RFDEC,
  /*721*/ PHRASE_TYPE      | G_RESTOFRFDEC,
  /*722*/ PHRASE_TYPE      | G_ALTRFDEC,
  /*723*/ PHRASE_TYPE      | G_POPDECS,
  /*724*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */

// P<RFREF> = ...;
  /*725*/ COUNT_OF_ALTS    | 0x000002,
  /*726*/ COUNT_OF_PHRASES | 0x000001,
  /*727*/ PHRASE_TYPE      | G_VARNAME,
  /*728*/ COUNT_OF_PHRASES | 0x000003,
  /*729*/ PHRASE_TYPE      | G_RFDEC,
  /*730*/ PHRASE_TYPE      | G_RESTOFRFDEC,
  /*731*/ PHRASE_TYPE      | G_ALTRFDEC,

// P<RESTOFRFDEC> = ...;
  /*732*/ COUNT_OF_ALTS    | 0x000002,
  /*733*/ COUNT_OF_PHRASES | 0x000004,
  /*734*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002c,  /* ',' */
  /*735*/ PHRASE_TYPE      | G_READLINEP,
  /*736*/ PHRASE_TYPE      | G_RFDEC,
  /*737*/ PHRASE_TYPE      | G_RESTOFRFDEC,
  /*738*/ COUNT_OF_PHRASES | 0x000000,

// P<RFDEC> = ...;
  /*739*/ COUNT_OF_ALTS    | 0x000002,
  /*740*/ COUNT_OF_PHRASES | 0x000002,
  /*741*/ PHRASE_TYPE      | G_XTYPE,
  /*742*/ PHRASE_TYPE      | G_RFELMNT,
  /*743*/ COUNT_OF_PHRASES | 0x000005,
  /*744*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*745*/ PHRASE_TYPE      | G_RFDEC,
  /*746*/ PHRASE_TYPE      | G_RESTOFRFDEC,
  /*747*/ PHRASE_TYPE      | G_ALTRFDEC,
  /*748*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */

// P<RFELMNT> = ...;
  /*749*/ COUNT_OF_ALTS    | 0x000002,
  /*750*/ COUNT_OF_PHRASES | 0x000003,
  /*751*/ PHRASE_TYPE      | G_Opt_AN_N_type,
  /*752*/ PHRASE_TYPE      | G_DECLNAME,
  /*753*/ PHRASE_TYPE      | G_DECLNAMES,
  /*754*/ COUNT_OF_PHRASES | 0x000002,
  /*755*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000014,  /* array */
  /*756*/ PHRASE_TYPE      | G_ADECLN,

// P<ALTRFDEC> = ...;
  /*757*/ COUNT_OF_ALTS    | 0x000002,
  /*758*/ COUNT_OF_PHRASES | 0x000004,
  /*759*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001c,  /* or */
  /*760*/ PHRASE_TYPE      | G_RFDEC,
  /*761*/ PHRASE_TYPE      | G_RESTOFRFDEC,
  /*762*/ PHRASE_TYPE      | G_ALTRFDEC,
  /*763*/ COUNT_OF_PHRASES | 0x000000,

// P<ASM> = ...;
  /*764*/ COUNT_OF_ALTS    | 0x000002,
  /*765*/ COUNT_OF_PHRASES | 0x000005,
  /*766*/ PHRASE_TYPE      | NEGATED_PHRASE     | G_semi,
  /*767*/ BIP_TYPE         | NEGATED_PHRASE     | B_nl,
  /*768*/ BIP_TYPE         | NEGATED_PHRASE     | WHITESPACE_ALLOWED | B_eof,
  /*769*/ REGEXP_TYPE      | WHITESPACE_ALLOWED | 0x000007,  /* ^. */
  /*770*/ PHRASE_TYPE      | G_ASM,
  /*771*/ COUNT_OF_PHRASES | 0x000000,

// P<Call_or_Assign_AUI> = ...;
  /*772*/ COUNT_OF_ALTS    | 0x000002,
  /*773*/ COUNT_OF_PHRASES | 0x000003,
  /*774*/ PHRASE_TYPE      | G_VAR,
  /*775*/ PHRASE_TYPE      | G_ASSOP,
  /*776*/ PHRASE_TYPE      | G_EXPR,
  /*777*/ COUNT_OF_PHRASES | 0x000001,
  /*778*/ PHRASE_TYPE      | G_VAR,

// P<SWITCHIDX> = ...;
  /*779*/ COUNT_OF_ALTS    | 0x000002,
  /*780*/ COUNT_OF_PHRASES | 0x000003,
  /*781*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*782*/ PHRASE_TYPE      | G_EXPR,
  /*783*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */
  /*784*/ COUNT_OF_PHRASES | 0x000000,

// P<Goto> = ...;
  /*785*/ COUNT_OF_ALTS    | 0x000001,
  /*786*/ COUNT_OF_PHRASES | 0x000004,
  /*787*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002d,  /* '-' */
  /*788*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003e,  /* '>' */
  /*789*/ PHRASE_TYPE      | G_VARNAME,
  /*790*/ PHRASE_TYPE      | G_SWITCHIDX,

// P<return> = ...;
  /*791*/ COUNT_OF_ALTS    | 0x000001,
  /*792*/ COUNT_OF_PHRASES | 0x000001,
  /*793*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00002b,  /* return */

// P<result> = ...;
  /*794*/ COUNT_OF_ALTS    | 0x000001,
  /*795*/ COUNT_OF_PHRASES | 0x000003,
  /*796*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00002c,  /* result */
  /*797*/ PHRASE_TYPE      | G_ASSOP,
  /*798*/ PHRASE_TYPE      | G_EXPR,

// P<monitor_AUI> = ...;
  /*799*/ COUNT_OF_ALTS    | 0x000001,
  /*800*/ COUNT_OF_PHRASES | 0x000001,
  /*801*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00002d,  /* monitor */

// P<stop> = ...;
  /*802*/ COUNT_OF_ALTS    | 0x000001,
  /*803*/ COUNT_OF_PHRASES | 0x000001,
  /*804*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00002e,  /* stop */

// P<signal> = ...;
  /*805*/ COUNT_OF_ALTS    | 0x000001,
  /*806*/ COUNT_OF_PHRASES | 0x000004,
  /*807*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00002f,  /* signal */
  /*808*/ PHRASE_TYPE      | G_PC_EVENTQ,
  /*809*/ PHRASE_TYPE      | G_CEXPR,
  /*810*/ PHRASE_TYPE      | G_Opt_EXPR,

// P<exit> = ...;
  /*811*/ COUNT_OF_ALTS    | 0x000001,
  /*812*/ COUNT_OF_PHRASES | 0x000001,
  /*813*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000030,  /* exit */

// P<continue> = ...;
  /*814*/ COUNT_OF_ALTS    | 0x000001,
  /*815*/ COUNT_OF_PHRASES | 0x000001,
  /*816*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000031,  /* continue */

// P<Unconditional_Instructions> = ...;
  /*817*/ COUNT_OF_ALTS    | 0x000003,
  /*818*/ COUNT_OF_PHRASES | 0x000002,
  /*819*/ PHRASE_TYPE      | G_UI_BLOCK,
  /*820*/ PHRASE_TYPE      | G_S,
  /*821*/ COUNT_OF_PHRASES | 0x000004,
  /*822*/ PHRASE_TYPE      | G_UI_BLOCK,
  /*823*/ PHRASE_TYPE      | G_PC_IU,
  /*824*/ PHRASE_TYPE      | G_TOP_LEVEL_CONDITION,
  /*825*/ PHRASE_TYPE      | G_S,
  /*826*/ COUNT_OF_PHRASES | 0x000003,
  /*827*/ PHRASE_TYPE      | G_UI_BLOCK,
  /*828*/ PHRASE_TYPE      | G_PC_WUF,
  /*829*/ PHRASE_TYPE      | G_S,

// P<UI> = ...;
  /*830*/ COUNT_OF_ALTS    | 0x000003,
  /*831*/ COUNT_OF_PHRASES | 0x000002,
  /*832*/ PHRASE_TYPE      | G_NONFINAL_UI,
  /*833*/ PHRASE_TYPE      | G_AUI,
  /*834*/ COUNT_OF_PHRASES | 0x000001,
  /*835*/ PHRASE_TYPE      | G_NONFINAL_UI,
  /*836*/ COUNT_OF_PHRASES | 0x000001,
  /*837*/ PHRASE_TYPE      | G_FINAL_UI,

// P<AUI> = ...;
  /*838*/ COUNT_OF_ALTS    | 0x000001,
  /*839*/ COUNT_OF_PHRASES | 0x000002,
  /*840*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00001b,  /* and */
  /*841*/ PHRASE_TYPE      | G_UI,

// P<UI_BLOCK> = ...;
  /*842*/ COUNT_OF_ALTS    | 0x000003,
  /*843*/ COUNT_OF_PHRASES | 0x000002,
  /*844*/ PHRASE_TYPE      | G_NONFINAL_UI,
  /*845*/ PHRASE_TYPE      | G_AUI,
  /*846*/ COUNT_OF_PHRASES | 0x000001,
  /*847*/ PHRASE_TYPE      | G_NONFINAL_UI,
  /*848*/ COUNT_OF_PHRASES | 0x000001,
  /*849*/ PHRASE_TYPE      | G_FINAL_UI,

// P<NONFINAL_UI> = ...;
  /*850*/ COUNT_OF_ALTS    | 0x000002,
  /*851*/ COUNT_OF_PHRASES | 0x000001,
  /*852*/ PHRASE_TYPE      | G_Call_or_Assign_AUI,
  /*853*/ COUNT_OF_PHRASES | 0x000001,
  /*854*/ PHRASE_TYPE      | G_monitor_AUI,

// P<FINAL_UI> = ...;
  /*855*/ COUNT_OF_ALTS    | 0x000007,
  /*856*/ COUNT_OF_PHRASES | 0x000001,
  /*857*/ PHRASE_TYPE      | G_Goto,
  /*858*/ COUNT_OF_PHRASES | 0x000001,
  /*859*/ PHRASE_TYPE      | G_return,
  /*860*/ COUNT_OF_PHRASES | 0x000001,
  /*861*/ PHRASE_TYPE      | G_result,
  /*862*/ COUNT_OF_PHRASES | 0x000001,
  /*863*/ PHRASE_TYPE      | G_stop,
  /*864*/ COUNT_OF_PHRASES | 0x000001,
  /*865*/ PHRASE_TYPE      | G_signal,
  /*866*/ COUNT_OF_PHRASES | 0x000001,
  /*867*/ PHRASE_TYPE      | G_exit,
  /*868*/ COUNT_OF_PHRASES | 0x000001,
  /*869*/ PHRASE_TYPE      | G_continue,

// P<More_STATEMENTS> = ...;
  /*870*/ COUNT_OF_ALTS    | 0x000002,
  /*871*/ COUNT_OF_PHRASES | 0x000002,
  /*872*/ PHRASE_TYPE      | G_STATEMENT,
  /*873*/ PHRASE_TYPE      | G_More_STATEMENTS,
  /*874*/ COUNT_OF_PHRASES | 0x000000,

// P<STATEMENTS> = ...;
  /*875*/ COUNT_OF_ALTS    | 0x000001,
  /*876*/ COUNT_OF_PHRASES | 0x000003,
  /*877*/ PHRASE_TYPE      | G_STATEMENT,
  /*878*/ PHRASE_TYPE      | G_More_STATEMENTS,
  /*879*/ BIP_TYPE         | WHITESPACE_ALLOWED | B_eof,

// P<Labels> = ...;
  /*880*/ COUNT_OF_ALTS    | 0x000003,
  /*881*/ COUNT_OF_PHRASES | 0x000006,
  /*882*/ PHRASE_TYPE      | G_VARNAME,
  /*883*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*884*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002a,  /* '*' */
  /*885*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */
  /*886*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003a,  /* ':' */
  /*887*/ SEMANTIC_TYPE    | S_COLON,
  /*888*/ COUNT_OF_PHRASES | 0x000006,
  /*889*/ PHRASE_TYPE      | G_VARNAME,
  /*890*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*891*/ PHRASE_TYPE      | G_EXPR,
  /*892*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */
  /*893*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003a,  /* ':' */
  /*894*/ SEMANTIC_TYPE    | S_COLON,
  /*895*/ COUNT_OF_PHRASES | 0x000003,
  /*896*/ PHRASE_TYPE      | G_VARNAME,
  /*897*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003a,  /* ':' */
  /*898*/ SEMANTIC_TYPE    | S_COLON,

// P<If_or_Unless> = ...;
  /*899*/ COUNT_OF_ALTS    | 0x000001,
  /*900*/ COUNT_OF_PHRASES | 0x000004,
  /*901*/ PHRASE_TYPE      | G_PC_IU,
  /*902*/ PHRASE_TYPE      | G_TOP_LEVEL_CONDITION,
  /*903*/ PHRASE_TYPE      | G_RESTOFIU,
  /*904*/ PHRASE_TYPE      | G_S,

// P<Opt_CYCPARM> = ...;
  /*905*/ COUNT_OF_ALTS    | 0x000002,
  /*906*/ COUNT_OF_PHRASES | 0x000001,
  /*907*/ PHRASE_TYPE      | G_CYCPARM,
  /*908*/ COUNT_OF_PHRASES | 0x000000,

// P<start_of_cycle> = ...;
  /*909*/ COUNT_OF_ALTS    | 0x000002,
  /*910*/ COUNT_OF_PHRASES | 0x000003,
  /*911*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000032,  /* cycle */
  /*912*/ PHRASE_TYPE      | G_Opt_CYCPARM,
  /*913*/ PHRASE_TYPE      | G_S,
  /*914*/ COUNT_OF_PHRASES | 0x000003,
  /*915*/ PHRASE_TYPE      | G_PC_WUF,
  /*916*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000032,  /* cycle */
  /*917*/ PHRASE_TYPE      | G_S,

// P<end_of_cycle> = ...;
  /*918*/ COUNT_OF_ALTS    | 0x000001,
  /*919*/ COUNT_OF_PHRASES | 0x000003,
  /*920*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000033,  /* repeat */
  /*921*/ PHRASE_TYPE      | G_RESTOFREPEAT,
  /*922*/ PHRASE_TYPE      | G_S,

// P<regular_declaration> = ...;
  /*923*/ COUNT_OF_ALTS    | 0x000001,
  /*924*/ COUNT_OF_PHRASES | 0x000004,
  /*925*/ PHRASE_TYPE      | G_INITDECS,
  /*926*/ PHRASE_TYPE      | G_XTYPE,
  /*927*/ PHRASE_TYPE      | G_DECLN,
  /*928*/ PHRASE_TYPE      | G_S,

// P<proc_declaration> = ...;
  /*929*/ COUNT_OF_ALTS    | 0x000001,
  /*930*/ COUNT_OF_PHRASES | 0x000008,
  /*931*/ PHRASE_TYPE      | G_INITDECS,
  /*932*/ PHRASE_TYPE      | G_SEX,
  /*933*/ PHRASE_TYPE      | G_RT,
  /*934*/ PHRASE_TYPE      | G_Opt_RtFnMapSpec,
  /*935*/ PHRASE_TYPE      | G_DECLNAME,
  /*936*/ PHRASE_TYPE      | G_ALIAS,
  /*937*/ PHRASE_TYPE      | G_FPP,
  /*938*/ PHRASE_TYPE      | G_S,

// P<own_or_external_declaration> = ...;
  /*939*/ COUNT_OF_ALTS    | 0x000001,
  /*940*/ COUNT_OF_PHRASES | 0x000005,
  /*941*/ PHRASE_TYPE      | G_INITDECS,
  /*942*/ PHRASE_TYPE      | G_XOWN,
  /*943*/ PHRASE_TYPE      | G_XTYPE,
  /*944*/ PHRASE_TYPE      | G_OWNDEC,
  /*945*/ PHRASE_TYPE      | G_S,

// P<on_event_block> = ...;
  /*946*/ COUNT_OF_ALTS    | 0x000001,
  /*947*/ COUNT_OF_PHRASES | 0x000006,
  /*948*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000034,  /* on */
  /*949*/ PHRASE_TYPE      | G_PC_EVENTQ,
  /*950*/ PHRASE_TYPE      | G_CEXPR,
  /*951*/ PHRASE_TYPE      | G_RESTOFNLIST,
  /*952*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000025,  /* start */
  /*953*/ PHRASE_TYPE      | G_S,

// P<record_format_declaration> = ...;
  /*954*/ COUNT_OF_ALTS    | 0x000001,
  /*955*/ COUNT_OF_PHRASES | 0x000005,
  /*956*/ PHRASE_TYPE      | G_INITDECS,
  /*957*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00000e,  /* record */
  /*958*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000019,  /* format */
  /*959*/ PHRASE_TYPE      | G_RFSTMNT,
  /*960*/ PHRASE_TYPE      | G_S,

// P<various_ends> = ...;
  /*961*/ COUNT_OF_ALTS    | 0x000001,
  /*962*/ COUNT_OF_PHRASES | 0x000003,
  /*963*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000035,  /* end */
  /*964*/ PHRASE_TYPE      | G_ENDLIST,
  /*965*/ PHRASE_TYPE      | G_S,

// P<include_file> = ...;
  /*966*/ COUNT_OF_ALTS    | 0x000001,
  /*967*/ COUNT_OF_PHRASES | 0x000003,
  /*968*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000036,  /* include */
  /*969*/ PHRASE_TYPE      | G_CONST,
  /*970*/ SEMANTIC_TYPE    | S_INCLUDE,

// P<begin_block> = ...;
  /*971*/ COUNT_OF_ALTS    | 0x000001,
  /*972*/ COUNT_OF_PHRASES | 0x000003,
  /*973*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000037,  /* begin */
  /*974*/ PHRASE_TYPE      | G_DOWN,
  /*975*/ PHRASE_TYPE      | G_S,

// P<switch_declaration> = ...;
  /*976*/ COUNT_OF_ALTS    | 0x000001,
  /*977*/ COUNT_OF_PHRASES | 0x00000b,
  /*978*/ PHRASE_TYPE      | G_INITDECS,
  /*979*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000038,  /* switch */
  /*980*/ PHRASE_TYPE      | G_DECLNAME,
  /*981*/ PHRASE_TYPE      | G_DECLNAMES,
  /*982*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000028,  /* '(' */
  /*983*/ PHRASE_TYPE      | G_EXPR,
  /*984*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00003a,  /* ':' */
  /*985*/ PHRASE_TYPE      | G_EXPR,
  /*986*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x000029,  /* ')' */
  /*987*/ PHRASE_TYPE      | G_RESTOFSWLIST,
  /*988*/ PHRASE_TYPE      | G_S,

// P<list_on> = ...;
  /*989*/ COUNT_OF_ALTS    | 0x000001,
  /*990*/ COUNT_OF_PHRASES | 0x000003,
  /*991*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000039,  /* list */
  /*992*/ PHRASE_TYPE      | G_S,
  /*993*/ SEMANTIC_TYPE    | S_LISTON,

// P<else> = ...;
  /*994*/ COUNT_OF_ALTS    | 0x000001,
  /*995*/ COUNT_OF_PHRASES | 0x000002,
  /*996*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x000024,  /* else */
  /*997*/ PHRASE_TYPE      | G_S,

// P<finish_opt_else> = ...;
  /*998*/ COUNT_OF_ALTS    | 0x000001,
  /*999*/ COUNT_OF_PHRASES | 0x000003,
  /*1000*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00003a,  /* finish */
  /*1001*/ PHRASE_TYPE      | G_FINISHELSEQ,
  /*1002*/ PHRASE_TYPE      | G_S,

// P<embedded_assembler> = ...;
  /*1003*/ COUNT_OF_ALTS    | 0x000001,
  /*1004*/ COUNT_OF_PHRASES | 0x000003,
  /*1005*/ CHAR_TYPE        | WHITESPACE_ALLOWED | 0x00002a,  /* '*' */
  /*1006*/ PHRASE_TYPE      | G_ASM,
  /*1007*/ PHRASE_TYPE      | G_S,

// P<trusted> = ...;
  /*1008*/ COUNT_OF_ALTS    | 0x000001,
  /*1009*/ COUNT_OF_PHRASES | 0x000002,
  /*1010*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00003b,  /* trustedprogram */
  /*1011*/ PHRASE_TYPE      | G_S,

// P<mainep> = ...;
  /*1012*/ COUNT_OF_ALTS    | 0x000001,
  /*1013*/ COUNT_OF_PHRASES | 0x000003,
  /*1014*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00003c,  /* mainep */
  /*1015*/ PHRASE_TYPE      | G_DECLNAME,
  /*1016*/ PHRASE_TYPE      | G_S,

// P<control> = ...;
  /*1017*/ COUNT_OF_ALTS    | 0x000001,
  /*1018*/ COUNT_OF_PHRASES | 0x000003,
  /*1019*/ KEYWORD_TYPE     | WHITESPACE_ALLOWED | 0x00003d,  /* control */
  /*1020*/ PHRASE_TYPE      | G_CONST,
  /*1021*/ PHRASE_TYPE      | G_S,

// P<PSEMI> = ...;
  /*1022*/ COUNT_OF_ALTS    | 0x000001,
  /*1023*/ COUNT_OF_PHRASES | 0x000000,

// P<STATEMENT> = ...;
  /*1024*/ COUNT_OF_ALTS    | 0x000017,
  /*1025*/ COUNT_OF_PHRASES | 0x000001,
  /*1026*/ PHRASE_TYPE      | G_Labels,
  /*1027*/ COUNT_OF_PHRASES | 0x000001,
  /*1028*/ PHRASE_TYPE      | G_Unconditional_Instructions,
  /*1029*/ COUNT_OF_PHRASES | 0x000002,
  /*1030*/ PHRASE_TYPE      | G_Comment,
  /*1031*/ PHRASE_TYPE      | G_S,
  /*1032*/ COUNT_OF_PHRASES | 0x000001,
  /*1033*/ PHRASE_TYPE      | G_If_or_Unless,
  /*1034*/ COUNT_OF_PHRASES | 0x000001,
  /*1035*/ PHRASE_TYPE      | G_start_of_cycle,
  /*1036*/ COUNT_OF_PHRASES | 0x000001,
  /*1037*/ PHRASE_TYPE      | G_end_of_cycle,
  /*1038*/ COUNT_OF_PHRASES | 0x000001,
  /*1039*/ PHRASE_TYPE      | G_regular_declaration,
  /*1040*/ COUNT_OF_PHRASES | 0x000001,
  /*1041*/ PHRASE_TYPE      | G_various_ends,
  /*1042*/ COUNT_OF_PHRASES | 0x000001,
  /*1043*/ PHRASE_TYPE      | G_record_format_declaration,
  /*1044*/ COUNT_OF_PHRASES | 0x000001,
  /*1045*/ PHRASE_TYPE      | G_proc_declaration,
  /*1046*/ COUNT_OF_PHRASES | 0x000001,
  /*1047*/ PHRASE_TYPE      | G_own_or_external_declaration,
  /*1048*/ COUNT_OF_PHRASES | 0x000001,
  /*1049*/ PHRASE_TYPE      | G_include_file,
  /*1050*/ COUNT_OF_PHRASES | 0x000001,
  /*1051*/ PHRASE_TYPE      | G_begin_block,
  /*1052*/ COUNT_OF_PHRASES | 0x000001,
  /*1053*/ PHRASE_TYPE      | G_on_event_block,
  /*1054*/ COUNT_OF_PHRASES | 0x000001,
  /*1055*/ PHRASE_TYPE      | G_switch_declaration,
  /*1056*/ COUNT_OF_PHRASES | 0x000001,
  /*1057*/ PHRASE_TYPE      | G_list_on,
  /*1058*/ COUNT_OF_PHRASES | 0x000001,
  /*1059*/ PHRASE_TYPE      | G_else,
  /*1060*/ COUNT_OF_PHRASES | 0x000001,
  /*1061*/ PHRASE_TYPE      | G_finish_opt_else,
  /*1062*/ COUNT_OF_PHRASES | 0x000002,
  /*1063*/ PHRASE_TYPE      | G_embedded_assembler,
  /*1064*/ PHRASE_TYPE      | G_PSEMI,
  /*1065*/ COUNT_OF_PHRASES | 0x000002,
  /*1066*/ PHRASE_TYPE      | G_trusted,
  /*1067*/ PHRASE_TYPE      | G_PSEMI,
  /*1068*/ COUNT_OF_PHRASES | 0x000002,
  /*1069*/ PHRASE_TYPE      | G_mainep,
  /*1070*/ PHRASE_TYPE      | G_PSEMI,
  /*1071*/ COUNT_OF_PHRASES | 0x000002,
  /*1072*/ PHRASE_TYPE      | G_control,
  /*1073*/ PHRASE_TYPE      | G_PSEMI,
  /*1074*/ COUNT_OF_PHRASES | 0x000001,
  /*1075*/ PHRASE_TYPE      | G_S,
};

#ifdef INITCODE


#define compile(P,d) compile_inner(P,d,__FILE__,__LINE__)
int compile_inner(int Ph, int depth, const char *file, const int line);

  typedef enum AST_CODE {
    AST_LVALUE = NUM_GRAMMAR+1,        // VarDeclIDX - variable, name, map call
    AST_RVALUE,                        // VarDeclIDX - variable, fn call, etc
    AST_EXPRESSION,                    // EXPR - replacement for P<EXPR> after applying precedence
    AST_TYPE_INFORMATION,              // TypeDeclIDX inferred type of expressions, constructed bottom-up by inference (eg int * real => real)
    AST_USER_PARENS,                   // EXPR  -- for generating C source with included user brackets.
    AST_BINARY_ARITHMETIC_OPERATION,   // OP, LEFT, RIGHT
    AST_UNARY_ARITHMETIC_OPERATION,    // OP, ARG
    AST_ASSIGN,                        // OP, LEFT, RIGHT
    AST_PROC_CALL,                     // PROC, FPP_LIST, APP_LIST
    AST_ARRAYACCESS,                   // ARRAY, DIM_LIST, APP_LIST
    AST_BINOP,                         // OP (str), OP (code)
    AST_MONOP,                         // OP (str), OP (code)
    AST_ASSOP,                         // OP (str), OP (code)
    AST_LAST_OP // Do NOT add any after this item.
  } AST_CODE;

  // /home/gtoal/src/compilers101/new-parser/imps/tests/progs/imp80pass2.i
  //%const %byte %integer %array PRECEDENCE(0:20)=0,3,3,4,5,5,4,3,3,4,4,5,5,3,5,5,
  //                                              0(3),3,5
  
  //%const %byte %integer %array OPVAL(0:20)=0,ADD,SUB,ANDL,IEXP,REXP,MULT,NONEQ,
  //                  ORL,INTDIV,REALDIV,RSHIFT,LSHIFT,ADD,IEXP,REXP,0(3),LNEG,NOTL
                                
  typedef enum Oper {
    OP_NONE=0,
    OP_ADD,
    OP_SUB,
    OP_AND,
    OP_IEXP,
    OP_REXP,
    OP_MULT,
    OP_EOR,
    OP_OR,
    OP_INTDIV,
    OP_REALDIV,
    OP_RSHIFT,
    OP_LSHIFT,
    OP_CONCAT,
    OP_NEG,
    OP_NOT,
    OP_POS,
    OP_LPAREN,
    OP_RPAREN,

    // not added to table.  May not need to as we are not handling assignments using TORP.
    OP_ASSIGN_ADDR,
    OP_ASSIGN_VALUE,
    OP_JAM_TRANSFER,
    OP_UNCOND_STR_RESOL,

    // Not even thinking about handling conditionals with TORP at this point.
    OP_BOOLAND,
    OP_BOOLOR,
    OP_BOOLNOT,
  } Oper;
  
  typedef enum Assoc {
    Left=1, Right
  } Assoc;
  
  typedef struct Torpedo {
    Oper Op;
    int Prec;
    int Assoc;
    int Arity;
    char *C_left, *C_mid, *C_right;
    int C_prec;
    wchar_t *Sym; // Debugging info only
  } Torpedo;

  // atoms should get C_prec of either 11 or 0. I'm not sure which yet.
  // C precedences taken from https://en.cppreference.com/w/c/language/operator_precedence
  // Note I carelessly numbered IMP precedences as 0 -> lowest and 6 -> highest,
  // but C precedences as 11 -> lowest and 0 -> highest!  Needs to be fixed.  Fortunately
  // they're handled separately so the mistake never manifests.

  #define ATOMPRIO 0

  const Torpedo OpDetails [] = {
    { OP_NONE,     0,   Left, 0, "", "*BADOP*", "",       ATOMPRIO, L"*ERROR*"    }, // (I always prefer to keep 0 free to catch unassigned errors)
    { OP_ADD,      3,   Left, 2, "", " + ", "",                  4, L"OP_ADD"     }, // "+"
    { OP_SUB,      3,   Left, 2, "", " - ", "",                  4, L"OP_SUB"     }, // "-"
    { OP_AND,      4,   Left, 2, "", " & ", "",                  8, L"OP_AND"     }, // "&"
    { OP_IEXP,     5,  Right, 2, "IEXP(", ", ", ")",      ATOMPRIO, L"OP_IEXP"    }, // "****" or "\\".  \\ is the Imp77 preferred operator.  Right associative.
    { OP_REXP,     5,  Right, 2, "REXP(", ", ", ")",      ATOMPRIO, L"OP_REXP"    }, // "**" or "\"      \  in Imp77
    { OP_MULT,     4,   Left, 2, "", " * ", "",                  3, L"OP_MULT"    }, // "*"
    { OP_EOR,      3,   Left, 2, "", " ^ ", "",                  9, L"OP_EOR"     }, // "!!"
    { OP_OR,       3,   Left, 2, "", " | ", "",                 10, L"OP_OR"      }, // "!" or "|"  (suprisingly '|' is also allowed for comments! ))
    { OP_INTDIV,   4,   Left, 2, "", " / ", "",                  3, L"OP_INTDIV"  }, // "//"
    { OP_REALDIV,  4,   Left, 2, "", " / ", "",                  3, L"OP_REALDIV" }, // "/"
    { OP_RSHIFT,   5,   Left, 2, /*"(unsigned)"*/"", " >> ", "", 5, L"OP_RSHIFT"  }, // ">>"    // UNSIGNED needs a size - char/short/int/long/long long
    { OP_LSHIFT,   5,   Left, 2, "", " << ", "",                 5, L"OP_LSHIFT"  }, // "<<"
    { OP_CONCAT,   5,   Left, 2, "", ".", "",                    1, L"OP_CONCAT"  }, // "."  // The only string operator.  All others are invalid. So prio is irrelevant.
    { OP_NEG,      3,   Left, 1, "", "-", "",                    2, L"OP_NEG"     }, // "-"  // Precedence of '-' is surprisingly low, and responsible for the -1>>1 inanity.
    { OP_NOT,      6,   Left, 1, "", "~", "",                    2, L"OP_NOT"     }, // "\" or "~"
    { OP_POS,      6,   Left, 1, "", "+", "",                    2, L"OP_POS"     }, // "+"
    { OP_LPAREN,   0,   Left, 0, "(", "", "",             ATOMPRIO, L"OP_LPAREN"  }, // "("  // '(' and ')' do not survive as far as an ExPop() call.
    { OP_RPAREN,   0,  Right, 0, ")", "", "",             ATOMPRIO, L"OP_RPAREN"  }, // ")"
    // Note: Imp Modulus (really Absolute value) (originally !expr! and later |expr| ) is not supported in Imp80, and replaced by MOD() or IMOD().
    // The C operator '%' (Modulo) is a perm call in Imp77: REM(a,b).
  };
  
  typedef struct Op_or_Data {
    char type; // 'O' or 'D' (we'll distinguish between 'C' or 'V' later - constant or variable)
    int idx;   // Torpedo or AST index depending on type above.
  } Op_or_Data;
  
  
  typedef struct ast_lvalue                        {
    int atom; // variable, map, name
  } ast_lvalue;
  
  typedef struct ast_rvalue                        {
    int atom; // variable, fn, proc, const etc - effectively an operand. but not an expr.
  } ast_rvalue;
  
  typedef struct ast_expression                    {
    int whatever;
  } ast_expression;
  
  typedef struct ast_type_information              {
    int blah;
  } ast_type_information;
  
  typedef struct ast_user_parens                   {
    int Expr;
  } ast_user_parens;
  
  typedef struct ast_binary_arithmetic_operation   {
    Oper binop;
    int left, right;
  } ast_binary_arithmetic_operation;
  
  typedef struct ast_unary_arithmetic_operation    {
    Oper monop;
    int arg;
  } ast_unary_arithmetic_operation;

  typedef struct ast_assign   {
    Oper assop;
    int LHS, RHS;
  } ast_assign;
  
  typedef struct ast_proc_call   {
    int Proc, Types, Args;
  } ast_proc_call;
  
  typedef struct ast_array_access   {
    int Array, Dims, Indices;
  } ast_array_access;
  
  typedef struct ast_binop   {
    int OpStr;
    Oper OpCode;
  } ast_binop;
  
  typedef struct ast_monop   {
    int OpStr;
    Oper OpCode;
  } ast_monop;
  
  typedef struct ast_assop   {
    int OpStr;
    Oper OpCode;
  } ast_assop;
  
  // Rough draft
  // Although the AST is a simple array of ints, it's cleaner if we overlay a struct over the ints
  // when accessing tuples, so that we don't have to remember offsets into the AST fields, which
  // from previous experience with the last imptoc was the cause of several coding errors.
  typedef struct AST_struct {
    AST_CODE                            ast_code;  // reserved field
    int                                 op;
    int                                 alt;
    int                                 phrases;
    int                                 Hidden_fields[TUPLE_RESULT_FIELDS];
    union {                             // (anonymous unions are a gcc extension)
      ast_lvalue                        lvalue;
      ast_rvalue                        rvalue;
      ast_expression                    expression;
      ast_type_information              type_information;
      ast_user_parens                   user_parens;
      ast_binary_arithmetic_operation   binary_arithmetic_operation;
      ast_unary_arithmetic_operation    unary_arithmetic_operation;
      ast_assign                        assign;
      ast_proc_call                     proc_call;
      ast_array_access                  array_access;
    };
  } AST_struct;

  // rather than have an awkward new syntax such as %prim (23) %routine BLAH, I'll use a parallel list of names
  // as a lookup table to an index, and enums to index a switch table
  static const char *prim[] = {
    "**BADPRIM**",
    "SELECTINPUT",
    "SELECTOUTPUT",
    "NEWLINE",
    "SPACE",
    "SKIPSYMBOL",
    "READSTRING",
    "NEWLINES",
    "SPACES",
    "NEXTSYMBOL",
    "PRINTSYMBOL",
    "READSYMBOL",
    "READ",
    "WRITE",
    "NEWPAGE",
    "ADDR",
    "ARCSIN",
    "INT",
    "INTPT",
    "FRACPT",
    "PRINT",
    "PRINTFL",
    "REAL",
    "INTEGER",
    "MOD",
    "ARCCOS",
    "SQRT",
    "LOG",
    "SIN",
    "COS",
    "TAN",
    "EXP",
    "CLOSESTREAM",
    "BYTEINTEGER",
    "EVENTINF",
    "RADIUS",
    "ARCTAN",
    "LENGTH",
    "PRINTSTRING",
    "NL",
    "LONGREAL",
    "PRINTCH",
    "READCH",
    "STRING",
    "READITEM",
    "NEXTITEM",
    "CHARNO",
    "TOSTRING",
    "SUBSTRING",
    "RECORD",
    "ARRAY",
    "SIZEOF",
    "IMOD",
    "PI",
    "EVENTLINE",
    "LONGINTEGER",
    "LONGLONGREAL",
    "LENGTHENI",
    "LENGTHENR",
    "SHORTENI",
    "SHORTENR",
    "NEXTCH",
    "HALFINTEGER",
    "PPROFILE",
    "FLOAT",
    "LINT",
    "LINTPT",
    "SHORTINTEGER",
    "TRUNC",
  };

  typedef enum IMP_PRIM {
    PRIM_SELECTINPUT = 1,
    PRIM_SELECTOUTPUT,
    PRIM_NEWLINE,
    PRIM_SPACE,
    PRIM_SKIPSYMBOL,
    PRIM_READSTRING,
    PRIM_NEWLINES,
    PRIM_SPACES,
    PRIM_NEXTSYMBOL,
    PRIM_PRINTSYMBOL,
    PRIM_READSYMBOL,
    PRIM_READ,
    PRIM_WRITE,
    PRIM_NEWPAGE,
    PRIM_ADDR,
    PRIM_ARCSIN,
    PRIM_INT,
    PRIM_INTPT,
    PRIM_FRACPT,
    PRIM_PRINT,
    PRIM_PRINTFL,
    PRIM_REAL,
    PRIM_INTEGER,
    PRIM_MOD,
    PRIM_ARCCOS,
    PRIM_SQRT,
    PRIM_LOG,
    PRIM_SIN,
    PRIM_COS,
    PRIM_TAN,
    PRIM_EXP,
    PRIM_CLOSESTREAM,
    PRIM_BYTEINTEGER,
    PRIM_EVENTINF,
    PRIM_RADIUS,
    PRIM_ARCTAN,
    PRIM_LENGTH,
    PRIM_PRINTSTRING,
    PRIM_NL,
    PRIM_LONGREAL,
    PRIM_PRINTCH,
    PRIM_READCH,
    PRIM_STRING,
    PRIM_READITEM,
    PRIM_NEXTITEM,
    PRIM_CHARNO,
    PRIM_TOSTRING,
    PRIM_SUBSTRING,
    PRIM_RECORD,
    PRIM_ARRAY,
    PRIM_SIZEOF,
    PRIM_IMOD,
    PRIM_PI,
    PRIM_EVENTLINE,
    PRIM_LONGINTEGER,
    PRIM_LONGLONGREAL,
    PRIM_LENGTHENI,
    PRIM_LENGTHENR,
    PRIM_SHORTENI,
    PRIM_SHORTENR,
    PRIM_NEXTCH,
    PRIM_HALFINTEGER,
    PRIM_PPROFILE,
    PRIM_FLOAT,
    PRIM_LINT,
    PRIM_LINTPT,
    PRIM_SHORTINTEGER,
    PRIM_TRUNC,
  } IMP_PRIM;

  // By the way, the EMAS3 "IOPT" Imp80 compiler is at http://www.gtoal.com/history.dcs.ed.ac.uk/archive/os/emas/emas2/compilers/imputils/trimp
  // (see https://history.dcs.ed.ac.uk/archive/os/emas/emas3/docs/ioptnotes.html for differences from EMAS2 Imp80
  // and also https://www.ancientgeek.org.uk/EMAS/ERCC_User_Notes/ERCC_User_Note_058.pdf )
  // Although this code is mostly following Peter Stephens Imp to C code which is based on the same EMAS2 Imp80
  // that Bob Eager's Imp80 implements.
  
  // In the ERCC compiler, these built-in procedures are all implemented by the compiler itself rather than as externals.
  // It will be easier to just parse them in source form than to pre-build a data structure with the declaration info.

  static const char *Prims[69 /*0:68*/] = {
    "**BADPRIM**",
    "%prim %routine %spec SELECT INPUT(%integer STREAM)",
    "%prim %routine %spec SELECT OUTPUT(%integer STREAM)",
    "%prim %routine %spec NEWLINE",
    "%prim %routine %spec SPACE",
    "%prim %routine %spec SKIP SYMBOL",
    "%prim %routine %spec READ STRING(%string %name S)",
    "%prim %routine %spec NEWLINES(%integer N)",
    "%prim %routine %spec SPACES(%integer N)",
    "%prim %integer %fn %spec NEXT SYMBOL",
    "%prim %routine %spec PRINT SYMBOL(%integer SYMBOL)",
    "%prim %routine %spec READ SYMBOL(%name SYMBOL)",
    "%prim %routine %spec READ(%name NUMBER)",
    "%prim %routine %spec WRITE(%integer VALUE,PLACES)",
    "%prim %routine %spec NEWPAGE",
    "%prim %integer %fn %spec ADDR(%name VARIABLE)",
    "%prim %long %real %fn %spec ARCSIN(%long %real X)",
    "%prim %integer %fn %spec INT(%long %real X)",
    "%prim %integer %fn %spec INTPT(%long %real X)",
    "%prim %long %real %fn %spec FRACPT(%long %real X)",
    "%prim %routine %spec PRINT(%long %real NUMBER,%integer BEFORE,AFTER)",
    "%prim %routine %spec PRINTFL(%long %real NUMBER,%integer PLACES)",
    "%prim %real %map %spec REAL(%integer VAR ADDR)",
    "%prim %integer %map %spec INTEGER(%integer VAR ADDR)",
    "%prim %long %real %fn %spec MOD(%long %real X)",
    "%prim %long %real %fn %spec ARCCOS(%long %real X)",
    "%prim %long %real %fn %spec SQRT(%long %real X)",
    "%prim %long %real %fn %spec LOG(%long %real X)",
    "%prim %long %real %fn %spec SIN(%long %real X)",
    "%prim %long %real %fn %spec COS(%long %real X)",
    "%prim %long %real %fn %spec TAN(%long %real X)",
    "%prim %long %real %fn %spec EXP(%long %real X)",
    "%prim %routine %spec CLOSE STREAM(%integer STREAM)",
    "%prim %byte %integer %map %spec BYTE INTEGER(%integer VAR ADDR)",
    "%prim %integer %fn %spec EVENTINF",
    "%prim %long %real %fn %spec RADIUS(%long %real X,Y)",
    "%prim %long %real %fn %spec ARCTAN(%long %real X,Y)",
    "%prim %byte %integer %map %spec LENGTH(%string %name  S)",
    "%prim %routine %spec PRINT STRING(%string(255) STR)",
    "%prim %integer %fn %spec NL",
    "%prim %long %real %map %spec LONG REAL(%integer VAR ADDR)",
    "%prim %routine %spec PRINT CH(%integer CHARACTER)",
    "%prim %routine %spec READ CH(%name CHARACTER)",
    "%prim %string %map %spec STRING(%integer VAR ADDR)",
    "%prim %routine %spec READ ITEM(%string %name ITEM)",
    "%prim %string (1) %fn %spec NEXT ITEM",
    "%prim %byte %integer %map %spec CHARNO(%string %name STR,%integer CHAR REQD)",
    "%prim %string (1) %fn %spec TO STRING(%integer ch)",
    "%prim %string (255) %fn %spec SUB STRING(%string(255) STR, %integer FIRST, LAST)",
    "%prim %record (*) %map %spec RECORD(%integer REC ADDR)",
    "%prim %array %map %spec ARRAY(%integer A1ADDR,%array %name FORMAT)",
    "%prim %integer %fn %spec SIZEOF(%name X)",
    "%prim %integer %fn %spec IMOD(%integer VALUE)",
    "%prim %long %real %fn %spec PI",
    "%prim %integer %fn %spec EVENTLINE",
    "%prim %long %integer %map %spec LONGINTEGER(%integer ADR)",
    "%prim %long %long %real %map %spec LONGLONGREAL(%integer ADR)",
    "%prim %long %integer %fn %spec LENGTHENI(%integer VAL)",
    "%prim %long %long %real %fn %spec LENGTHENR(%long %real VAL)",
    "%prim %integer %fn %spec SHORTENI(%long %integer VAL)",
    "%prim %long %real %fn %spec SHORTENR(%long %long %real VAL)",
    "%prim %integer %fn %spec NEXTCH",
    "%prim %half %integer %map %spec HALFINTEGER(%integer ADDR)",
    "%prim %routine %spec PPROFILE",
    "%prim %long %real %fn %spec FLOAT(%integer VALUE)",
    "%prim %long %integer %fn %spec LINT(%long %long %real X)",
    "%prim %long %integer %fn %spec LINTPT(%long %long %real X)",
    "%prim %short %integer %map %spec SHORTINTEGER(%integer N)",
    "%prim %integer %fn %spec TRUNC(%long %real X)",
  };

  // For diagnostics:
  static char *TypeName[32] = {
    // CST
    "*ERROR(0)*", "CST:BIP_TYPE", "CST:PHRASE_TYPE", "CST:SEMANTIC_TYPE", "CST:KEYWORD_TYPE",
    "CST:CHAR_TYPE", "CST:UTF32CHAR_TYPE", "CST:STRING_TYPE", "CST:UTF32STRING_TYPE",
    "CST:REGEXP_TYPE", "CST:OPTION_TYPE", "CST:COUNT_OF_ALTS", "CST:COUNT_OF_PHRASES",
    "CST:ALT_NUMBER", "*ERROR(14)*", "*ERROR(15)*",
    // AST
    "AST:BIP", "AST:PHRASE", "AST:LITERAL", "*ERROR(19)*",
    "*ERROR(20)*", "*ERROR(21)*", "*ERROR(22)*", "*ERROR(23)*",
    "*ERROR(24)*", "*ERROR(25)*", "*ERROR(26)*", "*ERROR(27)*",
    "*ERROR(28)*", "*ERROR(29)*", "*ERROR(30)*", "*ERROR(31)*",
  };


  // TO DO: WE NEED A PROPER DECODE PROCEDURE THAT WORKS OUT ALL TYPES OF PHRASE
  
  wchar_t *Decode(int Ph) {
    static wchar_t tmp[512];
    swprintf(tmp, 511, L"%s", TypeName[(Ph>>AST_type_shift)&AST_type_mask]);
    return tmp;
  }

  // Stringpool helpers

  STRING wstrtopool(wchar_t *wstr) {
    STRING result = Stringpool_nextfree;
    for (;;) {
      wchar_t wch = *wstr++;
      _Stringpool(Stringpool_nextfree++) = wch;
      if (wch == '\0') break;
    }
    return (STRING_TYPE << GRAMMAR_TYPE_SHIFT) | result; // or CHAR_TYPE?
  }

  wchar_t *pooltowstr(STRING p) {
    if (P_AST_type(p) != 0 && P_AST_type(p) != STRING_TYPE && P_AST_type(p) != AST_LITERAL) {
      fprintf(stderr, "* Error: bad string access: %ls\n", Decode(p));
    }
    p = p & AST_idx_mask;
    return &Stringpool(p);
  }
  
  void PrintTag(int Literal) {
    int i;
    int P_      = Literal&INDEX_MASK;
    unsigned int type    = Literal>>AST_type_shift;
    if ((Literal!=P_) && ((type<<AST_type_shift) != AST_LITERAL)) {
      fprintf(stderr, "* Internal error: Expected a Tag (stored as a literal - type 3) but got type %d.  Tag was:", type);
      for (i = atom(Literal).start; i < atom(Literal).end; i++)
        fprintf(stderr, "%lc", source(i).ch);
    }
    for (i = atom(Literal).start; i < atom(Literal).end; i++)
      fprintf(stdout, "%lc", source(i).ch);
  }

  // Tag2Str is a short term expedient.  Most of the places where it is used
  // so far should be extracting the canonical "C" variable name corresponding
  // to the Imp variable, which may have leading spaces and perhaps even
  // embedded spaces or {} comments!  For now just a quick hack to remove
  // spaces.
  char *Tag2Str(int Literal) {
    int i, idx, len;
    char c;
    int P_      = Literal&INDEX_MASK;
    unsigned int type    = PhraseType(Literal);
    len = atom(P_).end-atom(P_).start;
    //fprintf(stderr, "{len=%d}", len);
    char Str[len+1];

    idx = 0; i = atom(P_).start;
    for (;;) {
      if (i-atom(P_).start == len) break;
      c = (char)(source(i).ch & 255); // temp hack, not unicode.
      if (c != ' ') {
        Str[idx] = c; Str[idx+1] = '\0';
        idx += 1;
      }
      i++;
    }

    if ((Literal!=P_) && ((type<<AST_type_shift) != AST_LITERAL)) {
      fprintf(stderr, "* Internal error: Expected a Tag (stored as a literal - type 3) but got type %d.  Tag was \"%s\"\n", type, Str);
    }
    return strdup(Str); // :-@
  }
  wchar_t *Tag2WStr(int Literal) {
    int i, idx, len;
    int P_      = Literal&INDEX_MASK;
    unsigned int type    = PhraseType(Literal);
    //fprintf(stderr, "{0: type    = PhraseType(Literal) = %08x}", type);
    len = atom(P_).end-atom(P_).start;
    //fprintf(stderr, "{A: wchar_t WStr[len=%d+1]}", len);
    wchar_t wc, WStr[len+1];
    idx = 0; i = atom(P_).start;
    for (;;) {
      if (i-atom(P_).start == len) break;
      //fprintf(stderr, "{WStr[idx=%d] = source(i=%d).ch = %d ('%lc')}", idx, i, source(i).ch, source(i).ch);
      wc = source(i).ch;
      if (wc != L' ') {
        WStr[idx] = wc; WStr[idx] = '\0';
        idx += 1;
      }
      i++;
    }
    //fprintf(stderr, "{B:WStr[len=%d] = '\\0'}", len);
    //fprintf(stderr, "{C: done.}");
    if ((Literal!=P_) && ((type<<AST_type_shift) != AST_LITERAL)) {
      //                   ^^^^^^^^^^^^^^^^^^^^ can cause overflow if type is not unsigned!  There may be more like this to be found.
      fprintf(stderr, "* Internal error: Expected a Tag (stored as a literal - type 3) but got type %d.  Tag was \"%ls\"\n", type, WStr);
    }
    //fprintf(stderr, "{D: wchar_t *rslt = wcsdup(WStr)}");
    //fprintf(stderr, "{E: WStr=\"%ls\"}", WStr);
    wchar_t *rslt = wcsdup(WStr); // :-@
    if (rslt == NULL) {
      //fprintf(stderr, "{F1: return NULL}");
    } else {
      //fprintf(stderr, "{F2: return \"%ls\"}", rslt);
    }
    return rslt;
  }
  STRING Str2Pool(char *s) {
    int p = Stringpool_nextfree;
    for (;;) {
      char c = *s++;
      _Stringpool(Stringpool_nextfree++) = c;
      if (c == '\0') break;
    }
    return p;
  }


  // SCOPE MANAGEMENT:


  #include "symtab.h"

  static int DOWN_flag = 0;

  typedef enum CTRL_STACK_ENUM {
    FINISHELSE = 0,
    FINISH,
    END,
    ENDOFPROGRAM,
    ELSE,
    REPEAT,
    REPEATUNTIL
  } CTRL_STACK_ENUM;

  const char *ctrl_debug[] = {"FINISHELSE", "FINISH", "END", "ENDOFPROGRAM", "ELSE", "REPEAT", "REPEATUNTIL", "bug"};

  // These are set in <init>
  static int debug_ctrl_stack = 0;
  static int debug_compiler = 0;
  static int debug_declarations = 0;

  DECLARE(CTRL_STACK, CTRL_STACK_ENUM, 32);
  int CTRL_STACK_nextfree = 0;
  $define _CTRL_STACK[x] WRITE(x, CTRL_STACK, CTRL_STACK_ENUM)
  $define  CTRL_STACK[x]  READ(x, CTRL_STACK, CTRL_STACK_ENUM)

  int ctrl_depth(void) {
    if (debug_ctrl_stack) {
      int i = CTRL_STACK_nextfree;
      fprintf(stderr, "Control stack: "); while (--i >= 0) fprintf(stderr, " %s", ctrl_debug[CTRL_STACK[i]]); fprintf(stderr, "\n");
    }
    return CTRL_STACK_nextfree;
  }
  
  void push_ctrl(int Code) {
    if (debug_ctrl_stack) {
      int i = CTRL_STACK_nextfree;
      fprintf(stderr, "Control stack before push: "); while (--i >= 0) fprintf(stderr, " %s", ctrl_debug[CTRL_STACK[i]]); fprintf(stderr, "\n");
    }
    _CTRL_STACK[CTRL_STACK_nextfree++] = Code;
    if (debug_ctrl_stack) {
      int i = CTRL_STACK_nextfree;
      fprintf(stderr, "Control stack after push: "); while (--i >= 0) fprintf(stderr, " %s", ctrl_debug[CTRL_STACK[i]]); fprintf(stderr, "\n");
    }
  }

  #define  pop_ctrl()  pop_ctrl_inner(__LINE__,__FILE__)
  int pop_ctrl_inner(int line, char *file) {
    if (CTRL_STACK_nextfree == 0) {
      fprintf(stderr, "* Control stack empty.  Internal coding error. (detected at %s:%d)\n", file,line);
      exit(1);
    }
    if (debug_ctrl_stack) {
      int i = CTRL_STACK_nextfree;
      fprintf(stderr, "Control stack before pop: "); while (--i >= 0) fprintf(stderr, " %s", ctrl_debug[CTRL_STACK[i]]); fprintf(stderr, "\n");
    }
    if (debug_ctrl_stack) {
      int i = CTRL_STACK_nextfree-1;
      fprintf(stderr, "Control stack after pop: "); while (--i >= 0) fprintf(stderr, " %s", ctrl_debug[CTRL_STACK[i]]); fprintf(stderr, "\n");
    }
    return CTRL_STACK[--CTRL_STACK_nextfree];
  }


  // NAME TABLES

  // formal parameters, and record formats (maybe array formats too) need to suppress current <NAME> handling.
  // Otherwise, declarations are looking pretty good!


  // Inline sections like this are copied through to the global declarations in the main program.
  // If you want to *execute* code at startup, put it in the <init> phrase at the start of P<SS>
  typedef enum OBJECT {
    UNINIT_OBJECT=0, CODE, VAR, RECORDFORMAT, ARRAYFORMAT, SWITCHDEFN, LABELDEFN
  } OBJECT;
  const char *Object_name[] = {"**BADOBJ**", "CODE", "VAR", "RECORDFORMAT", "ARRAYFORMAT", "SWITCHDEFN", "LABELDEFN"};
  OBJECT Object;

  typedef enum BASETYPE {
    UNINIT_BASETYPE=0, INTEGER, FLOAT, STRINGTYPE, RECORD, PROCADDR, GENERIC /*%name*/, SWITCHLABEL, JUMPLABEL
  } BASETYPE;
  const char *Basetype_name[] = {"**BADTYPE**", "INTEGER", "FLOAT", "STRINGTYPE", "RECORD", "PROCADDR", "GENERIC", "SWITCHLABEL", "JUMPLABEL"};
  BASETYPE Basetype;

  typedef enum SIGNEDNESS {
    UNINIT_SIGNEDNESS=0, SIGNED, UNSIGNED
  } SIGNEDNESS;
  const char *Signedness_name[] = {"**BADSIGN**", "SIGNED", "UNSIGNED"};
  SIGNEDNESS Signedness;

  typedef enum PRECISION {
    UNINIT_PRECISION=0, COMPOUND, BYTE, SHORT, WORD, LONGWORD, QUADWORD, ADDR
  } PRECISION;
  const char *Precision_name[] = {"**BADPREC**", "COMPOUND", "BYTE", "SHORT", "WORD", "LONGWORD", "QUADWORD", "ADDR"};
  PRECISION Precision;

  typedef enum PROC {
    UNINIT_PROC=0, NONE, ROUTINE, FN, MAP
  } PROC;
  const char *Proc_name[] = {"**BADPROC**", "NONE", "ROUTINE", "FN", "MAP"};
  PROC Proc;

  typedef enum AN_N {
    UNINIT_AN_N=0, NO_NAME, ARRAYNAME, OBJECTNAME
  } AN_N;
  const char *NameInfo_name[] = {"**BADNAME**", "NO_NAME", "ARRAYNAME", "OBJECTNAME"};
  AN_N NameInfo;
  
  //typedef enum ISFORMAT {
  //  UNINIT_ISFORMAT=0, NO_FORMAT, IS_FORMAT
   //} ISFORMAT;
  //const char *IsFormat_name[] = {"**BADFORM**", "NO_FORMAT", "IS_FORMAT"};
  //ISFORMAT IsFormat;

  typedef enum SPECQ {
    UNINIT_SPEC=0, NO_SPEC, SPEC
  } SPECQ;
  const char *Spec_name[] = {"**BADSPEC**", "NO_SPEC", "SPEC"};
  SPECQ Spec;

  typedef enum ISARRAY {
    UNINIT_ISARRAY=0, SCALAR, ARRAY
  } ISARRAY;
  const char *IsArray_name[] = {"**BADARRAY**", "SCALAR", "ARRAY"};
  ISARRAY IsArray;
  
  typedef enum AREA {
    UNINIT_AREA=0, OWN, EXTDATA, CONSTANT, STACK, PARAMETER  // extrinsic is an implied %spec
  } AREA;
  const char *Area_name[] = {"**BADAREA**", "OWN", "EXTDATA", "CONSTANT", "STACK", "PARAMETER"};
  AREA Area;

  typedef enum LINKAGE {
    UNINIT_LINKAGE=0, EXTPROC, SYSTEM, DYNAMIC, PRIM, PERM, AUTO
  } LINKAGE;
  const char *Linkage_name[] = {"**BADLINK**", "EXTPROC", "SYSTEM", "DYNAMIC", "PRIM", "PERM", "AUTO"};
  LINKAGE Linkage;



  // See previous attempt for imp77 at ~/src/compilers101/new-parser/imps/datatypes.h



  // structures are never used directly.  Where you would normally embed a struct,
  // you must put a structIDX which is an integer into a flex array of structs.
  // Using indices rather than pointers is essential to having efficient flex arrays.

  // In structs with flexible numbers of fields, the flex field must come last.
  // None of these objects may contain pointers as the flex.h package is liable
  // to realloc the data on the fly: indexes will always be valid but pointers would not be.
  
  typedef int TypeDeclIDX;      // type information - everything needed to declare and use anything
  typedef int VarDeclIDX;       // A tag and its type information - entered into a scoped symbol table
  
  typedef int BoundIDX;         // one bound (lower or upper)
  typedef int BoundsPairIDX;    // lower and upper bound
  typedef int BoundsIDX;        // array of bounds pairs, one for each dimension

                                // extra info for records, arrays, strings:
  typedef int RecordFormatIDX;
  typedef int ArrayFormatIDX;
  typedef int StringFormatIDX;
  
  typedef int ParamFormatIDX;   // list of parameters to a procedure
  
  typedef int ASTidx;


$ifdef TypeDecl
$undef TypeDecl
$endif

  // OK, here's my next problem: as well as handling declarations on the fly, I want to return the
  // declaration parameters via an AST tuple.  This is fine for most of the items in the struct
  // below, but we may have a problem with the IDX items which point into other arrays.  Those
  // will also have to be managed by AST tuples and added to and removed from in the same order
  // as during parsing.  Right now, generating C on the fly from the CST is looking like the
  // more tempting option, despite some limitations.

  typedef struct TypeDecl {
    OBJECT     Object;
    BASETYPE   Basetype;
    SIGNEDNESS Signedness;
    PRECISION  Precision;
    PROC       Proc;
    AN_N       NameInfo;
    SPECQ      Spec;
    ISARRAY    IsArray;
    AREA       Area;
    LINKAGE    Linkage;
    // for arrays
    ArrayFormatIDX  arrfm;
    // for Rt/Fn/Map parameters:
    ParamFormatIDX  parms;
    // for records, strings, and fn/maps returning same:
    RecordFormatIDX recfm;
    StringFormatIDX strfm;
  } TypeDecl;

  // Note that DECLARE(x) creates x.next_free_index
  // which we could use instead of adding a separate x_nextfree
  // but I would need to add that to the NO_FLEX path as well.
  
  DECLARE(TypeDeclRA, TypeDecl, 10000);
  int TypeDecl_nextfree = 0;
  $define _TypeDecl[x] WRITE(x, TypeDeclRA, TypeDecl)
  $define  TypeDecl[x]  READ(x, TypeDeclRA, TypeDecl)


  typedef struct VarDecl {
    STRING         varname;    // Object name
    STRING         aliasname;  // %alias name or -1
    STRING         c_name;     // mangled for use when outputting C code
    TypeDeclIDX    type;       // or -1
    ArrayFormatIDX aform;      // or -1  // Not sure why I wanted an Array Format field when the TypeDecl has 'arrfm' as well.  Ignoring this one for now.
                                         // Possibly it was: there is a distinction between a declaration of an array format for use with the ARRAY() map,
                                         // and a description of the format of an actual array declaration.  The VarDecl 'aform' is likely for the former,
                                         // and the TypeDecl 'arrfm' for the latter.
  } VarDecl;

  DECLARE(VarDeclRA, VarDecl, 10000);
  int VarDecl_nextfree = 0;
  $define _VarDecl[x] WRITE(x, VarDeclRA, VarDecl)
  $define  VarDecl[x]  READ(x, VarDeclRA, VarDecl)


  typedef enum BOUNDTYPE {
    UNDEFINED_BOUND, CONSTANT_BOUND, VARIABLE_BOUND
  } BOUNDTYPE;

  DECLARE(BoundTypeRA, BOUNDTYPE, 10000);
  int BoundType_nextfree = 0;
  $define _BoundType[x] WRITE(x, BoundTypeRA, BoundType)
  $define  BoundType[x]  READ(x, BoundTypeRA, BoundType)


  typedef struct Bound {
    int type;            // lower or upper or both bounds of one dimension of an array may be
                         // constant, or taken from a variable at the point of declaration,
                         // or unknown. (unknown is an extension for later, for Hamish's 68K Imp)
                         // Some types of array (e.g. in a %record) must have all constant bounds.
                         // Arrays with variable bounds need a dopevector where the initial
                         // bounds can be stored at the point where space for the array is
                         // allocated (most likely using alloca() to mimic Imp's stack)
    ASTidx value;        // Index into the AST where the bound is expressed.
    VarDeclIDX indexvar; // variable used to index the array declaration.  (May not be needed?)
  } Bound;

  DECLARE(BoundRA, BOUNDTYPE, 10000);
  int Bound_nextfree = 0;
  $define _Bound[x] WRITE(x, BoundRA, Bound)
  $define  Bound[x]  READ(x, BoundRA, Bound)


  typedef struct BoundsPairTYPE {
    BoundIDX Lower, Upper;
  } BoundsPairTYPE;

  DECLARE(BoundsPairRA, BoundsPairTYPE, 10000);
  int BoundsPair_nextfree = 0;
  $define _BoundsPair[x] WRITE(x, BoundsPairRA, BoundsPair)
  $define  BoundsPair[x]  READ(x, BoundsPairRA, BoundsPair)


  typedef struct BoundsTYPE {
    int           dimensions;
    BoundsPairIDX Dimension[];
  } BoundsTYPE;

  DECLARE(BoundsRA, BoundsTYPE, 10000);
  int Bounds_nextfree = 0;
  $define _Bounds[x] WRITE(x, BoundsRA, Bounds)
  $define  Bounds[x]  READ(x, BoundsRA, Bounds)


  typedef struct recfmTYPE {
    STRING formatname;   // Record format name
    STRING c_formatname; // Record format name mangled for use when outputting C code
    int fields;          // count of fields
    VarDeclIDX field[];  // (extensible)
  } recfmTYPE;

  DECLARE(recfmRA, recfmTYPE, 10000);
  int recfm_nextfree = 0;
  $define _recfm[x] WRITE(x, recfmRA, recfm)
  $define  recfm[x]  READ(x, recfmRA, recfm)

  
  typedef struct arrfmTYPE {
    STRING formatname;      // Array format name, may be -1 for none
    VarDeclIDX field;       // Base element
    int dims;               // array dimensions
    BoundsPairIDX dim[];    // each dimension or each parameter (extensible)
  } arrfmTYPE;

  DECLARE(arrfmRA, arrfmTYPE, 10000);
  int arrfm_nextfree = 0;
  $define _arrfm[x] WRITE(x, arrfmRA, arrfm)
  $define  arrfm[x]  READ(x, arrfmRA, arrfm)


  // May later extend but until there are languages changes, no need.
  // (changes such as allowing C-style strings as opposed to Imp strings,
  //  or maybe significantly increasing string length, or allowing Unicode)
  typedef struct strfmTYPE {
    int maxlen;             // maximum string length
  } strfmTYPE;

  DECLARE(strfmRA, strfmTYPE, 10000);
  int strfm_nextfree = 0;
  $define _strfm[x] WRITE(x, strfmRA, strfm)
  $define  strfm[x]  READ(x, strfmRA, strfm)

  // Maybe this (and a record definition) ought to use the same data structure as a scoped name table?
  typedef struct paramTYPE {
    int            numparams;
    VarDeclIDX     param[];    // extensible
  } paramTYPE;
  DECLARE(ParamRA, paramTYPE, 10000);
  int Param_nextfree = 0;
  $define _Param[x] WRITE(x, ParamRA, ParamList)
  $define  Param[x]  READ(x, ParamRA, ParamList)  


  void DebugVarIDX(int VarIDX) {
    int VTag = VarDecl[VarIDX].varname;
    int TypeIDX = VarDecl[VarIDX].type;
    char *s = Tag2Str(VTag);
    fprintf(stderr, "Debug VAR: VarIDX %d is %s\n", VarIDX, s);

    fprintf(stderr, "VarDecl[%d].varname   = %d\n", VarIDX, VarDecl[VarIDX].varname);
    fprintf(stderr, "VarDecl[%d].aliasname = %d\n", VarIDX, VarDecl[VarIDX].aliasname);
    fprintf(stderr, "VarDecl[%d].c_name    = %d\n", VarIDX, VarDecl[VarIDX].c_name);
    fprintf(stderr, "VarDecl[%d].type      = %d\n", VarIDX, VarDecl[VarIDX].type);
    fprintf(stderr, "VarDecl[%d].aform     = %d\n", VarIDX, VarDecl[VarIDX].aform);
    fprintf(stderr, "TypeDecl[%d].Object     = %d\n", TypeIDX, TypeDecl[TypeIDX].Object);
    fprintf(stderr, "TypeDecl[%d].Basetype   = %d\n", TypeIDX, TypeDecl[TypeIDX].Basetype);
    fprintf(stderr, "TypeDecl[%d].Signedness = %d\n", TypeIDX, TypeDecl[TypeIDX].Signedness);
    fprintf(stderr, "TypeDecl[%d].Precision  = %d\n", TypeIDX, TypeDecl[TypeIDX].Precision);
    fprintf(stderr, "TypeDecl[%d].Proc       = %d\n", TypeIDX, TypeDecl[TypeIDX].Proc);
    fprintf(stderr, "TypeDecl[%d].NameInfo   = %d\n", TypeIDX, TypeDecl[TypeIDX].NameInfo);
    fprintf(stderr, "TypeDecl[%d].Spec       = %d\n", TypeIDX, TypeDecl[TypeIDX].Spec);
    fprintf(stderr, "TypeDecl[%d].IsArray    = %d\n", TypeIDX, TypeDecl[TypeIDX].IsArray);
    fprintf(stderr, "TypeDecl[%d].Area       = %d\n", TypeIDX, TypeDecl[TypeIDX].Area);
    fprintf(stderr, "TypeDecl[%d].Linkage    = %d\n", TypeIDX, TypeDecl[TypeIDX].Linkage);
    fprintf(stderr, "TypeDecl[%d].arrfm      = %d\n", TypeIDX, TypeDecl[TypeIDX].arrfm);
    fprintf(stderr, "TypeDecl[%d].parms      = %d\n", TypeIDX, TypeDecl[TypeIDX].parms);
    fprintf(stderr, "TypeDecl[%d].recfm      = %d\n", TypeIDX, TypeDecl[TypeIDX].recfm);
    fprintf(stderr, "TypeDecl[%d].strfm      = %d\n", TypeIDX, TypeDecl[TypeIDX].strfm);
  }

#define _textof(x) #x
#define textof(x) _textof(x)
#define Diagnose(IDX) Diagnose_inner(IDX, _textof(IDX), __FILE__, __LINE__)
  void Diagnose_inner(int IDX, char *info, char *file, int line) {
    if (IDX == 0) {
      fprintf(stderr, "Diagnose(0x%08x, \"%s\", \"%s\", %d); // Usually 0 means an implicitly unassigned variable somewhere\n", IDX, info, file, line);
      return;
    } else if (IDX == -1) {
      fprintf(stderr, "Diagnose(0x%08x, \"%s\", \"%s\", %d); // Usually -1 means an explicitly unassigned variable somewhere\n", IDX, info, file, line);
      return;
    } else if (IDX == 0x80808080) {
      fprintf(stderr, "Diagnose(0x%08x, \"%s\", \"%s\", %d); // 0x80808080 means a monitored but unassigned variable\n", IDX, info, file, line);
      return;
    }

    fprintf(stderr, "Diagnose(0x%08x, \"%s\", \"%s\", %d): ", IDX, info, file, line);
    switch (P_AST_type(IDX)) {
    case AST_BIP:
      fprintf(stderr, "AST_BIP"); break;
    case AST_PHRASE:
      {
      fprintf(stderr, "AST_PHRASE stored at AST(%d),", IDX&AST_idx_mask);
      int op = AST((IDX&AST_idx_mask)+1);
      switch (op) {
      case AST_LVALUE: fprintf(stderr, " AST_LVALUE"); break;
      case AST_RVALUE: fprintf(stderr, " AST_RVALUE"); break;
      case AST_EXPRESSION: fprintf(stderr, " AST_EXPRESSION"); break;
      case AST_TYPE_INFORMATION: fprintf(stderr, " AST_TYPE_INFORMATION"); break;
      case AST_USER_PARENS: fprintf(stderr, " AST_USER_PARENS"); break;
      case AST_BINARY_ARITHMETIC_OPERATION: fprintf(stderr, " AST_BINARY_ARITHMETIC_OPERATION"); break;
      case AST_UNARY_ARITHMETIC_OPERATION: fprintf(stderr, " AST_UNARY_ARITHMETIC_OPERATION"); break;
      case AST_ASSIGN: fprintf(stderr, " AST_ASSIGN"); break;
      case AST_PROC_CALL: fprintf(stderr, " AST_PROC_CALL"); break;
      case AST_ARRAYACCESS: fprintf(stderr, " AST_ARRAYACCESS"); break;
      case AST_BINOP: fprintf(stderr, " AST_BINOP"); break;
      case AST_MONOP: fprintf(stderr, " AST_MONOP"); break;
      case AST_ASSOP: fprintf(stderr, " AST_ASSOP"); break;
      default: fprintf(stderr, " Unknown op=%d", op); break;
      }
      fprintf(stderr, "\n");
      }
      break;
    case AST_LITERAL:
      fprintf(stderr, "AST_LITERAL"); break;
    case BIP_TYPE:
      fprintf(stderr, "BIP_TYPE"); break;
    case PHRASE_TYPE:
      {
      extern wchar_t *PHRASE_inner(int G_PhraseStart, char *file, int line);
      int op = P_op(IDX);
      fprintf(stderr, "PHRASE_TYPE:  Phrase@AST(%d)%s%s%s",
              P_AST_index(IDX),
              IDX&NEGATED_PHRASE     ? " Negated":"",
              IDX&GUARD_PHRASE       ? " Guard":"",
              IDX&WHITESPACE_ALLOWED ? " Whitesp":"");
      fprintf(stderr, " Op=%d", op);
      fprintf(stderr, " (G_%ls)", PHRASE_inner(op, file, line));
      fprintf(stderr, "\n");
      }
      return;
    case SEMANTIC_TYPE:
      fprintf(stderr, "SEMANTIC_TYPE"); break;
    case KEYWORD_TYPE:
      fprintf(stderr, "KEYWORD_TYPE"); break;
    case CHAR_TYPE:
      fprintf(stderr, "CHAR_TYPE"); break;
    case UTF32CHAR_TYPE:
      fprintf(stderr, "UTF32CHAR_TYPE"); break;
    case STRING_TYPE:
      fprintf(stderr, "STRING_TYPE"); break;
    case UTF32STRING_TYPE:
      fprintf(stderr, "UTF32STRING_TYPE"); break;
    case REGEXP_TYPE:
      fprintf(stderr, "REGEXP_TYPE"); break;
    case OPTION_TYPE:
      fprintf(stderr, "OPTION_TYPE"); break;
    case COUNT_OF_ALTS:
      fprintf(stderr, "COUNT_OF_ALTS"); break;
    case COUNT_OF_PHRASES:
      fprintf(stderr, "COUNT_OF_PHRASES"); break;
    case ALT_NUMBER:
      fprintf(stderr, "ALT_NUMBER"); break;

    default:
      fprintf(stderr, "Unknown object tag %02x (%s)", ((unsigned)IDX)>>27U, TypeName[(((unsigned)IDX)>>AST_type_shift)&31]); break;
      return;
    }
    
    fprintf(stderr, " Index=%d\n", P_AST_index(IDX));
  } // End of Diagnose()

  // shunting yard algorithm for opperator precedence.  In my previous imptoc
  // I used a precedence grammar.  I'm trying a flat grammar this time with
  // the precedence being added afterwards via Dijkstra's shunting yard algorithm
  // just for the experience (and because that's how the ERCC's grammar was written)

  // The corresponding code in the ERCC compilers is in TORP() in their pass2.
  // I'ld like to say that I learned from their example but it was easier just
  // to write it from first principles (using the description in Wikipedia as
  // a crib).
  
  static int debug_torp = 0;

#define MAX_TORP 1024

  DECLARE(OperStack, Oper, MAX_TORP); // enum acts as an index into the struct array
  #define _OperStack(x)  WRITE(x,OperStack,Oper)
  #define  OperStack(x)   READ(x,OperStack,Oper)
  static int OperStack_nextfree = 0;
  static int OperStack_bottom = 0;
  
  DECLARE(DataStack, Op_or_Data, MAX_TORP);  // a.k.a 'Output' in the description below.
  #define _DataStack(x)  WRITE(x,DataStack,Op_or_Data)
  #define  DataStack(x)   READ(x,DataStack,Op_or_Data)
  static int DataStack_nextfree = 0;
  static int DataStack_bottom = 0;

  static void ShowRP(char *message) {
    int i;
    if (debug_torp == 0) return;
    i = OperStack_nextfree;
    fprintf(stderr, "\n%s\n  OperStack:\n", message);
    if (i == 0) fprintf(stderr, "    <empty>\n"); else
    while (i > 0) {
          Oper y;
          y = OperStack(--i);
          fprintf(stderr, "    %ls\n", OpDetails[y].Sym);
          if (i && i == OperStack_bottom) fprintf(stderr, "    ------------- false bottom\n");
    }
    fprintf(stderr, "  DataStack:\n");
    i = DataStack_nextfree;
    if (i == 0) fprintf(stderr, "    <empty>\n"); else
    while (i > 0) {
          Op_or_Data Item;
          Item = DataStack(--i);
          if (Item.type == 'O') {
            fprintf(stderr, "    %ls\n", OpDetails[Item.idx].Sym);
          } else {
            fprintf(stderr, "    %ls\n", Decode(Item.idx));
          }
          if (i && i == DataStack_bottom) fprintf(stderr, "    ------------- false bottom\n");
    }
    fprintf(stderr, "\n");
  }

  void PushParen(wchar_t *Op) {
    if (debug_torp) fprintf(stderr, "PushParen(%ls)\n", Op);
    // only '(' and ')' for now!
    Oper OPER;
    if (wcscmp(Op, L"(")==0) {
      OPER = OP_LPAREN;
    } else if (wcscmp(Op, L")")==0) {
      OPER = OP_RPAREN;
    } else {
      OPER = OP_NONE; fprintf(stderr, "* Error: PushParen(\"%ls\") unknown\n", Op);
    }
  
    if (OPER == OP_LPAREN) { // 1.3
      /*
        - a left parenthesis (i.e. "("):
            push it onto the operator stack
       */
      _OperStack(OperStack_nextfree++) = OPER;
    } else if (OPER == OP_RPAREN) { // 1.4
      /*
        - a right parenthesis (i.e. ")"):
            while the operator at the top of the operator stack is not a left parenthesis:
                pop the operator from the operator stack into the output queue
            {assert there is a left parenthesis at the top of the operator stack}
            pop the left parenthesis from the operator stack and discard it
       */
      for (;;) {
        OPER = OperStack(--OperStack_nextfree);
        if (OPER == OP_LPAREN) break; // 1.4.2
        _DataStack(DataStack_nextfree++) = (Op_or_Data){'O',OPER}; // 1.4.1
      }
    }
    ShowRP("PushParen:\n");
  }

  void PushMonOp(int P) {
    Oper OPER;
    wchar_t *Ops;
    Ops = pooltowstr(P_P(P,1));

#ifdef NEVER
    if (debug_torp) fprintf(stderr, "PushMonOp(%ls)\n", Decode(P));
    
    if (debug_torp) fprintf(stderr, "PushMonOp: Ops = \"%ls\"\n", Ops);

    if (         wcscmp(Ops, L"\\")==0  ||  wcscmp(Ops, L"~")==0         ) {
      OPER = OP_NOT;
    } else if (wcscmp(Ops, L"-")==0) {
      OPER = OP_NEG;
    } else {
      OPER = OP_NONE;
      fprintf(stderr, "* Error: PushMonOp(\"%ls\") unknown\n", Ops);
    }
#else
    // if (debug_torp) Diagnose(P);
    OPER = P_P(P,2);
#endif

    for (;;) {
      if (OperStack_nextfree == OperStack_bottom) break;
      Oper O2 = OperStack(OperStack_nextfree-1);
      if (O2 == OP_LPAREN) break;
      
      // Not 100% sure this is all valid for monops. Works well for binops.
      // Also somewhat dubious about the precedence levels copied from the ERCC Imp compiler.
      
      if (   (OpDetails[O2].Prec > OpDetails[OPER].Prec)
          || (OpDetails[OPER].Assoc == Left && (OpDetails[O2].Prec == OpDetails[OPER].Prec))) {
          O2 = OperStack(--OperStack_nextfree);
          if (debug_torp) fprintf(stderr, "A: Transferring %ls to DataStack\n", OpDetails[O2].Sym);
          _DataStack(DataStack_nextfree++) = (Op_or_Data){'O',O2};
      } else break;
    }
    _OperStack(OperStack_nextfree++) = OPER;  // <-- runtime error, don't know why. OperStack_nextfree is 0
    ShowRP("PushMonOp:\n");

  }


  void PushBinOp(int P) {
    // 1.2
    Oper OPER;
    wchar_t *Ops;
    Ops = pooltowstr(P_P(P,1));

#ifdef NEVER
    if (debug_torp) fprintf(stderr, "PushBinOp(%ls)\n", Decode(P));
    
    // P came from a 'wlit()' call and should be a STRING pointer to \ or ~
    // only '\' or '~', and '-' for now!
    
    if (debug_torp) fprintf(stderr, "PushBinOp: Ops = \"%ls\"\n", Ops);

    if (wcscmp(Ops, L"+")==0) {
      OPER = OP_ADD;
    } else if (wcscmp(Ops, L"-")==0) {
      OPER = OP_SUB;
    } else if (wcscmp(Ops, L"&")==0) {
      OPER = OP_AND;
    } else if (wcscmp(Ops, L"****")==0) { // or \\ ...
      OPER = OP_IEXP;
    } else if (wcscmp(Ops, L"**")==0) { // or \ ...
      OPER = OP_REXP;
    } else if (wcscmp(Ops, L"^^")==0) {
      OPER = OP_IEXP;
    } else if (wcscmp(Ops, L"^")==0) {
      OPER = OP_REXP;
    } else if (wcscmp(Ops, L"*")==0) {
      OPER = OP_MULT;
    } else if (wcscmp(Ops, L"!!")==0) {
      OPER = OP_EOR;
    } else if (wcscmp(Ops, L"!")==0) {
      OPER = OP_OR;
    } else if (Ops[0] == L'/' && Ops[1] == L'/' && Ops[2] == L'\0') { // avoid bug in takeon where a '//' in a string is handled as if it were a C comment.
      OPER = OP_INTDIV;
    } else if (wcscmp(Ops, L"/")==0) {
      OPER = OP_REALDIV;
    } else if (wcscmp(Ops, L">>")==0) {
      OPER = OP_RSHIFT;
    } else if (wcscmp(Ops, L"<<")==0) {
      OPER = OP_LSHIFT;
    } else if (wcscmp(Ops, L".")==0) {
      OPER = OP_CONCAT;
    } else {
      fprintf(stderr, "Error: PushBinOp(\"%ls\") unknown\n", Ops);
      OPER = OP_NONE;
    }
#else
    // if (debug_torp) Diagnose(P);
    OPER = P_P(P,2);
#endif

    /*

        if the token is:
        - an operator o1:
            while (
                there is an operator o2 at the top of the operator stack which is not a left parenthesis,
                and (o2 has greater precedence than o1 or (o1 and o2 have the same precedence and o1 is left-associative))
            ):
                pop o2 from the operator stack into the output queue
            push o1 onto the operator stack
     */
    // 1.2.1
    for (;;) {
      if (OperStack_nextfree == OperStack_bottom) break;
      Oper O2 = OperStack(OperStack_nextfree-1);
      if (O2 == OP_LPAREN) break;
      if (   (OpDetails[O2].Prec > OpDetails[OPER].Prec)
          || (OpDetails[OPER].Assoc == Left && (OpDetails[O2].Prec == OpDetails[OPER].Prec))) {
          O2 = OperStack(--OperStack_nextfree);
          if (debug_torp) fprintf(stderr, "A: Transferring %ls to DataStack\n", OpDetails[O2].Sym);
          _DataStack(DataStack_nextfree++) = (Op_or_Data){'O',O2};
      } else break;
    }
    _OperStack(OperStack_nextfree++) = OPER;  // <-- runtime error, don't know why. OperStack_nextfree is 0
    ShowRP("PushBinOp:\n");
  }

  void PushConst(int P) {
    /*
        - a number:
            put it into the output queue
     */
    if (debug_torp) fprintf(stderr, "PushConst(%ls)\n", Decode(P));
    // 1.5 either literal constant or symbolic constant
    _DataStack(DataStack_nextfree++) = (Op_or_Data){'D',P};
    ShowRP("PushConst:\n");
  }
  
  void PushVar(int P) {
    /*
        - a number:
            put it into the output queue
     */
    if (debug_torp) fprintf(stderr, "PushVar(%ls)\n", Decode(P));
    // 1.5 either literal constant or symbolic constant
    _DataStack(DataStack_nextfree++) = (Op_or_Data){'D',P};
    ShowRP("PushVar:\n");
  }

  int Stack_to_Tree(void) {
    Oper op;
    int t[4];
    int Left, Right;
    if (DataStack_nextfree == DataStack_bottom) {
      fprintf(stderr, "* Error: expression stack ran out of data\n");
      return -1;
    }
    Op_or_Data TOS = DataStack(--DataStack_nextfree);
    if (TOS.type == 'O') {
      if (OpDetails[TOS.idx].Arity == 1) {
        t[1] = TOS.idx;
        t[2] = Left = Stack_to_Tree();
        return P_mktuple(AST_UNARY_ARITHMETIC_OPERATION, 0, 2, t);
      } else if (OpDetails[TOS.idx].Arity == 2) {
        t[1] = TOS.idx;
        t[2] = Right = Stack_to_Tree();
        t[3] = Left  = Stack_to_Tree();
        return P_mktuple(AST_BINARY_ARITHMETIC_OPERATION, 0, 3, t);
      } else {
        fprintf(stderr, "* Error: bad operator on stack\n");
      }
    } else if (TOS.type == 'D') {
      return TOS.idx;
    } else {
      fprintf(stderr, "* Error: bad data type on stack\n");
    }
    return -1;
  }

  void PushExpr(int P) {
    /*
        This should ne an 'AST_USER_PARENS' object which is treated as an atom and always output with '()' around it.
            put it into the output queue
     */
    if (debug_torp) fprintf(stderr, "PushExpr(%ls)\n", Decode(P));
    _DataStack(DataStack_nextfree++) = (Op_or_Data){'D',P};
    ShowRP("PushExpr:\n");
  }

  int ExPop(void) {
  
    // At one point this did not handle user brackets if there was valid code on the stack below it, eg for "a + (b + c)"
    // it was not possible to evaluate "(b + c)" without also picking up "a +" when the "b c +" was popped off the stack,
    // which at that time consists of a b c + +.

    // THIS WAS FIXED USING HAMISH'S FALSE BOTTOM TECHNIQUE (as seen in EMAS Pop2) where instead of testing the bottom of
    // the stack at index 0, we compare against DataStack_bottom instead.  Then at the point of evaluating an <EXPR> that
    // is within explicit parentheses, we save the old stack bottom, evaluate the expr as if in a virgin empty stack, then
    // we restore the previous stack bottom.  All of which costs zero overhead in this code.  Very elegant, Hamish.

    if (debug_torp) fprintf(stderr, "\nExPop()  Oper Stack contains %d items\n", OperStack_nextfree);
    ShowRP("Expop before final transfers:");
    // 2. Pop any remaining operator tokens from the stack to the output
    while (OperStack_nextfree > OperStack_bottom) {
          Oper y;
          y = OperStack(--OperStack_nextfree);
          if (debug_torp) fprintf(stderr, "B: Transferring %ls to DataStack\n", OpDetails[y].Sym);
          _DataStack(DataStack_nextfree++) = (Op_or_Data){'O',y};
    }
    // TO DO: Construct AST tree here...
    ShowRP("Expop before converting to AST:");
    int Expr = Stack_to_Tree();
    if (DataStack_nextfree > DataStack_bottom) {
      fprintf(stderr, "? Warning: TORP stack is not empty (%d items remaining) after extracting an <EXPR> as an AST tree.\n", DataStack_nextfree);
      DataStack_nextfree = 0; OperStack_nextfree = 0; // forcibly empty for now.  only during initial development.
    }
    return Expr;
  }
  
  DECLARE(DeclStack, int, 1024);
  $define _DeclStack(x)  WRITE(x,DeclStack,int)
  $define  DeclStack(x)   READ(x,DeclStack,int)
  static int DeclStack_nextfree = 0;

  static void PushDecl(int i) {
    _DeclStack[DeclStack_nextfree++] = i;
  };
  static int PopDecl(void) {
    int i = DeclStack[--DeclStack_nextfree];
    return i;
  };


  int ArrayDims = 0;
  DECLARE(LowBound, int, 16); // is there something such as 'PHRASE' I could use instead of 'int'?
  DECLARE(HighBound, int, 16);
  $define _LowBound[n]  WRITE(n, LowBound,  int)
  $define  LowBound[n]   READ(n, LowBound,  int)
  $define _HighBound[n] WRITE(n, HighBound, int)
  $define  HighBound[n]  READ(n, HighBound, int)
  void AddDims(int Low, int High) { _LowBound[ArrayDims] = Low; _HighBound[ArrayDims] = High; ArrayDims += 1; }

  // NOT ONLY OUTPUT THE DECLARATION IN C CODE, BUT ALSO ADD DECLARATION TO SCOPED NAME TABLES.

  int ParentVarIDX = -1, ParentTypeIDX = -1;       // VarDeclIDX for procedure to which parameters are being attached.
  int Tag = -1, VTag = -1, ATag = -1;              // Tag for declarations, VTag for use. ATag for an alias.   GLOBALS.
  char *STag = NULL, *SVTag = NULL, *SATag = NULL; // STag, VTag and ATag converted to a char *.  

  extern int generate_c(int P, int depth); // forward ref.  generate_c is intended to *only* output its parameter in C form,
                                           //               it should *not* attempt to compile anything.  Its parameter should
                                           //               already have been compiled and be ready to use. (Although the lines
                                           //               may be a little blurred during the development phase)
  
  int Declaration(int depth, int More) { // returns VarDeclIDX of new declaration
                                         // if (More) just print the tag, not the whole declaration.
                                         // i.e. for "int A, B;" rather than "int A; int B;".
                              
  // <DECLARE> collects all the pieces that preceded it which were set up during the walk
  // of the CST and uses them to modify the scoped name tables.  It also outputs the
  // declarations on the fly rather than during a subsequent walk of the generated AST.

  // It may be preferable to have this code only create the data structure and add it to the
  // scope tables, leaving the generation of the corresponding C code for the declaration up
  // to a call to 'generate_c' with this data structure as a parameter (eg an AST_DECLARE tuple)

  // One reason for doing so would be to handle initialised declarations better.

  // However it may be essential to create the name tables on the fly as the state of declarations
  // may be needed to steer the parser, though at the moment it is not looking like that is necessary.
  // If it were and if we were to try to postpone the C code generation until the CST was fully
  // converted to an AST, we would have to regenerate the name tables during that tree walk.

  // Until I see a definite need to do otherwise, I'm going to assume that we can postpone the
  // creation of the name tables until the AST is walked.  Note that the reason for these issues
  // is that the ERCC compilers handled a statement at a time but this parser is (currently)
  // parsing the entire program before the AST is interpreted.


  // TO DO: when declaring a %record, create a new scope which is just for that record.
  //        then when accessing a record field, look within the scope that it attached
  //        to the parent object for the field name, which will point to the details for
  //        that field.  This will align normal declarations and fields more consistently

  // When handling things like record formats and procedure parameters, rather than resetting
  // the state variables for declarations - push them on a stack instead and *then* clear
  // them down.  So that the parameters or fields can be parsed like any other declaration
  // and then attached to the parent - pop the stack on the end of the record format or
  // formal parameter list so that anything which follows at the parent level will preserve
  // whatever context was active.


  // DESCRIBE:
  if (debug_declarations) {
    if (Object == LABELDEFN) {
    } else if (Object == VAR && Basetype == GENERIC) {
      fprintf(stdout, "  /* ");
      PrintTag(Tag); // Tag is a global containing the <NAME> that immediately preceded the <DECLARE>
      fprintf(stdout, ": TypeDecl=%d VarDecl=%d Object=%s Basetype=%s ", TypeDecl_nextfree, VarDecl_nextfree, Object_name[Object], Basetype_name[Basetype]);
      fprintf(stdout, "*/");
    } else {
      fprintf(stdout, "  /* ");
      PrintTag(Tag); // Tag is a global containing the <NAME> that immediately preceded the <DECLARE>
      fprintf(stdout, ": TypeDecl=%d VarDecl=%d Object=%s ", TypeDecl_nextfree, VarDecl_nextfree, Object_name[Object]);
      if (Object == CODE) {
        fprintf(stdout, "Proc=%s ", Proc_name[Proc]);
        fprintf(stdout, "Linkage=%s ", Linkage_name[Linkage]);
      } else if (Object == VAR) {
        fprintf(stdout, "Area=%s ", Area_name[Area]);
      }
      if (Object == VAR || (Object == CODE && Proc != ROUTINE) || Object == ARRAYFORMAT) {
        if (Basetype != RECORD && Precision != COMPOUND) fprintf(stdout, "Sign=%s ", Signedness_name[Signedness]);
        fprintf(stdout, "Prec=%s ", Precision_name[Precision]);
        fprintf(stdout, "Type=%s ", Basetype_name[Basetype]);
        fprintf(stdout, "NameInfo=%s ", NameInfo_name[NameInfo]);
      }
      if (Object == VAR) {
        if (Proc != UNINIT_PROC) fprintf(stdout, "Proc=%s ", Proc_name[Proc]);
        //fprintf(stdout, "format=%s ", IsFormat_name[IsFormat]);
        fprintf(stdout, "IsArray=%s ", IsArray_name[IsArray]);
      }
      fprintf(stdout, "Spec=%s ", Spec_name[Spec]);
      fprintf(stdout, "*/");
    }
  }
  // GENERATE CODE:

  switch (Object) {
  
    // ##################################### VARIABLES ####################################

  case VAR:

    // ####################################### AREA #######################################

    if (Area == OWN) fprintf(stdout, "static ");
    else if (Area == EXTDATA) {
      // I don't believe that these external data declarations have to come at the top level *unless* they're initialised.
      fprintf(stdout, "extern ");
        /*
              In ISO C, 'extern' does not mean 'not defined in this file', it means
              'visible outside this file'. For instance,

              extern int x(void) { return 1; }
              extern int i3 = 3;

              are both valid ISO C, although they're unusual and the compiler warns
              about the second one.
         */
    } else if (Area == CONSTANT) fprintf(stdout, "const ");

    // ##################################### BASETYPE #####################################
    
    if (Basetype == RECORD) {

      // If the type was given as a format name then let's use the typedef otherwise
      // we'll need to put the struct definition inline.  And remember when defining
      // a record format, if it refers to itself as a %name field eg to link to a next
      // item, you need to predefine it as "typedef recfm recfm" before you actually
      // typedef the contents of recfm!
      
      fprintf(stdout, "/*pending name*/recfm  ");
    } else if (Basetype == STRINGTYPE) {
      fprintf(stdout, "Imp_String ");
    } else if (Basetype == INTEGER) {
      if (Signedness == UNSIGNED) fprintf(stdout, "unsigned ");
      if (Precision == BYTE) fprintf(stdout, "char ");
      else if (Precision == SHORT) fprintf(stdout, "short int ");
      else if (Precision == WORD) fprintf(stdout, "int ");
      else if (Precision == LONGWORD) fprintf(stdout, "long int ");
      else if (Precision == QUADWORD) fprintf(stdout, "long long int ");
      else if (Precision == ADDR) fprintf(stdout, "void *");
    } else if (Basetype == FLOAT) {
      if (Precision == WORD) fprintf(stdout, "float ");
      else if (Precision == LONGWORD) fprintf(stdout, "double "); 
      else if (Precision == QUADWORD) fprintf(stdout, "long double "); 
      else if (Precision == ADDR) fprintf(stdout, "void *");
    } else if (Basetype == GENERIC) {
      fprintf(stdout, "void *"); // %name parameter
    }

    // ##################################### NAMEINFO #####################################

    if (NameInfo == OBJECTNAME) fprintf(stdout, "*");
    else if (NameInfo == ARRAYNAME) fprintf(stdout, "**");

    // ####################################### TAG ########################################

    PrintTag(Tag);

    // ###################################### ISARRAY #####################################

    if (IsArray == ARRAY) { // May need bounds
      int D;
      
      // TO DO: This prints out the declaration but does not YET add it to the name/scope tables
      // When we do, there is already an array BoundsRA for storing the data.  Note that LowBound
      // and HighBound are just temporary communication variables, not part of the long term
      // name tables.  We *could* go straight to the BoundsRA array but if/when I make that
      // decision, I need to have done a lot more validation and testing.

      // done elsewhere PrintTag(Tag);
      for (D = 0; D < ArrayDims; D++) {
        int Low = LowBound[D];
        int High = HighBound[D];

        // TO DO: if Low is not constant, create a variable that is initialised to the value
        // of the lower bound at the point where the array is declared, and use that when
        // accessing array elements via the $define macro, to protect against the value of
        // the expression representing the lower bound changing when some variable in that
        // expression is assigned to later.

        // Also, we'll need those for each dimension, maybe saved in an array of arrayname_low[ArrayDims]

        // Note that the $define to access an array element can also be used to perform
        // array bound checking on array indices (although the overhead may be significant,
        // but the error reporting should be better than what you would get from using
        // valgrind or the gcc extensions that can perform checks)

        // These macro expansions are ugly in the generated C.  It would be nicer to modify
        // the indices in the compiler which would allow the tree representing the index expression
        // to be output with fewer brackets and maybe with constants having been folded.
        // The compromise (when using imp80 to C to translate an Imp source with a view to
        // maintaining the C source in future) is to maintain the source with the embedded
        // $define directives from gtcpp rather than the cleaner pure C source that is
        // output by gtcpp.
        
        fprintf(stdout, "[(");
        generate_c(High, depth+1);
        fprintf(stdout, ")-(");
        generate_c(Low, depth+1);
        fprintf(stdout, ")+1]");
      }
      fprintf(stdout, ";\n");
      
      fprintf(stdout, "\n$define "); PrintTag(Tag);
      for (D = 0; D < ArrayDims; D++) {
        fprintf(stdout, "[N%0d]", D);
      }
      fprintf(stdout, " "); PrintTag(Tag);
      for (D = 0; D < ArrayDims; D++) {
        fprintf(stdout, "[(N%0d)-(", D);
        int Low = LowBound[D];
        generate_c(Low, depth+1);
        fprintf(stdout, ")]");
      }
      fprintf(stdout, "\n");
    }
    
    // ####################################### END ########################################

    //if (Area == PARAMETER) {
      // comma handled elsewhere
    //} else {
      //fprintf(stdout, "; "); // CANNOT OUTPUT ';' HERE IF THIS IS AN INITIALISED DECLARATION!
      // this should be handled elsewhere too...
    //}
    break;

    // ################################### PROCEDURES ####################################

  case CODE:

    // ##################################### LINKAGE #####################################

    if (Linkage == EXTPROC) {
      if (Spec == SPEC) {
        fprintf(stdout, "extern ");
      } else {
        // The body of an Imp %externalroutine does not require "extern" in C.
        // An external *spec* does *NOT* have to be at the top level although
        // an external body does.
        /*
              In ISO C, 'extern' does not mean 'not defined in this file', it means
              'visible outside this file'. For instance,

              extern int x(void) { return 1; }
              extern int i3 = 3;

              are both valid ISO C, although they are unusual and the compiler warns
              about the second one.
         */
        // declaration of an externalroutine or function etc *but* only valid if at the top level.  So check.  (TO DO)
      }
    } else if (ctrl_depth() == 0) {
      fprintf(stdout, "static ");
    } else {
      if (Spec == SPEC) fprintf(stdout, "auto "); // GCC requires "auto" for forward references to nested procedures, but not for the procedures themselves.
    }

    // ##################################### BASETYPE #####################################

    if (Proc == ROUTINE) {
      fprintf(stdout, "void ");
    } else if (Basetype == RECORD) {
      fprintf(stdout, "/*pending name*/recfm  ");
    } else if (Basetype == STRINGTYPE) {
      fprintf(stdout, "Imp_String ");
    } else {
      if (Basetype == INTEGER) {
        if (Signedness == UNSIGNED) fprintf(stdout, "unsigned ");
        if (Precision == BYTE) fprintf(stdout, "char ");
        else if (Precision == SHORT) fprintf(stdout, "short int ");
        else if (Precision == WORD) fprintf(stdout, "int ");
        else if (Precision == LONGWORD) fprintf(stdout, "long int ");
        else if (Precision == QUADWORD) fprintf(stdout, "long long int ");
        else if (Precision == ADDR) fprintf(stdout, "void *");
      } else if (Basetype == FLOAT) {
        if (Precision == WORD) fprintf(stdout, "float ");
        else if (Precision == LONGWORD) fprintf(stdout, "double "); 
        else if (Precision == QUADWORD) fprintf(stdout, "long double "); 
        else if (Precision == ADDR) fprintf(stdout, "void *");
      }
    }
    if (NameInfo == OBJECTNAME) fprintf(stdout, "*");
    if (Proc == MAP) fprintf(stdout, "*");
    PrintTag(Tag);
    
    // Moving these to point of call:
    //fprintf(stdout, "(/*to do*/)");
    //if (Spec == SPEC) fprintf(stdout, ";"); else fprintf(stdout, " {\n"); // the %end will come much later
    break;

  case RECORDFORMAT:
    fprintf(stdout, "/* TO DO: %%RECORDFORMAT DECLARATION */\n");
    break;
  case ARRAYFORMAT:
    fprintf(stdout, "/* TO DO: %%ARRAYFORMAT DECLARATION */\n");
    break;
  case SWITCHDEFN:
    fprintf(stdout, "/* TO DO: %%SWITCH DECLARATION */\n");
    break;
  case LABELDEFN:
    fprintf(stdout, "/* TO DO: %%LABEL DECLARATION */\n");
    break;
  case UNINIT_OBJECT:
    break;
  }

    _TypeDecl[TypeDecl_nextfree].Object     =  Object     ;
    _TypeDecl[TypeDecl_nextfree].Basetype   =  Basetype   ;
    _TypeDecl[TypeDecl_nextfree].Signedness =  Signedness ;
    _TypeDecl[TypeDecl_nextfree].Precision  =  Precision  ;
    _TypeDecl[TypeDecl_nextfree].Proc       =  Proc       ;
    _TypeDecl[TypeDecl_nextfree].NameInfo   =  NameInfo   ;
    _TypeDecl[TypeDecl_nextfree].Spec       =  Spec       ;
    _TypeDecl[TypeDecl_nextfree].IsArray    =  IsArray    ;
    _TypeDecl[TypeDecl_nextfree].Area       =  Area       ;
    _TypeDecl[TypeDecl_nextfree].Linkage    =  Linkage    ;
    // TO DO:
    _TypeDecl[TypeDecl_nextfree].arrfm      =  -1         ;
    _TypeDecl[TypeDecl_nextfree].parms      =  -1         ;
    _TypeDecl[TypeDecl_nextfree].recfm      =  -1         ;
    _TypeDecl[TypeDecl_nextfree].strfm      =  -1         ;
    
    _VarDecl[VarDecl_nextfree].varname      = Tag;
    _VarDecl[VarDecl_nextfree].aliasname    = -1;
    _VarDecl[VarDecl_nextfree].c_name       = Tag;
    _VarDecl[VarDecl_nextfree].type         = TypeDecl_nextfree;
    _VarDecl[VarDecl_nextfree].aform        = -1;

//fprintf(stdout, "      /* VarDecl[%d] = {varname=%s tag=%d ", VarDecl_nextfree, Tag2Str(Tag), Tag);
//fprintf(stdout, "Object=%d Basetype=%d Signedness=%d Precision=%d Proc=%d NameInfo=%d Spec=%d IsArray=%d Area=%d Linkage=%d} */\n",
//                        Object,     Basetype,     Signedness,  Precision,  Proc,   NameInfo,  Spec,   IsArray,   Area,   Linkage);


    // If this declaration is a formal parameter, attach it to the 'parms' list of the parent procedure.
    // Parameters are going to be in reverse order for now but that may not be a problem since C calls parameters in the wrong order anyway ;-)
    // But seriously, this is just the first draft.  I'll reverse the list later.
    if (Area == PARAMETER) {
      //TypeDecl[TypeDecl_nextfree].parms = TypeDecl[ParentTypeIDX].parms; // linked list (albeit reversed)
      //TypeDecl[ParentTypeIDX].parms = TypeDecl_nextfree;

      int last_link = ParentTypeIDX;
      for (;;) {
        if (TypeDecl[last_link].parms == -1) break;
        last_link = TypeDecl[last_link].parms;
      }
      TypeDecl[last_link].parms = TypeDecl_nextfree; // append to end of parameter list
    }
    
    TypeDecl_nextfree += 1;
    VarDecl_nextfree += 1;

    add_entry("decl", Tag2Str(Tag), VarDecl_nextfree-1);
    return VarDecl_nextfree-1;
  } // end of Declaration()



  int Mk_AST_procedure_call(int PVar, int depth) {
    int Var = -1;
    
    // Parameters have not yet been compile()'d
    // if <VAR> is not a procedure call, report an error
    // (remember that it might be a procedure parameter that is being called)

    Var = compile(PVar, depth+1);  // Code to evaluate P<VAR> should return a P_mktuple(AST_PROC_CALL, 0, 3, t) if appropriate
                                   // This procedure is only here to perform the various checks.

    if (P_op(Var) != AST_PROC_CALL) {
      fprintf(stderr, "* ERROR: Not a procedure\n"); // exit(1);
      return -1;
    }
    return Var;
  }






  int Compile_Var(int Parent, int PVarname, int POpt_app, int POpt_field, int depth) {

    // P<VAR> = <VARNAME><APP><Opt_Record_Field>
    // P<Opt_Record_Field> = '_'<VARNAME><APP><Opt_Record_Field>, ''

    int Varname = -1, APP = -1, Field = -1, Var = -1;
    
    if (Parent == -1) {
      // build top level
      Varname = compile(PVarname, depth+1);
      APP     = compile(POpt_app, depth+1);
      Field   = compile(POpt_field, depth+1);
      // BIG TODO GOES HERE  <-- ************************************************************ CURRENT WORK-IN-PROGRESS  Get starter code from <XXCall_or_Assign_AUI>
      Var = Varname; // = Appify(Varname, APP);
    } else {
      // modify parent with these (do it longhand, not via another proc)
      // Var = Modify_Var(Var, PVarname, POpt_app, POpt_field, depth+1);
    }
    if (Field == -1 || P_alt(Field) != 0) return Var;   // *** IN PROGRESS ***

    // '_'<VARNAME><APP><Opt_Record_Field>
    // keep (tail) recursing if <Opt_Record_Field> is not empty
    
    return Compile_Var(Var, P_P(Field, 2), P_P(Field, 3), P_P(Field, 4), depth+1);

  } // end of Compile_Var()

  int Mk_AST_assignment(int Var, int Assop, int Expr, int depth) {
    int t[LARGEST_ALT];
    
    // work out the vagaries of assigning to a name or %map, and whether
    // it is a '=' (or <-) versus a '=='
    // Do all the error reporting here - by the time the AST_ASSIGN is executed
    // by generate_c, success is assumed.

    t[1] = Assop; // OP
    t[2] = Var;   // LHS  *** THIS IS AN RVALUE TUPLE *** which is not correct but will do short-term at this stage of restructuring ...
    t[3] = Expr;  // RHS
    int Ass = P_mktuple(AST_ASSIGN, 0, 3, t);
    //Diagnose(Ass);
    return Ass;
  }






//#endif
  int ColonFlag = 0;
//#ifdef INITCODE

#endif //INITCODE
int parse_init(void)
{
#ifdef IN_PARSER // regen etc use this too but don't need a lot of what uparse.c needs.
  // perform any initialisation required by the parse-time semantic routines.
  // Note that for now, we have no way of declaring data outside of
  // those procedures.  Obviously this will have to change.

  // LINE RECONSTRUCTION *might* GO HERE.  But probably not.
  
  // initially default scope is at the level appropriate for perms
  
  debug_scope = 0;
  debug_ast = 0;
  debug_ctrl_stack = 0;
  debug_compiler = 0;
  debug_declarations = 0;
  debug_torp = 0;

  //push_scope_level();
  // Declare perms, prims here
  //add_entry("decls", "NEWLINE", 42); // param can be anything. Usually index into an array of records of the appropriate type.  During initial code creation, we'll just use random tags.
  // initial top-level file-level scope, eg for %externalroutines
  //push_scope_level();
  // ready for externals

  //fprintf(stdout, "\n// Relies on using gtcpp to preprocess before cleaning up with clang-format");
  fprintf(stdout, "\n$define unless(cond) if (!(cond)) \n$define until(cond) while(!(cond))\n");
  
#endif
  return TRUE;
}
int parse_terminate(void)
{
#ifdef IN_PARSER
  // perform any final tidy-up required by the parse-time semantic routines.

  //pop_scope_level(); // from externals back to perms
  //pop_scope_level(); // from perms to none.
#endif
  return TRUE;
}
int parse_whitespace(void)
{
#ifdef IN_PARSER
  while (source(TP).ch==' ' || source(TP).ch=='\t' || source(TP).ch=='\f') {
    TP += 1;
  }
#endif
  return TRUE;
}
int parse_Imp77_stropping(void)
{
#ifdef IN_PARSER
  int debug_stropping = 0;

  // The source file has already been read trivially into source().
  
  // We will copy from source() into temp(), then perform line reconstruction
  // on temp(), writing back to source().  The parser will then parse source()
  // into atoms according to the grammar.  Initially it will only store the
  // reconstructed characters into the atoms, but once it is working, I will
  // modify it to also store the unreconsructed source for use in source-to-source
  // translations, where whitespace, embedded comments, and indentation is
  // desired in the translation, in order to mirror the original file.

  // Because unfortunately underlining in Unicode is done by a *following*
  // underline joiner character (818) rather than being a single unicode
  // code point, it is difficult to use a single-character encoding of a
  // stropped keyword letter - what the old Imp compilers would represent
  // by adding 128 to the character.  However there *is* an alternive
  // source of upper case and lower case letters in the mathematics area!

  // A:Z could be encoded as 1D400:1D419 and a:z as 1D41A:1D433 :-)
  // but for now I'm encoding keywords in lower case and variables in
  // upper case.
  
  // The 1D400+ encoding looks more or less like ordinary text if it happens
  // to be displayed (e.g. during debugging) although there should never be
  // any need to display internally-coded keywords to users of the
  // compilers built with this parser.

  // All arrays are flex and the upper bound is a limit, not a minimum.
  DECLARE(SYM, reconstructed, 128000000/*600000*/);
#define _SYM(x) WRITE(x,SYM,reconstructed)
#define  SYM(x)  READ(x,SYM,reconstructed)

  int LASTP, P = 0;
  while (source(P).ch != 0 /* WEOF */) {
    _SYM(P).ch = source(P).ch;
    _SYM(P).start = P; _SYM(P).end = P+1;
    P += 1;
  }
  _SYM(P).ch = 0 /* WEOF */;
  _SYM(P).start = P; _SYM(P).end = P; // no chars for EOF
  LASTP = P;
  
  if (debug_stropping) {
    int I;
    fprintf(stderr, "source() moved to SYM(0:%d) = \"", LASTP);
    for (I = 0; I < LASTP; I++) {
      /*if (SYM(I).ch != 0)*/ fprintf(stderr, "%lc", SYM(I).ch);
    }
    if (SYM(LASTP).ch != 0) fprintf(stderr, "[%d]", SYM(LASTP).ch);
    fprintf(stderr, "\";\n");
  };

  int FP = 0, PP = 0; // Fetch Pointer, Put Pointer.

#define DONE() \
        do {                                                                      \
            FP -= 1; /* the terminating 0*/                                       \
            _source(PP).ch = 0;                                                   \
            _source(PP).end = SYM(FP).end;                                        \
            if (debug_stropping) {                                                \
              int I;                                                              \
              fprintf(stderr, "SYM(0:%d) moved to source(0:%d) = \"", FP, PP);    \
              for (I = 0; I < PP; I++) {                                          \
                if (source(I).ch != 0) fprintf(stderr, "%lc", source(I).ch);      \
              }                                                                   \
              if (source(PP).ch != 0) fprintf(stderr, "[%d]", source(PP).ch);     \
              fprintf(stderr, "\";\n");                                           \
            }                                                                     \
            return TRUE;                                                          \
        } while (0)

  wint_t WC;

  // NOTE THAT WITH THIS IMP77 GRAMMAR, '\n' IS NOT WHITESPACE.  LINE ENDINGS ARE EXPLICITLY
  // ENTERED IN THE GRAMMAR.  (See the phrases <T>, and <NL_opt>.
  
  // uparse.c has been modified so that its implicit whitespace skipping no longer skips '\n'.
  // (The algol60 parser in contrast treats all \n's the same as spaces)
  
  // HOW TO HANDLE ' IN A PARSED COMMENT?
  //
  // %COMMENT A ' MESSES UP!
  //
  // because it keeps scanning until a closing quote.  However if you don't scan between quotes,
  // line reconstruction will lose spaces within strings!
  //
  // You can't just end a quoted string at a newline because embedded newlines are allowed.
  // And I checked Imp77 - it allows a single quote ch in a comment.

  // If line reconstruction were being done on the fly then it could be modified if we knew we were
  // in a comment, but since we're doing it all in advance, the only option to handle this appears
  // to be that whenever we're in a comment, we throw away all the following line reconstruction and
  // re-do it, with that comment handled differently.

  // Or bite the bullet and work out how to do line reconstruction on the fly (which my previous
  // imptoc did eventually manage using the 'demandload' call. So *every* fetch via TP would have
  // to be recoded as a procedure call, with on-the-fly line reconstruction, and either a way to
  // undo it if backtracking or simply never doing it any farther past TP and undoing it on backtracking.

  // What a can of worms just to handle badly designed comments.  TO DO.

#define CHECK_EOF(x) do if ((x) == 0) DONE(); else { _source(PP).end = SYM(FP-1).end; } while (0)

  // PP is the 'current' slot we are writing into.
  _source(PP).start = SYM(FP).start;

  for (;;) {

    _source(PP).end = SYM(FP).end; // Keep updated.
    WC = SYM(FP++).ch; CHECK_EOF(WC);

    if (WC == '%') { // We found a keyword.  It will always be read up to the last character of the keyword.

      for (;;) {
        WC = SYM(FP++).ch; CHECK_EOF(WC);
        if (WC == '%') {

        } else if (!isalpha(WC)) {
          // It's possible to have a bunch of '%' signs and *no* keyword characters.
          --FP; // point FP back to the non-keyword character, not as currently, the one past that.
          break;    
        } else { // isalpha(WC)
          if (isupper(WC)) WC = tolower(WC);
          _source(PP).end = SYM(FP-1).end;
          _source(PP++).ch = WC; // | 128
          _source(PP).start = SYM(FP).start;
        }
      }
      continue;
    }

    else if (WC == '{') {

      for (;;) {
        WC = SYM(FP++).ch; CHECK_EOF(WC);

        if (WC == '\n') {
          --FP; /* re-read the \n as a significant character */
          // _source(PP).end = SYM(FP-1).end; // point FP back to the newline
          break;
        }
        if (WC == '}') {  // Not sure if \n should be gobbled for {this style
          break; // but still looking.
        }
      }
      continue;
    }

    else if (WC == '\'') {
      _source(PP++).ch = WC;
      for (;;) {
        WC = SYM(FP++).ch; CHECK_EOF(WC);
        if (WC == '\'') {
          // peek ahead:
          int Peek = SYM(FP).ch; CHECK_EOF(Peek);
          if (Peek == '\'') { // doubled 's
            _source(PP++).ch = WC;
            _source(PP++).ch = Peek;
            FP++;
          } else {
            _source(PP).ch = WC;
            _source(PP).end = SYM(FP-1).end; // Leave Peek for later.
            PP++;
            break;
          }
        } else {
          _source(PP++).ch = WC;
        }
      }
      continue;
    }

    else if (WC == '"') { // TO DO: Update ' and " items in imp77 as well
      _source(PP++).ch = WC;
      for (;;) {
        WC = SYM(FP++).ch; CHECK_EOF(WC);
        if (WC == '"') {
          // peek ahead:
          int Peek = SYM(FP).ch; CHECK_EOF(Peek);
          if (Peek == '"') { // doubled "s
            _source(PP++).ch = WC;
            _source(PP++).ch = Peek;
            FP++;
          } else {
            _source(PP).ch = WC;
            _source(PP).end = SYM(FP-1).end; // Leave Peek for later.
            PP++;
            break;
          }
        } else {
          _source(PP++).ch = WC;
        }
      }
      continue;
    }

    else if (WC == ' ' || WC == '\t' || WC == '\f') {  // use iswblank(WC) instead?

      continue;
    }




    else {
      // everything else just returns one significant non-space character. This includes '\n'.

      if ((WC == '\n') && ((PP>1) && (source(PP-1).ch == 'c'))) {  // BEWARE WHEN CHANGING STROPPING ENCODING: Looking for a preceding '%C' ...
        if (PP>0) _source(PP-1).ch = ' '; // remove the '%c'
        _source(PP++).ch = ' '; // remove the newline

        // This is the only place where we gobble spaces *after* a token rather than before.
        // It may be cleaner to set a 'continuation' flag and gobble them before the next
        // symbol fetch rather than do it here in a lookahead.  Esp. wrt to reconstituting source
        // from the array for the listing file etc etc.
        // BUT FOR NOW, %C IS HANDLED BY THS HACK:

        int Lookahead = FP;
        while (SYM(Lookahead).ch == '\n' || SYM(Lookahead).ch == ' ' || SYM(Lookahead).ch == '\t' || SYM(Lookahead).ch == '\f') { // Use iswblank()?
          // No worries about  '{...}' - this behaviour seems to be identical to Imp77's
          _SYM(Lookahead).ch = ' ';   // gobble following newlines and whitespace before next significant character.
          Lookahead++;
        }
        continue;
      }

      if (iswalpha(WC) && iswlower(WC)) {
        WC = towupper(WC);  // ALSO TEMPORARY
      }
      _source(PP++).ch = WC;
      continue;
    }


    // Still skipping whitespace ...

  }

  DONE();
  P = 0;
  while (source(P).ch != 0) {
    if (debug_stropping) fprintf(stderr, "%d: ch='%lc'  start=%d:end=%d\n", P, source(P).ch, source(P).start, source(P).end);
    P++;
  }

#undef DONE
#endif
  return TRUE;
}
int parse_COLON(void)
{
  // Noting that we have just seen a label at parse time allows us
  // to handle an immediately-following comment differently, i.e.
  // by avoiding the line reconstruction (if doing so on the fly)
  // and thus preserving the text of the comment for output by a
  // source-to-source translator.
  //ColonFlag = 1; // Note that <COLON> occurs last in its list of alternatives so if it is
                 // executed at all, the parse is going to be successful.
                 // We should then reset ColonFlag at the point where it is tested (for the comments)
  return TRUE;
}
int parse_INCLUDE(void)
{
  // We almost certainly need to handle include files at parse time (with a stack of
  // input files, as I'm doing in takeon.c)
  return TRUE;
}
int parse_LISTON(void)
{
  // listing control has to be done at parse time
  // (unless there is a *major* restructuring)
  return TRUE;
}
int parse_LISTOFF(void)
{
  return TRUE;
}

// B<eof> = 0;

// B<ch> = 1;

// B<nl> = 2;

// E
#endif  // SUPPRESS_DATA
#endif  // _GRAMMAR_H_
