Home | History | Annotate | Download | only in antlr
      1 /*
      2  * antlr.g	--	PCCTS Version 1.xx ANTLR
      3  *
      4  * Parse an antlr input grammar and build a syntax-diagram.
      5  *
      6  * Written in itself (needs at least 1.06 to work)
      7  *
      8  * SOFTWARE RIGHTS
      9  *
     10  * We reserve no LEGAL rights to the Purdue Compiler Construction Tool
     11  * Set (PCCTS) -- PCCTS is in the public domain.  An individual or
     12  * company may do whatever they wish with source code distributed with
     13  * PCCTS or the code generated by PCCTS, including the incorporation of
     14  * PCCTS, or its output, into commerical software.
     15  *
     16  * We encourage users to develop software with PCCTS.  However, we do ask
     17  * that credit is given to us for developing PCCTS.  By "credit",
     18  * we mean that if you incorporate our source code into one of your
     19  * programs (commercial product, research project, or otherwise) that you
     20  * acknowledge this fact somewhere in the documentation, research report,
     21  * etc...  If you like PCCTS and have developed a nice tool with the
     22  * output, please mention that you developed it using PCCTS.  In
     23  * addition, we ask that this header remain intact in our source code.
     24  * As long as these guidelines are kept, we expect to continue enhancing
     25  * this system and expect to make other tools available as they are
     26  * completed.
     27  *
     28  * ANTLR 1.33
     29  * Terence Parr
     30  * Parr Research Corporation
     31  * with Purdue University and AHPCRC, University of Minnesota
     32  * 1989-1995
     33  */
     34 
     35 /* MR1									*/
     36 /* MR1 10-Apr-97 MR1	Replace #if logic with #include "pcctscfg.h"	*/
     37 /* MR1									*/
     38 
     39 #header <<
     40 	#include "pcctscfg.h"
     41 	#include "set.h"
     42 	#include <ctype.h>
     43 	#include "syn.h"
     44 	#include "hash.h"
     45 	#include "generic.h"
     46 	#define zzcr_attr(attr,tok,t)
     47 	>>
     48 
     49 <<
     50 
     51 /* MR20 G. Hobbelt For Borland C++ 4.x & 5.x compiling with ALL warnings enabled */
     52 #if defined(__TURBOC__)
     53 #pragma warn -aus  /* unused assignment of 'xxx' */
     54 #endif
     55 
     56 
     57 #ifdef __USE_PROTOS
     58 static void chkToken(char *, char *, char *, int);
     59 #else
     60 static void chkToken();
     61 #endif
     62 
     63 #ifdef __USE_PROTOS
     64 static int isDLGmaxToken(char *Token);				     /* MR3 */
     65 #else
     66 static int isDLGmaxToken();				                             /* MR3 */
     67 #endif
     68 
     69 static int class_nest_level = 0;
     70 
     71 /* MR20 G. Hobbelt extern definitions moved to antlr.h */
     72 
     73 >>
     74 
     75 #lexaction <<
     76 /* maintained, but not used for now */
     77 set AST_nodes_refd_in_actions = set_init;
     78 int inAlt = 0;
     79 set attribsRefdFromAction = set_init; /* MR20 */
     80 int UsedOldStyleAttrib = 0;
     81 int UsedNewStyleLabel = 0;
     82 #ifdef __USE_PROTOS
     83 char *inline_set(char *);
     84 #else
     85 char *inline_set();
     86 #endif
     87 
     88 /* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	    */
     89 /* MR1					in DLG action			                    */
     90 
     91 int tokenActionActive=0;                                            /* MR1 */
     92 
     93 >>
     94 
     95 #lexclass STRINGS
     96 #token QuotedTerm "\""		<< zzmode(START); >>
     97 #token "\n|\r|\r\n"     	<<
     98 							zzline++;
     99 							warn("eoln found in string");
    100 							zzskip();
    101 							>>
    102 #token "\\(\n|\r|\r\n)"		<< zzline++; zzmore(); >>
    103 #token "\\~[]"				<< zzmore(); >>
    104 #token "~[\n\r\"\\]+"		<< zzmore(); >>
    105 
    106 #lexclass ACTION_STRINGS
    107 #token "\""					<< zzmode(ACTIONS); zzmore(); >>
    108 #token "\n|\r|\r\n"			<<
    109 							zzline++;
    110 							warn("eoln found in string (in user action)");
    111 							zzskip();
    112 							>>
    113 #token "\\(\n|\r|\r\n)"		<< zzline++; zzmore(); >>
    114 #token "\\~[]"				<< zzmore(); >>
    115 #token "~[\n\r\"\\]+"			<< zzmore(); >>
    116 
    117 #lexclass ACTION_CHARS
    118 #token "'"					<< zzmode(ACTIONS); zzmore(); >>
    119 #token "\n|\r|\r\n"			<<
    120 							zzline++;
    121 							warn("eoln found in char literal (in user action)");
    122 							zzskip();
    123 							>>
    124 #token "\\~[]"				<< zzmore(); >>
    125 #token "~[\n\r'\\]+"		<< zzmore(); >>
    126 
    127 #lexclass ACTION_COMMENTS
    128 #token "\*/"				<< zzmode(ACTIONS); zzmore(); >>
    129 #token "\*"					<< zzmore(); >>
    130 #token "\n|\r|\r\n"			<< zzline++; zzmore(); DAWDLE; >>
    131 #token "~[\n\r\*]+"			<< zzmore(); >>
    132 
    133 #lexclass TOK_DEF_COMMENTS
    134 #token "\*/"				<< zzmode(PARSE_ENUM_FILE);
    135                               zzmore(); >>
    136 #token "\*"					<< zzmore(); >>
    137 #token "\n|\r|\r\n"			<< zzline++; zzmore(); DAWDLE; >>
    138 #token "~[\n\r\*]+"			<< zzmore(); >>
    139 
    140 #lexclass TOK_DEF_CPP_COMMENTS
    141 #token "\n|\r|\r\n"			<< zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; >>
    142 #token "~[\n\r]+"			<< zzskip(); >>
    143 
    144 #lexclass ACTION_CPP_COMMENTS
    145 #token "\n|\r|\r\n"			<< zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; >>
    146 #token "~[\n\r]+"			<< zzmore(); >>
    147 
    148 #lexclass CPP_COMMENTS
    149 #token "\n|\r|\r\n"			<< zzline++; zzmode(START); zzskip(); DAWDLE; >>
    150 #token "~[\n\r]+"			<< zzskip(); >>
    151 
    152 #lexclass COMMENTS
    153 #token "\*/"				<< zzmode(START); zzskip(); >>
    154 #token "\*"					<< zzskip(); >>
    155 #token "\n|\r|\r\n"			<< zzline++; zzskip(); DAWDLE; >>
    156 #token "~[\n\r\*]+"			<< zzskip(); >>
    157 
    158 /*
    159  * This lexical class accepts actions of type [..] and <<..>>
    160  *
    161  * It translates the following special items for C:
    162  *
    163  * $j		--> "zzaArg(current zztasp, j)"
    164  * $i.j		--> "zzaArg(zztaspi, j)"
    165  * $i.nondigit> "zzaArg(current zztasp, i).nondigit"
    166  * $$		--> "zzaRet"
    167  * $alnum	--> "alnum"			(used to ref parameters)
    168  * $rule	--> "zzaRet"
    169  * $retval	--> "_retv.retval" if > 1 return values else "_retv"
    170  * $[token, text] --> "zzconstr_attr(token, text)"
    171  * $[]		--> "zzempty_attr()"
    172  *
    173  * It translates the following special items for C++:
    174  * (attributes are now stored with 'Token' and $i's are only
    175  *  pointers to the Tokens.  Rules don't have attributes now.)
    176  *
    177  * $j		--> "_tbj" where b is the block level
    178  * $i.j		--> "_tij"
    179  * $j->nondigit> "_tbj->nondigit"
    180  * $$		--> "$$"
    181  * $alnum	--> "alnum"			(used to ref parameters)
    182  * $rule	--> "$rule"
    183  * $retval	--> "_retv.retval" if > 1 return values else "_retv"
    184  * $[token, text] --> invalid
    185  * $[]		--> invalid
    186  *
    187  * And, for trees:
    188  *
    189  * #0		-->	"(*_root)"
    190  * #i		--> "zzastArg(i)"
    191  * #[args]	--> "zzmk_ast(zzastnew(), args)"
    192  * #[]		--> "zzastnew()"
    193  * #( root, child1, ..., childn )
    194  *			--> "zztmake(root, child1, ...., childn, NULL)"
    195  * #()		--> "NULL"
    196  *
    197  * For C++, ...
    198  *
    199  * #0		-->	"(*_root)"
    200  * #i		--> "_astbi" where b is the block level
    201  * #alnum	--> "alnum_ast"	(used to ref #label)
    202  * #[args]	--> "new AST(args)"
    203  * #[]		--> "new AST"
    204  * #( root, child1, ..., childn )
    205  *			--> "AST::tmake(root, child1, ...., childn, NULL)"
    206  * #()		--> "NULL"
    207  *
    208  * To escape,
    209  *
    210  * \]		--> ]
    211  * \)		--> )
    212  * \$		--> $
    213  * \#		--> #
    214  *
    215  * A stack is used to nest action terminators because they can be nested
    216  * like crazy:  << #[$[..],..] >>
    217  */
    218 #lexclass ACTIONS
    219 #token Action "\>\>"        << /* these do not nest */
    220                               zzmode(START);
    221                               NLATEXT[0] = ' ';
    222                               NLATEXT[1] = ' ';
    223                               zzbegexpr[0] = ' ';
    224                               zzbegexpr[1] = ' ';
    225 							  if ( zzbufovf ) {
    226 								err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE));
    227 							  }
    228 
    229 /* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	*/
    230 /* MR1					in DLG action			*/
    231 /* MR1			Doesn't matter what kind of action it is - reset*/
    232 
    233 			      tokenActionActive=0;		 /* MR1 */
    234                             >>
    235 #token Pred "\>\>?"			<< /* these do not nest */
    236                               zzmode(START);
    237                               NLATEXT[0] = ' ';
    238                               NLATEXT[1] = ' ';
    239                               zzbegexpr[0] = '\0';
    240 							  if ( zzbufovf ) {
    241 								err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE));
    242 							  };
    243 #ifdef __cplusplus__
    244 /* MR10 */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
    245 #else
    246 #ifdef __STDC__
    247 /* MR10 */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
    248 #else
    249 #ifdef __USE_PROTOS
    250 /* MRxx */                    list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred);
    251 #else
    252 /* MR10 */                    list_apply(CurActionLabels,mark_label_used_in_sem_pred);
    253 #endif
    254 #endif
    255 #endif
    256                             >>
    257 #token PassAction "\]"		<< if ( topint() == ']' ) {
    258 								  popint();
    259 								  if ( istackempty() )	/* terminate action */
    260 								  {
    261 									  zzmode(START);
    262 									  NLATEXT[0] = ' ';
    263 									  zzbegexpr[0] = ' ';
    264 									  if ( zzbufovf ) {
    265 										err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE));
    266 									  }
    267 								  }
    268 								  else {
    269 									  /* terminate $[..] and #[..] */
    270 									  if ( GenCC ) zzreplstr("))");
    271 									  else zzreplstr(")");
    272 									  zzmore();
    273 								  }
    274 							   }
    275 							   else if ( topint() == '|' ) { /* end of simple [...] */
    276 								  popint();
    277 								  zzmore();
    278 							   }
    279 							   else zzmore();
    280 							>>
    281 #token "consumeUntil\( [\ \t]* \{~[\}]+\} [\ \t]* \)"
    282    							<<
    283    							zzmore();
    284 							zzreplstr(inline_set(zzbegexpr+
    285 									  strlen("consumeUntil(")));
    286 							>>
    287 #token "consumeUntil\( ~[\)]+ \)"
    288 							<< zzmore(); >>
    289 #token "\n|\r|\r\n"			<< zzline++; zzmore(); DAWDLE; >>
    290 #token "\>"					<< zzmore(); >>
    291 #token "$"					<< zzmore(); >>
    292 #token "$$"					<< if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();}
    293 							   else err("$$ use invalid in C++ mode"); >>
    294 
    295 #token "$\[\]"				<< if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();}
    296 							   else err("$[] use invalid in C++ mode"); >>
    297 #token "$\["				<<
    298 							pushint(']');
    299 							if ( !GenCC ) zzreplstr("zzconstr_attr(");
    300 							else err("$[..] use invalid in C++ mode");
    301 							zzmore();
    302 							>>
    303 #token "$[0-9]+"			<<{
    304 							static char buf[100];
    305                             numericActionLabel=1;       /* MR10 */
    306 							if ( strlen(zzbegexpr)>(size_t)85 )
    307 								fatal("$i attrib ref too big");
    308 							set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);
    309 							if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)",
    310 										BlkLevel-1,zzbegexpr+1);
    311 							else sprintf(buf,"_t%d%s",
    312 										BlkLevel-1,zzbegexpr+1);
    313 							zzreplstr(buf);
    314 							zzmore();
    315 							UsedOldStyleAttrib = 1;
    316 							if ( UsedNewStyleLabel )
    317 								err("cannot mix old-style $i with new-style labels");
    318 							}
    319 							>>
    320 #token "$[0-9]+."			<<{
    321 							static char buf[100];
    322                             numericActionLabel=1;       /* MR10 */
    323 							if ( strlen(zzbegexpr)>(size_t)85 )
    324 								fatal("$i.field attrib ref too big");
    325 							zzbegexpr[strlen(zzbegexpr)-1] = ' ';
    326 							set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction);
    327 							if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).",
    328 										BlkLevel-1,zzbegexpr+1);
    329 							else sprintf(buf,"_t%d%s.",
    330 										BlkLevel-1,zzbegexpr+1);
    331 							zzreplstr(buf);
    332 							zzmore();
    333 							UsedOldStyleAttrib = 1;
    334 							if ( UsedNewStyleLabel )
    335 								err("cannot mix old-style $i with new-style labels");
    336 							}
    337 							>>
    338 #token "$[0-9]+.[0-9]+"		<<{
    339 							static char buf[100];
    340 							static char i[20], j[20];
    341 							char *p,*q;
    342                             numericActionLabel=1;       /* MR10 */
    343 							if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big");
    344 							for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) {
    345 								if ( q == &i[20] )
    346 									 fatalFL("i of $i.j attrib ref too big",
    347 											 FileStr[CurFile], zzline );
    348 								*q++ = *p;
    349 							}
    350 							*q = '\0';
    351 							for (p++, q= &j[0]; *p!='\0'; p++) {
    352 								if ( q == &j[20] )
    353 									fatalFL("j of $i.j attrib ref too big",
    354 											FileStr[CurFile], zzline );
    355 								*q++ = *p;
    356 							}
    357 							*q = '\0';
    358 							if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j);
    359 							else sprintf(buf,"_t%s%s",i,j);
    360 							zzreplstr(buf);
    361 							zzmore();
    362 							UsedOldStyleAttrib = 1;
    363 							if ( UsedNewStyleLabel )
    364 								err("cannot mix old-style $i with new-style labels");
    365 							}
    366 							>>
    367 #token "$[_a-zA-Z][_a-zA-Z0-9]*"
    368 							<<{ static char buf[300]; LabelEntry *el;
    369 							zzbegexpr[0] = ' ';
    370 							if ( CurRule != NULL &&
    371 								 strcmp(CurRule, &zzbegexpr[1])==0 ) {
    372 								if ( !GenCC ) zzreplstr("zzaRet");
    373 							}
    374 							else if ( CurRetDef != NULL &&
    375 									  strmember(CurRetDef, &zzbegexpr[1])) {
    376 								 if ( hasMultipleOperands( CurRetDef ) ) {
    377 									require (strlen(zzbegexpr)<=(size_t)285,
    378 											 "$retval attrib ref too big");
    379 									sprintf(buf,"_retv.%s",&zzbegexpr[1]);
    380 									zzreplstr(buf);
    381 								}
    382 								else zzreplstr("_retv");
    383 							}
    384 							else if ( CurParmDef != NULL &&
    385 									  strmember(CurParmDef, &zzbegexpr[1])) {
    386 								;
    387 							}
    388 							else if ( Elabel==NULL ) {
    389 								{ err("$-variables in actions outside of rules are not allowed"); }
    390 							} else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) {
    391 /* MR10 */
    392 /* MR10 */                      /* element labels might exist without an elem when */
    393 /* MR10 */                      /*  it is a forward reference (to a rule)          */
    394 /* MR10 */
    395 /* MR10 */						if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) )
    396 /* MR10 */							{ err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); }
    397 /* MR10 */
    398 /* MR10 */						if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) {
    399 /* MR10 */                          err("You can no longer use attributes returned by rules when also using ASTs");
    400 /* MR10 */                          err("   Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...\>\>\")");
    401 /* MR10 */                      };
    402 /* MR10 */
    403 /* MR10 */                      /* keep track of <<... $label ...>> for semantic predicates in guess mode */
    404 /* MR10 */                      /* element labels contain pointer to the owners node                      */
    405 /* MR10 */
    406 /* MR10 */                      if (el->elem != NULL && el->elem->ntype == nToken) {
    407 /* MR10 */                        list_add(&CurActionLabels,el);
    408 /* MR10 */                      };
    409 							}
    410 							else
    411 								warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1]));
    412 							}
    413 							zzmore();
    414 							>>
    415 #token "#0"					<< zzreplstr("(*_root)"); zzmore(); chkGTFlag(); >>
    416 #token "#\[\]"				<< if ( GenCC ) {
    417                                     if (NewAST) zzreplstr("(newAST)");
    418                                         else zzreplstr("(new AST)");}
    419 							   else {zzreplstr("zzastnew()");} zzmore();
    420 							   chkGTFlag();
    421 							>>
    422 #token "#\(\)"				<< zzreplstr("NULL"); zzmore(); chkGTFlag(); >>
    423 #token "#[0-9]+"			<<{
    424 							static char buf[100];
    425 							if ( strlen(zzbegexpr)>(size_t)85 )
    426 								fatal("#i AST ref too big");
    427 							if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1);
    428 							else sprintf(buf,"zzastArg(%s)",zzbegexpr+1);
    429 							zzreplstr(buf);
    430 							zzmore();
    431 							set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions);
    432 							chkGTFlag();
    433  							}
    434 							>>
    435 
    436 /* MR14 Arpad Beszedes  26-May-98
    437         Add support for #line directives when antlr source is pre-processed
    438         #lexclass ACTIONS
    439 */
    440 
    441 #token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)"
    442         <<
    443         zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();
    444         getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);
    445         >>
    446 
    447 #token "#line ~[\n\r]* (\n|\r|\r\n)"
    448         <<
    449         zzline++; zzmore();
    450         >>
    451 
    452 /* MR14 end of a block to support #line in antlr source code */
    453 
    454 #token "#[_a-zA-Z][_a-zA-Z0-9]*"
    455 							<<
    456 							if ( !(strcmp(zzbegexpr, "#ifdef")==0 ||
    457 								 strcmp(zzbegexpr, "#if")==0 ||
    458 								 strcmp(zzbegexpr, "#else")==0 ||
    459 								 strcmp(zzbegexpr, "#endif")==0 ||
    460 								 strcmp(zzbegexpr, "#ifndef")==0 ||
    461 								 strcmp(zzbegexpr, "#define")==0 ||
    462 								 strcmp(zzbegexpr, "#pragma")==0 ||
    463 								 strcmp(zzbegexpr, "#undef")==0 ||
    464 								 strcmp(zzbegexpr, "#import")==0 ||
    465 								 strcmp(zzbegexpr, "#line")==0 ||
    466 								 strcmp(zzbegexpr, "#include")==0 ||
    467 								 strcmp(zzbegexpr, "#error")==0) )
    468 							{
    469 								static char buf[100];
    470 								sprintf(buf, "%s_ast", zzbegexpr+1);
    471 /* MR27 */						list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1));
    472 								zzreplstr(buf);
    473 								chkGTFlag();
    474 							}
    475 							zzmore();
    476 							>>
    477 #token "#\["				<<
    478 							pushint(']');
    479 							if ( GenCC ) {
    480                                 if (NewAST) zzreplstr("(newAST(");
    481                                     else zzreplstr("(new AST("); }
    482 							else zzreplstr("zzmk_ast(zzastnew(),");
    483 							zzmore();
    484 							chkGTFlag();
    485 							>>
    486 #token "#\("				<<
    487 							pushint('}');
    488 							if ( GenCC ) {
    489 								if (tmakeInParser) {
    490 									zzreplstr("tmake(");
    491 								}
    492 								else {
    493 									zzreplstr("ASTBase::tmake(");
    494 								}
    495 							}
    496 							else {
    497 								zzreplstr("zztmake(");
    498 							}
    499 							zzmore();
    500 							chkGTFlag();
    501 							>>
    502 #token "#"					<< zzmore(); >>
    503 #token "\)"					<<
    504 							if ( istackempty() )
    505 								zzmore();
    506 							else if ( topint()==')' ) {
    507 								popint();
    508 							}
    509 							else if ( topint()=='}' ) {
    510 								popint();
    511 								/* terminate #(..) */
    512 								zzreplstr(", NULL)");
    513 							}
    514 							zzmore();
    515 							>>
    516 #token "\["					<<
    517 							pushint('|');	/* look for '|' to terminate simple [...] */
    518 							zzmore();
    519 							>>
    520 #token "\("					<<
    521 							pushint(')');
    522 							zzmore();
    523 							>>
    524 
    525 #token "\\\]"				<< zzreplstr("]");  zzmore(); >>
    526 #token "\\\)"				<< zzreplstr(")");  zzmore(); >>
    527 
    528 /* MR1	10-Apr-97  MR1  Previously unable to put right shift operator	*/
    529 /* MR1					in DLG action			*/
    530 
    531 #token "\\>"	<< if (! tokenActionActive) zzreplstr(">");	 /* MR1 */
    532 		   zzmore();				         /* MR1 */
    533 		>>					         /* MR1	*/
    534 
    535 
    536 #token "'"					<< zzmode(ACTION_CHARS); zzmore();>>
    537 #token "\""					<< zzmode(ACTION_STRINGS); zzmore();>>
    538 #token "\\$"				<< zzreplstr("$");  zzmore(); >>
    539 #token "\\#"				<< zzreplstr("#");  zzmore(); >>
    540 #token "\\(\n|\r|\r\n)"		<< zzline++; zzmore(); >>
    541 #token "\\~[\]\)>$#]"		<< zzmore(); >> /* escaped char, always ignore */
    542 #token "/"					<< zzmore(); >>
    543 #token "/\*"				<< zzmode(ACTION_COMMENTS); zzmore(); >>
    544 #token "\*/"				<< warn("Missing /*; found dangling */ in action"); zzmore(); >>
    545 #token "//"					<< zzmode(ACTION_CPP_COMMENTS); zzmore(); >>
    546 #token "~[\n\r\)\(\\$#\>\]\[\"'/]+" << zzmore(); >>
    547 
    548 #lexclass START
    549 #token "[\t\ ]+"			<< zzskip(); >>				/* Ignore White */
    550 #token "\n|\r|\r\n"	   		<< zzline++; zzskip(); >>	/* Track Line # */
    551 #token "\["                 << zzmode(ACTIONS); zzmore();
    552                                istackreset();
    553                                pushint(']'); >>
    554 #token "\<\<"               << action_file=CurFile; action_line=zzline;
    555                                zzmode(ACTIONS); zzmore();
    556                                list_free(&CurActionLabels,0);       /* MR10 */
    557                                numericActionLabel=0;                /* MR10 */
    558                                istackreset();
    559                                pushint('>'); >>
    560 #token "\""					<< zzmode(STRINGS); zzmore(); >>
    561 #token "/\*"				<< zzmode(COMMENTS); zzskip(); >>
    562 #token "\*/"				<< warn("Missing /*; found dangling */"); zzskip(); >>
    563 #token "//"					<< zzmode(CPP_COMMENTS); zzskip(); >>
    564 
    565 /* MR14 Arpad Beszedes  26-May-98
    566         Add support for #line directives when antlr source is pre-processed
    567         #lexclass START
    568 */
    569 
    570 #token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)"
    571         <<
    572         zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore();
    573         getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr);
    574         >>
    575 
    576 #token "#line ~[\n\r]* (\n|\r|\r\n)"
    577         <<
    578         zzline++; zzmore();
    579         >>
    580 
    581 /* MR14 end of a block to support #line in antlr source code */
    582 
    583 /*                                                                          */
    584 /*  8-Apr-97	Regularize escape sequence for ">>"                         */
    585 /*			appearing in string literals                                    */
    586 /*                                                                          */
    587 
    588 #token "\>\>"			<< warn("Missing <<; found dangling \>\>"); zzskip(); >> /* MR1 */
    589 #token WildCard "."
    590 #token "\@"			<<FoundException = 1;		/* MR6 */
    591     				  FoundAtOperator = 1;>>	/* MR6 */
    592 #token Eof					"@"
    593 							<<	/* L o o k  F o r  A n o t h e r  F i l e */
    594 							{
    595 							FILE *new_input;
    596 							new_input = NextFile();
    597 							if ( new_input == NULL ) { NLA=Eof; return; }
    598 							fclose( input );
    599 							input = new_input;
    600 							zzrdstream( input );
    601 							zzskip();	/* Skip the Eof (@) char i.e continue */
    602 							}
    603 							>>
    604 
    605 #token LABEL
    606 
    607 #errclass "grammar-element" { element }
    608 #errclass "meta-symbol"		{ "\}" "!" ";" "\|" "\~" "^" "\)" }
    609 
    610 #token Pragma			"{\\}#pragma"			/* MR21 */
    611 #token FirstSetSymbol	"{\\}#FirstSetSymbol"	/* MR21 */
    612 /*
    613  * Get a grammar -- Build a list of rules like:
    614  *
    615  *	o-->Rule1--o
    616  *	|
    617  *	o-->Rule2--o
    618  *	|
    619  *	...
    620  *	|
    621  *	o-->RuleN--o
    622  */
    623 
    624 /* rule grammar */
    625 
    626 grammar :	<<Graph g;>>
    627 			(	"{\\}#header" Action    /* MR13 */
    628 				<<
    629 				if ( HdrAction==NULL ) {
    630 				HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
    631 				require(HdrAction!=NULL, "rule grammar: cannot allocate header action");
    632 				strcpy(HdrAction, LATEXT(1));
    633 				}
    634 				else warn("additional #header statement ignored");
    635 				>>
    636             |   "{\\}#first" Action
    637 				<<
    638     				if ( FirstAction==NULL ) {
    639         				FirstAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
    640         				require(FirstAction!=NULL, "rule grammar: cannot allocate #first action");
    641         				strcpy(FirstAction, LATEXT(1));
    642     				} else {
    643                         warn("additional #first statement ignored");
    644                     };
    645 				>>
    646 
    647 			|	"{\\}#parser" QuotedTerm
    648 				<<
    649 				if ( GenCC ) {
    650 					warn("#parser meta-op incompatible with -CC; ignored");
    651 				}
    652 				else {
    653 					if ( strcmp(ParserName,"zzparser")==0 ) {
    654 						ParserName=StripQuotes(mystrdup(LATEXT(1)));
    655 						if ( RulePrefix[0]!='\0' )
    656 						{
    657 							warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored");
    658 							RulePrefix[0]='\0';
    659 						}
    660 					}
    661 					else warn("additional #parser statement ignored");
    662 				}
    663 				>>
    664 			|	"{\\}#tokdefs" QuotedTerm
    665 				<<{
    666 				char *fname;
    667 				zzantlr_state st; FILE *f; struct zzdlg_state dst;
    668 				UserTokenDefsFile = mystrdup(LATEXT(1));
    669 				zzsave_antlr_state(&st);
    670 				zzsave_dlg_state(&dst);
    671 				fname = mystrdup(LATEXT(1));
    672 				f = fopen(StripQuotes(fname), "r");
    673 				if ( f==NULL ) {warn(eMsg1("cannot open token defs file '%s'", fname+1));}
    674 				else {
    675 					ANTLRm(enum_file(fname+1), f, PARSE_ENUM_FILE);
    676 					UserDefdTokens = 1;
    677 				}
    678 				zzrestore_antlr_state(&st);
    679 				zzrestore_dlg_state(&dst);
    680 				}>>
    681 			)*
    682 			(	Action
    683 				<<{
    684 				UserAction *ua = newUserAction(LATEXT(1));
    685 				ua->file = action_file; ua->line = action_line;
    686 				if ( class_nest_level>0 ) list_add(&class_before_actions, ua);
    687 				else list_add(&BeforeActions, ua);
    688 				}>>
    689 			|	laction
    690 			|	lmember				/* MR1 */
    691 			|	lprefix				/* MR1 */
    692 			|	aLexclass
    693 			|	token
    694 			|	error
    695 			|	tclass
    696             |   aPred               /* MR11 */
    697 			|	default_exception_handler
    698 			|	class_def
    699 			|	"\}"
    700 				<<
    701 				if ( class_nest_level==0 )
    702 					warn("missing class definition for trailing '}'");
    703 				class_nest_level--;
    704 				>>
    705 			)*
    706 
    707 			rule		<<g=$3; SynDiag = (Junction *) $3.left;>>
    708 			(	rule
    709 
    710                 	<<if ( $1.left!=NULL ) {
    711                         g.right = NULL;
    712 
    713 /* MR21a */             /*  Avoid use of a malformed graph when CannotContinue */
    714 /* MR21a */             /*  is already set                                     */
    715 /* MR21a */
    716 /* MR21a */             if (! (CannotContinue && g.left == NULL)) {
    717 /* MR21a */               g = Or(g, $1);
    718 /* MR21a */             }
    719 /* MR21a */		      }
    720                     >>
    721 
    722 			|	aLexclass
    723 			|	token
    724 			|	error
    725 			|	tclass
    726             |   aPred               /* MR11 */
    727 			|	class_def
    728 			|	"\}"
    729 				<<
    730 				if ( class_nest_level==0 )
    731 					warn("missing class definition for trailing '}'");
    732 				class_nest_level--;
    733 				>>
    734 			)*
    735 			(	Action
    736 				<<{
    737 				UserAction *ua = newUserAction(LATEXT(1));
    738 				ua->file = action_file; ua->line = action_line;
    739 				if ( class_nest_level>0 ) list_add(&class_after_actions, ua);
    740 				else list_add(&AfterActions, ua);
    741 				}>>
    742 			|	laction
    743 			|	lmember				/* MR1 */
    744 			|	lprefix				/* MR1 */
    745 			|	error
    746 			|	tclass
    747 			|	class_def
    748             |   aPred               /* MR11 */
    749 			|	"\}"
    750 				<<
    751 				if ( class_nest_level==0 )
    752 					warn("missing class definition for trailing '}'");
    753 				class_nest_level--;
    754 				>>
    755 			)*
    756 			Eof
    757 		;
    758 		<<CannotContinue=TRUE;>>
    759 
    760 /* rule class_def */
    761 
    762 class_def
    763 	:	<<int go=1; char name[MaxRuleName+1];>>
    764 		"class"
    765 		(	NonTerminal		<<if(go) strncpy(name,LATEXT(1),MaxRuleName);>>
    766 		|	TokenTerm		<<if(go) strncpy(name,LATEXT(1),MaxRuleName);>>
    767 		)
    768 		<<
    769 		if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0
    770 			 && GenCC ) {
    771 			err("only one grammar class allowed in this release");
    772 			go = 0;
    773 		}
    774 		else strcpy(CurrentClassName, name);
    775 		>>
    776 		<<if ( !GenCC ) { err("class meta-op used without C++ option"); }>>
    777 
    778 /* MR10 */  (~ "\{"
    779 /* MR10 */            <<if (ClassDeclStuff == NULL) {
    780 /* MR10 */                   ClassDeclStuff=(char *)calloc(MaxClassDeclStuff+1,sizeof(char));
    781 /* MR10 */              };
    782 /* MR10 */              strncat(ClassDeclStuff," ",MaxClassDeclStuff);
    783 /* MR10 */              strncat(ClassDeclStuff,LATEXT(1),MaxClassDeclStuff);
    784 /* MR22 */              do {
    785 /* MR22 */                if (0 == strcmp(LATEXT(1),"public")) break;
    786 /* MR22 */                if (0 == strcmp(LATEXT(1),"private")) break;
    787 /* MR22 */                if (0 == strcmp(LATEXT(1),"protected")) break;
    788 /* MR22 */                if (0 == strcmp(LATEXT(1),"virtual")) break;
    789 /* MR22 */                if (0 == strcmp(LATEXT(1),",")) break;
    790 /* MR22 */                if (0 == strcmp(LATEXT(1),":")) break;
    791 /* MR22 */                if (BaseClassName != NULL) break;
    792 /* MR22 */                BaseClassName=(char *)calloc(strlen(LATEXT(1))+1,sizeof(char));
    793 /* MR22 */                require(BaseClassName!=NULL, "rule grammar: cannot allocate base class name");
    794 /* MR22 */				  strcpy(BaseClassName,LATEXT(1));
    795 /* MR22 */              } while (0);
    796 /* MR10 */            >>
    797 /* MR10 */  )*
    798 
    799 		"\{"
    800 		<<
    801 		no_classes_found = 0;
    802 		if ( class_nest_level>=1 ) {warn("cannot have nested classes");}
    803 		else class_nest_level++;
    804 		>>
    805 	;
    806 	<<CannotContinue=TRUE;>>
    807 
    808 /*
    809  * Build -o-->o-R-o-->o-	where -o-R-o- is the block from rule 'block'.
    810  * Construct the RuleBlk front and EndRule node on the end of the
    811  * block.  This is used to add FOLLOW pointers to the rule end.  Add the
    812  * new rule name to the Rname hash table and sets its rulenum.
    813  * Store the parameter definitions if any are found.
    814  *
    815  * Note that locks are required on the RuleBlk and EndRule nodes to thwart
    816  * infinite recursion.
    817  *
    818  * Return the left graph pointer == NULL to indicate error/dupl rule def.
    819  */
    820 
    821 /* rule rule */
    822 
    823 rule	:	<<
    824 
    825 			ExceptionGroup *eg;
    826 			RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e;
    827 			set toksrefd, rulesrefd;
    828 			char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL;
    829 			CurExGroups = NULL;
    830 			CurElementLabels = NULL;
    831 			CurAstLabelsInActions = NULL; /* MR27 */
    832 			/* We want a new element label hash table for each rule */
    833 			if ( Elabel!=NULL ) killHashTable(Elabel);
    834 			Elabel = newHashTable();
    835 			attribsRefdFromAction = empty;
    836 			>>
    837 			NonTerminal
    838 			<<q=NULL;
    839 			  if ( hash_get(Rname, LATEXT(1))!=NULL ) {
    840 				  err(eMsg1("duplicate rule definition: '%s'",LATEXT(1)));
    841 				  CannotContinue=TRUE;
    842 			  }
    843 			  else
    844 			  {
    845 			  	  q = (RuleEntry *)hash_add(Rname,
    846 											LATEXT(1),
    847 											(Entry *)newRuleEntry(LATEXT(1)));
    848 			      CurRule = q->str;
    849 			  }
    850 			  CurRuleNode = q;
    851 			  f = CurFile; l = zzline;
    852 			  NumRules++;
    853 			>>
    854 			{	"!"  <<if ( q!=NULL ) q->noAST = TRUE;>> }
    855 			{	<<;>>
    856 				{"\<"}
    857 				PassAction
    858 				<<	pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
    859 					require(pdecl!=NULL, "rule rule: cannot allocate param decl");
    860 					strcpy(pdecl, LATEXT(1));
    861 					CurParmDef = pdecl;
    862 				>>
    863 			}
    864 			{	"\>"
    865 				PassAction
    866 				<<	ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
    867 				    require(ret!=NULL, "rule rule: cannot allocate ret type");
    868 					strcpy(ret, LATEXT(1));
    869  					CurRetDef = ret;
    870 				>>
    871 			}
    872 			{ QuotedTerm <<if ( q!=NULL ) q->egroup=mystrdup(LATEXT(1));>> }
    873 			<<
    874 			if ( GenEClasseForRules && q!=NULL ) {
    875 				e = newECnode;
    876 				require(e!=NULL, "cannot allocate error class node");
    877 				if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);}
    878 				else a = q->egroup;
    879 				if ( Tnum( a ) == 0 )
    880 				{
    881 					e->tok = addTname( a );
    882 					list_add(&eclasses, (char *)e);
    883 					if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);
    884 					/* refers to itself */
    885 					list_add(&(e->elist), mystrdup(q->str));
    886 				}
    887 				else {
    888 					warn(eMsg1("default errclass for '%s' would conflict with token/errclass/tokclass",a));
    889 					if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]);
    890 					free((char *)e);
    891 				}
    892 			}
    893 			>>
    894 			<<BlkLevel++;
    895               if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply");
    896 /* MR23 */    CurBlockID_array[BlkLevel] = CurBlockID;
    897 /* MR23 */    CurAltNum_array[BlkLevel] = CurAltNum;
    898             >>
    899 
    900 			":" <<inAlt=1;>>
    901 			block[&toksrefd, &rulesrefd]
    902 			<<r = makeBlk($7,0, NULL /* pFirstSetSymbol */ );
    903 			  CurRuleBlk = (Junction *)r.left;
    904 			  CurRuleBlk->blockid = CurBlockID;
    905 			  CurRuleBlk->jtype = RuleBlk;
    906 			  if ( q!=NULL ) CurRuleBlk->rname = q->str;
    907 			  CurRuleBlk->file = f;
    908 			  CurRuleBlk->line = l;
    909 			  CurRuleBlk->pdecl = pdecl;
    910 			  CurRuleBlk->ret = ret;
    911 			  CurRuleBlk->lock = makelocks();
    912 			  CurRuleBlk->pred_lock = makelocks();
    913 			  CurRuleBlk->tokrefs = toksrefd;
    914 			  CurRuleBlk->rulerefs = rulesrefd;
    915 			  p = newJunction();	/* add EndRule Node */
    916 			  ((Junction *)r.right)->p1 = (Node *)p;
    917 			  r.right = (Node *) p;
    918 			  p->jtype = EndRule;
    919 			  p->lock = makelocks();
    920 			  p->pred_lock = makelocks();
    921 			  CurRuleBlk->end = p;
    922 			  if ( q!=NULL ) q->rulenum = NumRules;
    923 			  $7 = r;
    924 			>>
    925 			<<
    926                 /* MR23 */      CurBlockID_array[BlkLevel] = (-1);
    927                 /* MR23 */      CurAltNum_array[BlkLevel] = (-1);
    928                 --BlkLevel;
    929             >>
    930             <<altFixup();leFixup();egFixup();>>                      /* MR7 */
    931 			";" <<inAlt=0;>>
    932 			{	Action
    933 				<<	a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
    934 					require(a!=NULL, "rule rule: cannot allocate error action");
    935 					strcpy(a, LATEXT(1));
    936 					CurRuleBlk->erraction = a;
    937 				>>
    938 			}
    939 			(	exception_group > [eg]
    940 				<<if ( eg!=NULL ) {
    941 					list_add(&CurExGroups, (void *)eg);
    942 					if (eg->label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1;
    943 			    }
    944 				>>
    945 			)*
    946 			<<if ( q==NULL ) $0.left = NULL; else $0 = $7;>>
    947 			<<CurRuleBlk->exceptions = CurExGroups;>>
    948 			<<CurRuleBlk->el_labels = CurElementLabels;>>
    949 			<<CurRuleNode->ast_labels_in_actions = CurAstLabelsInActions;>> /* MR27 */
    950 			<<CurRuleNode = NULL;>> /* MR27 Moved */
    951 		;
    952 		<<CannotContinue=TRUE;>>
    953 
    954 /*
    955  * pragma	:	"{\\}#pragma" "dup\-labeled\-tokens"
    956  *			<<Pragma_DupLabeledTokens=1;>>
    957  *		;
    958  */
    959 
    960 /* rule laction */
    961 
    962 laction	:	<<char *a;>>
    963 
    964 			"{\\}#lexaction"
    965 			Action
    966 			<<
    967 			a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
    968 			require(a!=NULL, "rule laction: cannot allocate action");
    969 			strcpy(a, LATEXT(1));
    970 			list_add(&LexActions, a);
    971 			>>
    972 		;
    973 		<<CannotContinue=TRUE;>>
    974 
    975 /* MR1									    */
    976 /* MR1  11-Apr-97	Provide mechanism for inserting code into DLG class */
    977 /* MR1			  via #lexmember <<....>> & #lexprefix <<...>>      */
    978 /* MR1									    */
    979 
    980 /* rule lmember */
    981 
    982 lmember:	<<char *a;>>					     /* MR1 */
    983 
    984 /* MR1 */		"{\\}#lexmember"
    985 /* MR1 */		Action
    986 /* MR1 */		<<
    987 /* MR1 */		if (! GenCC) {
    988 /* MR1 */		  err("Use #lexmember only in C++ mode (to insert code in DLG class header");
    989 /* MR1 */	        } else {
    990 /* MR1 */		  a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
    991 /* MR1 */		  require(a!=NULL, "rule lmember: cannot allocate action");
    992 /* MR1 */		  strcpy(a, LATEXT(1));
    993 /* MR1 */		  list_add(&LexMemberActions, a);
    994 /* MR1 */		};
    995 /* MR1 */		>>
    996 /* MR1 */	;
    997 /* MR1 */	<<CannotContinue=TRUE;>>
    998 
    999 /* rule lprefix */
   1000 
   1001 lprefix:	<<char *a;>>					     /* MR1 */
   1002 
   1003 /* MR1 */		"{\\}#lexprefix"
   1004 /* MR1 */		Action
   1005 /* MR1 */		<<
   1006 /* MR1 */		if (! GenCC) {
   1007 /* MR1 */		  err("Use #lexprefix only in C++ mode (to insert code in DLG class header");
   1008 /* MR1 */	        } else {
   1009 /* MR1 */		  a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
   1010 /* MR1 */		  require(a!=NULL, "rule lprefix: cannot allocate action");
   1011 /* MR1 */		  strcpy(a, LATEXT(1));
   1012 /* MR1 */		  list_add(&LexPrefixActions, a);
   1013 /* MR1 */		};
   1014 /* MR1 */		>>
   1015 /* MR1 */	;
   1016 /* MR1 */	<<CannotContinue=TRUE;>>
   1017 
   1018 /*
   1019  * #pred upper        <<isupper()>>?            predicate literal
   1020  * #pred lower        <<islower()>>?            predicate literal
   1021  * #pred up_or_low    upper || lower            predicate expression
   1022  *                                                concealed interdependence
   1023  * #pred up_or_low_2  <<isletter()>>?  A || B   predicate literal equals predicate expr
   1024  *                                                analyze using lower||upper
   1025  *                                                generate using isLetter()
   1026  */
   1027 
   1028 /* rule aPref */
   1029 
   1030 aPred:  <<PredEntry     *predEntry=NULL;
   1031           char          *name=NULL;
   1032           Predicate     *predExpr=NULL;
   1033           char          *predLiteral=NULL;
   1034           int           save_file;
   1035           int           save_line;
   1036           int           predExprPresent=0;
   1037         >>
   1038 
   1039         "{\\}#pred"
   1040 
   1041         <<
   1042           MR_usingPredNames=1;      /* will need to use -mrhoist version of genPredTree */
   1043         >>
   1044 
   1045                                     /* used to allow NonTerminal but it caused problems
   1046                                        when a rule name immediately followed a #pred statement */
   1047 
   1048         TokenTerm     <<name=mystrdup(LATEXT(1));>>
   1049 
   1050           <<
   1051             /* don't free - referenced in predicates */
   1052 
   1053             CurPredName=(char *)calloc(1,strlen(name) + 10);
   1054             strcat(CurPredName,"#pred ");
   1055             strcat(CurPredName,name);
   1056 
   1057             predEntry=(PredEntry *) hash_get(Pname,name);
   1058             if (predEntry != NULL) {
   1059               warnFL(eMsg1("#pred %s previously defined - ignored",name),
   1060                                               FileStr[action_file],action_line);
   1061               name=NULL;
   1062             };
   1063           >>
   1064 
   1065         (
   1066 
   1067             Pred    <<predLiteral=mystrdup(LATEXT(1));
   1068                       save_line=action_line;
   1069                       save_file=action_file;
   1070                     >>
   1071 
   1072               {
   1073                     predOrExpr>[predExpr]   <<predExprPresent=1;>>
   1074               }
   1075 
   1076               <<if (predLiteral != NULL && name != NULL) {
   1077 
   1078                       /*
   1079                        *  predExpr may be NULL due to syntax errors
   1080                        *    or simply omitted by the user
   1081                       */
   1082 
   1083                       predEntry=newPredEntry(name);
   1084                       predEntry->file=save_file;
   1085                       predEntry->line=save_line;
   1086                       predExpr=MR_predFlatten(predExpr);
   1087                       predEntry->predLiteral=predLiteral;
   1088                       if (! predExprPresent || predExpr == NULL) {
   1089                         predExpr=new_pred();
   1090                         predExpr->expr=predLiteral;
   1091                         predExpr->source=newActionNode();
   1092                         predExpr->source->action=predExpr->expr;
   1093                         predExpr->source->rname=CurPredName;
   1094                         predExpr->source->line=action_line;
   1095                         predExpr->source->file=action_file;
   1096                         predExpr->source->is_predicate=1;
   1097                         predExpr->k=predicateLookaheadDepth(predExpr->source);
   1098                       };
   1099                       predEntry->pred=predExpr;
   1100                       hash_add(Pname,name,(Entry *)predEntry);
   1101                       predExpr=NULL;
   1102                 };
   1103                 predicate_free(predExpr);
   1104               >>
   1105 
   1106             |
   1107                <<save_line=zzline; save_file=CurFile;>>
   1108 
   1109                 predOrExpr>[predExpr]
   1110 
   1111               <<if (predExpr != NULL && name != NULL) {
   1112                   predEntry=newPredEntry(name);
   1113                   predEntry->file=CurFile;
   1114                   predEntry->line=zzline;
   1115                   predExpr=MR_predFlatten(predExpr);
   1116                   predEntry->pred=predExpr;
   1117                   hash_add(Pname,name,(Entry *)predEntry);
   1118                   predExpr=NULL;
   1119                 };
   1120                 predicate_free(predExpr);
   1121               >>
   1122         )
   1123         {";"}
   1124 ;
   1125 
   1126 /* fail */
   1127 
   1128 <<predicate_free(predExpr);
   1129 >>
   1130 
   1131 /* rule predOrExpr */
   1132 
   1133 predOrExpr>[Predicate *result] :
   1134             <<Predicate     *ORnode;
   1135               Predicate     *predExpr;
   1136               Predicate     **tail=NULL;
   1137             >>
   1138         predAndExpr>[predExpr]
   1139             <<
   1140                 ORnode=new_pred();
   1141                 ORnode->expr=PRED_OR_LIST;
   1142                 if (predExpr != NULL) {
   1143                     ORnode->down=predExpr;
   1144                     tail=&predExpr->right;
   1145                 };
   1146             >>
   1147         ( "\|\|"  predAndExpr>[predExpr]
   1148             <<
   1149                 if (predExpr != NULL) {
   1150                     *tail=predExpr;
   1151                     tail=&predExpr->right;
   1152                 };
   1153             >>
   1154         )*
   1155         <<
   1156             $result=ORnode;
   1157             ORnode=NULL;
   1158         >>
   1159 ;
   1160 
   1161 /* fail */
   1162 
   1163 <<predicate_free(ORnode);>>
   1164 
   1165 /* rule predAndExpr */
   1166 
   1167 predAndExpr>[Predicate *result] :
   1168             <<Predicate     *ANDnode;
   1169               Predicate     *predExpr;
   1170               Predicate     **tail=NULL;
   1171             >>
   1172         predPrimary>[predExpr]
   1173             <<
   1174                 ANDnode=new_pred();
   1175                 ANDnode->expr=PRED_AND_LIST;
   1176                 if (predExpr != NULL) {
   1177                     ANDnode->down=predExpr;
   1178                     tail=&predExpr->right;
   1179                 };
   1180             >>
   1181         ( "&&"  predPrimary>[predExpr]
   1182             <<
   1183                 if (predExpr != NULL) {
   1184                     *tail=predExpr;
   1185                     tail=&predExpr->right;
   1186                 };
   1187             >>
   1188         )*
   1189         <<
   1190             $result=ANDnode;
   1191             ANDnode=NULL;
   1192         >>
   1193 ;
   1194 
   1195 /* fail */
   1196 
   1197 <<predicate_free(ANDnode);>>
   1198 
   1199 
   1200 /* rule predPrimary */
   1201 
   1202 predPrimary>[Predicate *result] :
   1203             <<
   1204               char          *name=NULL;
   1205               PredEntry     *predEntry=NULL;
   1206               Predicate     *predExpr=NULL;
   1207             >>
   1208 
   1209         TokenTerm            <<name=mystrdup(LATEXT(1));>>
   1210 
   1211             <<
   1212                 predEntry=(PredEntry *) hash_get(Pname,name);
   1213                 if (predEntry == NULL) {
   1214                   warnFL(eMsg1("no previously defined #pred with name \"%s\"",name),
   1215                         FileStr[CurFile],zzline);
   1216                   name=NULL;
   1217                   $result=NULL;
   1218                 } else {
   1219                   predExpr=predicate_dup(predEntry->pred);
   1220                   predExpr->predEntry=predEntry;
   1221                   $result=predExpr;
   1222                 };
   1223             >>
   1224 
   1225         | "\(" predOrExpr>[predExpr] "\)"
   1226             <<
   1227                 $result=predExpr;
   1228             >>
   1229 
   1230         | "!" predPrimary>[predExpr]
   1231             <<
   1232                 predExpr->inverted=!predExpr->inverted;
   1233                 $result=predExpr;
   1234             >>
   1235 ;
   1236 
   1237 /* fail */  <<
   1238               predicate_free(predExpr);
   1239             >>
   1240 
   1241 /* rule aLexclass */
   1242 
   1243 aLexclass:	"{\\}#lexclass" TokenTerm <<lexclass(mystrdup(LATEXT(1)));>>
   1244 		;
   1245 		<<CannotContinue=TRUE;>>
   1246 
   1247 /* rule error */
   1248 
   1249 error	:	<<char *t=NULL; ECnode *e; int go=1; TermEntry *p;>>
   1250 			"{\\}#errclass"
   1251 			(<<;>>	TokenTerm  <<t=mystrdup(LATEXT(1));>>
   1252 			|		QuotedTerm <<t=mystrdup(LATEXT(1));>>
   1253 			)
   1254 			<<e = newECnode;
   1255 			  require(e!=NULL, "cannot allocate error class node");
   1256 			  e->lexclass = CurrentLexClass;
   1257 			  if ( Tnum( (t=StripQuotes(t)) ) == 0 )
   1258 			  {
   1259 				if ( hash_get(Texpr, t) != NULL )
   1260 					warn(eMsg1("errclass name conflicts with regular expression  '%s'",t));
   1261 			  	e->tok = addTname( t );
   1262 				set_orel(e->tok, &imag_tokens);
   1263 				require((p=(TermEntry *)hash_get(Tname, t)) != NULL,
   1264 						"hash table mechanism is broken");
   1265 				p->classname = 1;	/* entry is errclass name, not token */
   1266 				list_add(&eclasses, (char *)e);
   1267 			  }
   1268 			  else
   1269 			  {
   1270 			  	warn(eMsg1("redefinition of errclass or conflict w/token or tokclass '%s'; ignored",t));
   1271 				free( (char *)e );
   1272 				go=0;
   1273 			  }
   1274 			>>
   1275 			"\{"
   1276 				( NonTerminal <<if ( go ) t=mystrdup(LATEXT(1));>>
   1277 				| TokenTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
   1278 				| QuotedTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
   1279 				)
   1280 				<<if ( go ) list_add(&(e->elist), t);>>
   1281 				(
   1282 					( NonTerminal <<if ( go ) t=mystrdup(LATEXT(1));>>
   1283 					| TokenTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
   1284 					| QuotedTerm <<if ( go ) t=mystrdup(LATEXT(1));>>
   1285 					)
   1286 					<<if ( go ) list_add(&(e->elist), t);>>
   1287 				)*
   1288 			"\}"
   1289 		;
   1290 		<<CannotContinue=TRUE;>>
   1291 
   1292 /* rule tclass */
   1293 
   1294 tclass	:	<<char *t=NULL; TCnode *e; int go=1,tok,totok; TermEntry *p, *term, *toterm;>>
   1295             <<char *akaString=NULL; int save_file; int save_line;>>
   1296             <<char *totext=NULL; >>
   1297 			"{\\}#tokclass" TokenTerm <<t=mystrdup(LATEXT(1));>>
   1298 			<<e = newTCnode;
   1299 			  require(e!=NULL, "cannot allocate token class node");
   1300 			  e->lexclass = CurrentLexClass;
   1301 			  if ( Tnum( t ) == 0 )
   1302 			  {
   1303 			  	e->tok = addTname( t );
   1304 				set_orel(e->tok, &imag_tokens);
   1305 				set_orel(e->tok, &tokclasses);
   1306 				require((p=(TermEntry *)hash_get(Tname, t)) != NULL,
   1307 						"hash table mechanism is broken");
   1308 				p->classname = 1;	/* entry is class name, not token */
   1309 				p->tclass = e;		/* save ptr to this tclass def */
   1310 				list_add(&tclasses, (char *)e);
   1311 			  }
   1312 			  else
   1313 			  {
   1314 			  	warn(eMsg1("redefinition of tokclass or conflict w/token '%s'; ignored",t));
   1315 				free( (char *)e );
   1316 				go=0;
   1317 			  }
   1318 			>>
   1319 /* MR23 */      {
   1320 /* MR23 */          "\("
   1321 /* MR23 */          QuotedTerm
   1322 /* MR23 */                 <<akaString=mystrdup(StripQuotes(LATEXT(1)));
   1323 /* MR11 */                   save_file=CurFile;save_line=zzline;
   1324 /* MR23 */                 >>
   1325 /* MR23 */          "\)"
   1326 /* MR23 */      }
   1327 /* MR23 */
   1328 /* MR23 */
   1329 /* MR23 */		<<
   1330 /* MR23 */         if (p!= NULL && akaString != NULL) {
   1331 /* MR23 */           if (p->akaString != NULL) {
   1332 /* MR23 */             if (strcmp(p->akaString,akaString) != 0) {
   1333 /* MR23 */                warnFL(eMsg2("this #tokclass statment conflicts with a previous #tokclass %s(\"%s\") statement",
   1334 /* MR23 */                              t,p->akaString),
   1335 /* MR23 */			                    FileStr[save_file],save_line);
   1336 /* MR23 */             };
   1337 /* MR23 */            } else {
   1338 /* MR23 */              p->akaString=akaString;
   1339 /* MR23 */            };
   1340 /* MR23 */          };
   1341 /* MR23 */		>>
   1342 
   1343 			"\{"
   1344 				(
   1345     				( TokenTerm
   1346     				  <<if ( go ) {
   1347     					term = (TermEntry *) hash_get(Tname, LATEXT(1));
   1348     					if ( term==NULL && UserDefdTokens ) {
   1349     						err("implicit token definition not allowed with #tokdefs");
   1350     						go = 0;
   1351     					}
   1352     					else {t=mystrdup(LATEXT(1)); tok=addTname(LATEXT(1));}
   1353     					}>>
   1354 
   1355                         {
   1356                             ".."
   1357                             TokenTerm
   1358 
   1359             				  <<if ( go ) {
   1360                 					toterm = (TermEntry *) hash_get(Tname, LATEXT(1));
   1361                 					if ( toterm==NULL && UserDefdTokens ) {
   1362                 						err("implicit token definition not allowed with #tokdefs");
   1363                 						go = 0;
   1364                 					} else {
   1365                                         totext=mystrdup(LATEXT(1)); totok=addTname(LATEXT(1));
   1366                                     }
   1367             				    }
   1368                               >>
   1369                         }
   1370 
   1371     				| QuotedTerm
   1372     				  <<if ( go ) {
   1373     					term = (TermEntry *) hash_get(Texpr, LATEXT(1));
   1374     					if ( term==NULL && UserDefdTokens ) {
   1375     						err("implicit token definition not allowed with #tokdefs");
   1376     						go = 0;
   1377         					}
   1378     					else {t=mystrdup(LATEXT(1)); tok=addTexpr(LATEXT(1));}
   1379     					}>>
   1380     				)
   1381     				<<if ( go ) {
   1382                         if (totext == NULL) {
   1383                             list_add(&(e->tlist), t);
   1384                         } else {
   1385                             list_add(&(e->tlist),"..");
   1386                             list_add(&(e->tlist),t);
   1387                             list_add(&(e->tlist),totext);
   1388                         }
   1389                         totext=NULL;
   1390                       }
   1391                     >>
   1392 				)+  // MR15 Manfred Kogler - forbid empty #tokclass sets (was "+")
   1393 			"\}"
   1394 		;
   1395 		<<CannotContinue=TRUE;>>
   1396 
   1397 /* rule token */
   1398 
   1399 token	:	<<char *t=NULL, *e=NULL, *a=NULL; int tnum=0;>>
   1400             <<char *akaString=NULL; TermEntry *te;int save_file=0,save_line=0;>>           /* MR11 */
   1401 			"{\\}#token"
   1402 
   1403 /* MR1 10-Apr-97 MR1 Allow shift right operator in DLG actions		   */
   1404 /* MR1			Danger when parser feedback to lexer		           */
   1405 /* MR1	                                                               */
   1406 
   1407 			<<tokenActionActive=1;>>		                    /* MR1 */
   1408 			{	TokenTerm  <<t=mystrdup(LATEXT(1));>>
   1409 
   1410 /* MR11 */      {
   1411 /* MR11 */          "\("
   1412 /* MR11 */          QuotedTerm
   1413 /* MR11 */                 <<akaString=mystrdup(StripQuotes(LATEXT(1)));
   1414 /* MR11 */                   save_file=CurFile;save_line=zzline;
   1415 /* MR11 */                 >>
   1416 /* MR11 */          "\)"
   1417 /* MR11 */      }
   1418 
   1419 				{	"=" "[0-9]+"		/* define the token type number */
   1420 					<<tnum = atoi(LATEXT(1));>>
   1421 				}
   1422 			}
   1423 			{ QuotedTerm <<e=mystrdup(LATEXT(1));>> }
   1424 			{	Action
   1425 				<<
   1426 					a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
   1427 					require(a!=NULL, "rule token: cannot allocate action");
   1428 					strcpy(a, LATEXT(1));
   1429 				>>
   1430 			}
   1431 
   1432             { ";" }     /* MR11 */
   1433 
   1434 			<<chkToken(t, e, a, tnum);>>
   1435 
   1436             <<if (t != NULL) {
   1437                 te=(TermEntry *)hash_get(Tname,t);
   1438                 if (te != NULL && akaString != NULL) {
   1439                   if (te->akaString != NULL) {
   1440                     if (strcmp(te->akaString,akaString) != 0) {
   1441                       warnFL(eMsg2("this #token statment conflicts with a previous #token %s(\"%s\") statement",
   1442                                     t,te->akaString),
   1443                         FileStr[save_file],save_line);
   1444                     };
   1445                   } else {
   1446                     te->akaString=akaString;
   1447                   };
   1448                 };
   1449               };
   1450             >>
   1451 		;
   1452 		<<CannotContinue=TRUE;>>
   1453 
   1454 /* rule block */
   1455 
   1456 block[set *toksrefd, set *rulesrefd]
   1457 		:	<<
   1458     			Graph g, b;
   1459     			set saveblah;
   1460     			int saveinalt = inAlt;
   1461     			ExceptionGroup *eg;
   1462     			*$toksrefd = empty;
   1463     			*$rulesrefd = empty;
   1464     			set_clr(AST_nodes_refd_in_actions);
   1465     			CurBlockID++;
   1466 /* MR23 */      CurBlockID_array[BlkLevel] = CurBlockID;
   1467     			CurAltNum = 1;
   1468 /* MR23 */      CurAltNum_array[BlkLevel] = CurAltNum;
   1469     			saveblah = attribsRefdFromAction;
   1470     			attribsRefdFromAction = empty;
   1471 			>>
   1472 
   1473 			alt[toksrefd,rulesrefd]		<<b = g = $1;>>
   1474 
   1475 			<<
   1476 			if ( ((Junction *)g.left)->p1->ntype == nAction )
   1477 			{
   1478                 ActionNode *actionNode=(ActionNode *)
   1479                                          ( ( (Junction *)g.left) ->p1);
   1480 				if (!actionNode->is_predicate )
   1481 				{
   1482 					actionNode->init_action = TRUE;
   1483 /* MR12c */  		if (actionNode->noHoist) {
   1484 /* MR12c */           errFL("<<nohoist>> appears as init-action - use <<>> <<nohoist>>",
   1485 /* MR12c */                       FileStr[actionNode->file],actionNode->line);
   1486 /* MR12c */         };
   1487 				}
   1488 			}
   1489 			((Junction *)g.left)->blockid = CurBlockID;
   1490 			>>
   1491 
   1492 			(	exception_group > [eg]
   1493 				<<
   1494 				if ( eg!=NULL ) {
   1495 /* MR7 *****       	eg->altID = makeAltID(CurBlockID,CurAltNum);        *****/
   1496 /* MR7 *****		CurAltStart->exception_label = eg->altID;           *****/
   1497 					list_add(&CurExGroups, (void *)eg);
   1498 				}
   1499 				>>
   1500 			)*
   1501 			<<CurAltNum++;
   1502 /* MR23 */    CurAltNum_array[BlkLevel] = CurAltNum;
   1503             >>
   1504 
   1505 			(	"\|" <<inAlt=1;>>
   1506 				alt[toksrefd,rulesrefd]		<<g = Or(g, $2);>>
   1507 				<<
   1508 				((Junction *)g.left)->blockid = CurBlockID;
   1509 				>>
   1510 
   1511 				(	exception_group > [eg]
   1512 					<<
   1513 					if ( eg!=NULL ) {
   1514 /* MR7 *****       	eg->altID = makeAltID(CurBlockID,CurAltNum);        *****/
   1515 /* MR7 *****		CurAltStart->exception_label = eg->altID;           *****/
   1516 						list_add(&CurExGroups, (void *)eg);
   1517 					}
   1518 					>>
   1519 				)*
   1520 
   1521 				<<CurAltNum++;
   1522 /* MR23 */        CurAltNum_array[BlkLevel] = CurAltNum;
   1523                 >>
   1524 
   1525 			)*
   1526 			<<$0 = b;>>
   1527 			<<attribsRefdFromAction = saveblah; inAlt = saveinalt;>>
   1528 		;
   1529 		<<CannotContinue=TRUE;>>
   1530 
   1531 /* rule alt */
   1532 
   1533 alt[set *toksrefd, set *rulesrefd]
   1534 		:	<<int n=0; Graph g; int e_num=0, old_not=0; Node *node; set elems, dif;
   1535 			int first_on_line = 1, use_def_MT_handler = 0;
   1536 			g.left=NULL; g.right=NULL;
   1537 
   1538 			CurAltStart = NULL;
   1539 			elems = empty;
   1540 			inAlt = 1;
   1541 			>>
   1542 			{	"\@"	/* handle MismatchedToken signals with default handler */
   1543 				<<use_def_MT_handler = 1;>>
   1544 			}
   1545 
   1546 			(	<<;>>       /* MR9 Removed unreferenced variable "tok" */
   1547 				{ <<old_not=0;>> "\~" <<old_not=1;>> }
   1548 				element[old_not, first_on_line, use_def_MT_handler] > [node]
   1549 				<<if ( node!=NULL && node->ntype!=nAction ) first_on_line = 0;>>
   1550 				<<
   1551 				if ( $2.left!=NULL ) {
   1552 					g = Cat(g, $2);
   1553 					n++;
   1554 					if ( node!=NULL ) {
   1555 						if ( node->ntype!=nAction ) e_num++;
   1556 						/* record record number of all rule and token refs */
   1557 						if ( node->ntype==nToken ) {
   1558 							TokNode *tk = (TokNode *)((Junction *)$2.left)->p1;
   1559 							tk->elnum = e_num;
   1560 							set_orel(e_num, &elems);
   1561 						}
   1562 						else if ( node->ntype==nRuleRef ) {
   1563 							RuleRefNode *rn = (RuleRefNode *)((Junction *)$2.left)->p1;
   1564 							rn->elnum = e_num;
   1565 							set_orel(e_num, $rulesrefd);
   1566 						}
   1567 					}
   1568 				}
   1569 				>>
   1570 			)*
   1571 			<<if ( n == 0 ) g = emptyAlt();
   1572 			  $0 = g;
   1573 			  /* We want to reduce number of LT(i) calls and the number of
   1574 			   * local attribute variables in C++ mode (for moment, later we'll
   1575 			   * do for C also).  However, if trees are being built, they
   1576 			   * require most of the attrib variables to create the tree nodes
   1577 			   * with; therefore, we gen a token ptr for each token ref in C++
   1578 			   */
   1579 			  if ( GenCC && !GenAST )
   1580 			  {
   1581 				  /* This now free's the temp set -ATG 5/6/95 */
   1582 				  set temp;
   1583 				  temp = set_and(elems, attribsRefdFromAction);
   1584 				  set_orin($toksrefd, temp);
   1585 				  set_free(temp);
   1586 			  }
   1587 			  else set_orin($toksrefd, elems);
   1588 			  if ( GenCC ) {
   1589 				dif = set_dif(attribsRefdFromAction, elems);
   1590 			  	if ( set_deg(dif)>0 )
   1591 					err("one or more $i in action(s) refer to non-token elements");
   1592 				set_free(dif);
   1593 			  }
   1594 			  set_free(elems);
   1595 			  set_free(attribsRefdFromAction);
   1596 			  inAlt = 0;
   1597    			>>
   1598 		;
   1599 		<<CannotContinue=TRUE;>>
   1600 
   1601 /* rule element_label */
   1602 
   1603 element_label > [LabelEntry *label]
   1604 	:	<<TermEntry *t=NULL; LabelEntry *l=NULL; RuleEntry *r=NULL; char *lab;>>
   1605 		LABEL	<<lab = mystrdup(LATEXT(1));>>
   1606 		<<
   1607 		UsedNewStyleLabel = 1;
   1608 		if ( UsedOldStyleAttrib ) err("cannot mix with new-style labels with old-style $i");
   1609 		t = (TermEntry *) hash_get(Tname, lab);
   1610 		if ( t==NULL ) t = (TermEntry *) hash_get(Texpr, lab);
   1611 		if ( t==NULL ) r = (RuleEntry *) hash_get(Rname, lab);
   1612 		if ( t!=NULL ) {
   1613 			err(eMsg1("label definition clashes with token/tokclass definition: '%s'", lab));
   1614 			$label = NULL;
   1615 		}
   1616 		else if ( r!=NULL ) {
   1617 			err(eMsg1("label definition clashes with rule definition: '%s'", lab));
   1618 			$label = NULL;
   1619 		}
   1620 		else {
   1621 			/* we don't clash with anybody else */
   1622 			l = (LabelEntry *) hash_get(Elabel, lab);
   1623  			if ( l==NULL ) {	/* ok to add new element label */
   1624 				l = (LabelEntry *)hash_add(Elabel,
   1625 										   lab,
   1626 										   (Entry *)newLabelEntry(lab));
   1627 				/* add to list of element labels for this rule */
   1628 				list_add(&CurElementLabels, (void *)lab);
   1629 /* MR7 */       leAdd(l);  /* list of labels waiting for exception group definitions */
   1630 				$label = l;
   1631 			}
   1632 			else {
   1633 				err(eMsg1("label definitions must be unique per rule: '%s'", lab));
   1634 				$label = NULL;
   1635 			}
   1636 		}
   1637 		>>
   1638 		":"
   1639 	;
   1640 
   1641 /* rule element */
   1642 
   1643 element[int old_not, int first_on_line, int use_def_MT_handler] > [Node *node]
   1644 		: <<
   1645 		  Attrib blk;
   1646 		  Predicate *pred = NULL;
   1647 		  int local_use_def_MT_handler=0;
   1648 		  ActionNode *act;
   1649 		  RuleRefNode *rr;
   1650 		  set toksrefd, rulesrefd;
   1651 		  TermEntry *term;
   1652 		  TokNode *p=NULL; RuleRefNode *q; int approx=0;
   1653 		  LabelEntry *label=NULL;
   1654           int predMsgDone=0;
   1655           int semDepth=0;
   1656           int   ampersandStyle;
   1657           int   height;         /* MR11 */
   1658           int   equal_height;   /* MR11 */
   1659 
   1660           char* pFirstSetSymbol = NULL; /* MR21 */
   1661 
   1662 		  $node = NULL;
   1663 		  >>
   1664 		  {element_label>[label]}
   1665 		  ( TokenTerm
   1666 			<<
   1667 			term = (TermEntry *) hash_get(Tname, LATEXT(1));
   1668 			if ( term==NULL && UserDefdTokens ) {
   1669 				err("implicit token definition not allowed with #tokdefs");
   1670 				$$.left = $$.right = NULL;
   1671 			}
   1672 			else {
   1673 				$$ = buildToken(LATEXT(1));
   1674 				p=((TokNode *)((Junction *)$$.left)->p1);
   1675 				term = (TermEntry *) hash_get(Tname, LATEXT(1));
   1676 				require( term!= NULL, "hash table mechanism is broken");
   1677 				p->tclass = term->tclass;
   1678 				p->complement = $old_not;
   1679 				if ( label!=NULL ) {
   1680 					p->el_label = label->str;
   1681 					label->elem = (Node *)p;
   1682 				}
   1683 			}
   1684 			>>
   1685 			{	".."
   1686 				(	QuotedTerm
   1687 					<<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>
   1688 				|	TokenTerm
   1689 					<<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>
   1690 				)
   1691 			}
   1692 			<<
   1693 			if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) )
   1694 				list_add(&MetaTokenNodes, (void *)p);
   1695 			>>
   1696 			(	"^"	<<if ( p!=NULL ) p->astnode=ASTroot;>>
   1697 			|		<<if ( p!=NULL ) p->astnode=ASTchild;>>
   1698 			|	"!" <<if ( p!=NULL ) p->astnode=ASTexclude;>>
   1699 			)
   1700 			{ "\@" <<local_use_def_MT_handler = 1;>> }
   1701 			<<
   1702 			if ( p!=NULL && $first_on_line ) {
   1703 				CurAltStart = (Junction *)$$.left;
   1704                 altAdd(CurAltStart);                                 /* MR7 */
   1705 				p->altstart = CurAltStart;
   1706 			}
   1707    			if ( p!=NULL )
   1708 				p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler;
   1709 			$node = (Node *)p;
   1710 			>>
   1711 		  | QuotedTerm
   1712 			<<
   1713 			term = (TermEntry *) hash_get(Texpr, LATEXT(1));
   1714 			if ( term==NULL && UserDefdTokens ) {
   1715 				err("implicit token definition not allowed with #tokdefs");
   1716 				$$.left = $$.right = NULL;
   1717 			}
   1718 			else {
   1719 				$$ = buildToken(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);
   1720 				p->complement = $old_not;
   1721 				if ( label!=NULL ) {
   1722 					p->el_label = label->str;
   1723 	   				label->elem = (Node *)p;
   1724 				}
   1725 			}
   1726 			>>
   1727 			{	".."
   1728 				(	QuotedTerm
   1729 					<<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>
   1730 				|	TokenTerm
   1731 					<<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>>
   1732 				)
   1733 			}
   1734 			(	"^"	<<if ( p!=NULL ) p->astnode=ASTroot;>>
   1735 			|		<<if ( p!=NULL ) p->astnode=ASTchild;>>
   1736 			|	"!" <<if ( p!=NULL ) p->astnode=ASTexclude;>>
   1737 			)
   1738 			{ "\@" <<local_use_def_MT_handler = 1;>> }
   1739 			<<
   1740 			if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) )
   1741 				list_add(&MetaTokenNodes, (void *)p);
   1742 			>>
   1743 			<<
   1744 			if ( $first_on_line ) {
   1745 				CurAltStart = (Junction *)$$.left;
   1746                 altAdd(CurAltStart);                                 /* MR7 */
   1747 				p->altstart = CurAltStart;
   1748 			}
   1749    			if ( p!=NULL )
   1750 				p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler;
   1751 			$node = (Node *)p;
   1752 			>>
   1753 
   1754 		  | <<if ( $old_not ) warn("~ WILDCARD is an undefined operation (implies 'nothing')");>>
   1755 			"."
   1756 			<<$$ = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);>>
   1757 			(	"^"	<<p->astnode=ASTroot;>>
   1758 			|		<<p->astnode=ASTchild;>>
   1759 			|	"!" <<p->astnode=ASTexclude;>>
   1760 			)
   1761 			<<list_add(&MetaTokenNodes, (void *)p);>>
   1762 			<<
   1763 			if ( $first_on_line ) {
   1764 				CurAltStart = (Junction *)$$.left;
   1765                 altAdd(CurAltStart);                                 /* MR7 */
   1766 				p->altstart = CurAltStart;
   1767 				if ( label!=NULL ) {
   1768 					p->el_label = label->str;
   1769 					label->elem = (Node *)p;
   1770 				}
   1771 			}
   1772 			$node = (Node *)p;
   1773 			>>
   1774 
   1775 		  | <<if ( $old_not ) warn("~ NONTERMINAL is an undefined operation");>>
   1776 			NonTerminal
   1777 			<<$$ = buildRuleRef(LATEXT(1));>>
   1778 			{ "!" <<q = (RuleRefNode *) ((Junction *)$$.left)->p1;
   1779 					q->astnode=ASTexclude;>>
   1780 			}
   1781 			{	{"\<"}
   1782 				PassAction <<addParm(((Junction *)$$.left)->p1, LATEXT(1));>>
   1783 			}
   1784 			<<rr=(RuleRefNode *) ((Junction *)$$.left)->p1;>>
   1785 			{	<<char *a;>>
   1786 				"\>"
   1787 				PassAction
   1788 				<<
   1789 					a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
   1790 					require(a!=NULL, "rule element: cannot allocate assignment");
   1791 					strcpy(a, LATEXT(1));
   1792 					rr->assign = a;
   1793 				>>
   1794 			}
   1795 			<<
   1796 			if ( label!=NULL ) {
   1797 				rr->el_label = label->str;
   1798 				label->elem = (Node *)rr;
   1799 			}
   1800 			if ( $first_on_line ) {
   1801 				CurAltStart = (Junction *)$$.left;
   1802                 altAdd(CurAltStart);                                 /* MR7 */
   1803 				((RuleRefNode *)((Junction *)$$.left)->p1)->altstart = CurAltStart;
   1804 			}
   1805 			$node = (Node *)rr;
   1806 			>>
   1807 		  )
   1808 
   1809 		|	<<if ( $old_not )	warn("~ ACTION is an undefined operation");>>
   1810 			Action <<$0 = buildAction(LATEXT(1),action_file,action_line, 0);>>
   1811 			<<if ( $first_on_line ) {                                /* MR7 */
   1812                 CurAltStart = (Junction *)$0.left;                   /* MR7 */
   1813                 altAdd(CurAltStart);                                 /* MR7 */
   1814               };>>                                                   /* MR7 */
   1815 			<<$node = (Node *) ((Junction *)$0.left)->p1;>>
   1816 
   1817 		|	<<if ( $old_not )	warn("~ SEMANTIC-PREDICATE is an undefined operation");>>
   1818 			Pred   <<$0 = buildAction(LATEXT(1),action_file,action_line, 1);>>
   1819 			<<act = (ActionNode *) ((Junction *)$0.left)->p1;>>
   1820             <<if (numericActionLabel) {             /* MR10 */
   1821                 list_add(&NumericPredLabels,act);   /* MR10 */
   1822                 numericActionLabel=0;               /* MR10 */
   1823               };                                    /* MR10 */
   1824             >>
   1825 			{	<<char *a;>>
   1826 				PassAction
   1827 				<<
   1828 				a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
   1829 				require(a!=NULL, "rule element: cannot allocate predicate fail action");
   1830 				strcpy(a, LATEXT(1));
   1831 				act->pred_fail = a;
   1832 				>>
   1833 			}
   1834 			<<if ( $first_on_line ) {                                /* MR7 */
   1835                 CurAltStart = (Junction *)$0.left;                   /* MR7 */
   1836                 altAdd(CurAltStart);                                 /* MR7 */
   1837               };>>                                                   /* MR7 */
   1838 			<<$node = (Node *)act;>>
   1839 
   1840 		|	<<if ( $old_not )	warn("~ BLOCK is an undefined operation");>>
   1841 			<<BlkLevel++;
   1842               if (BlkLevel >= MAX_BLK_LEVEL) fatal("Blocks nested too deeply");
   1843 /* MR23 */    CurBlockID_array[BlkLevel] = CurBlockID;
   1844 /* MR23 */    CurAltNum_array[BlkLevel] = CurAltNum;
   1845             >>
   1846 			{	Pragma
   1847 				(	"approx" <<approx=LL_k;>>
   1848 				|	"LL\(1\)"  <<approx = 1;>>  /* MR20 */
   1849 				|	"LL\(2\)"  <<approx = 2;>>  /* MR20 */
   1850                 )
   1851             }
   1852 
   1853 /* MR21 */  {  FirstSetSymbol
   1854 /* MR21 */     "\("
   1855 /* MR21 */    		(	NonTerminal
   1856 /* MR21 */                <<
   1857 /* MR21 */                     pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1,
   1858 /* MR21 */                                                    sizeof(char));
   1859 /* MR21 */                          require(pFirstSetSymbol!=NULL,
   1860 /* MR21 */                                  "cannot allocate first set name");
   1861 /* MR21 */                          strcpy(pFirstSetSymbol, LATEXT(1));
   1862 /* MR21 */                      >>
   1863 /* MR21 */          |    TokenTerm
   1864 /* MR21 */                  <<
   1865 /* MR21 */                      pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1,
   1866 /* MR21 */                                                        sizeof(char));
   1867 /* MR21 */                      require(pFirstSetSymbol!=NULL,
   1868 /* MR21 */                              "cannot allocate first set name");
   1869 /* MR21 */                      strcpy(pFirstSetSymbol, LATEXT(1));
   1870 /* MR21 */                  >>
   1871 /* MR21 */          )
   1872 /* MR21 */      "\)"
   1873 /* MR21 */  }
   1874 
   1875             (
   1876 
   1877         	"\(" block[&toksrefd,&rulesrefd] "\)"
   1878 				<<blk = $$ = $2;
   1879                         /* MR23 */      CurBlockID_array[BlkLevel] = (-1);
   1880                         /* MR23 */      CurAltNum_array[BlkLevel] = (-1);
   1881                   --BlkLevel;
   1882             >>
   1883 
   1884 				(	"\*"		<<$$ = makeLoop($$,approx,pFirstSetSymbol);>>
   1885 				|	"\+"		<<$$ = makePlus($$,approx,pFirstSetSymbol);>>
   1886 				|	"?"
   1887 					(
   1888                         ( "=>" <<ampersandStyle=0;>>
   1889                         | "&&" <<ampersandStyle=1;>>  /* MR10 (g)? && <<p>>? */
   1890                         )
   1891                         Pred	/* generalized predicate */
   1892 						/* first make into a predicate */
   1893 					    <<$$ = buildAction(LATEXT(1),action_file,action_line,1);>>
   1894 					    <<act = (ActionNode *) ((Junction *)$$.left)->p1;>>
   1895                         <<semDepth=predicateLookaheadDepth(act);>>  /* MR10 */
   1896                         <<if (numericActionLabel) {             /* MR10 */
   1897                             list_add(&NumericPredLabels,act);   /* MR10 */
   1898                             numericActionLabel=0;               /* MR10 */
   1899                           };                                    /* MR10 */
   1900                         >>
   1901 						{	<<char *a;>>
   1902 							PassAction
   1903 							<<
   1904 							a = (char *)calloc(strlen(LATEXT(1))+1, sizeof(char));
   1905 							require(a!=NULL, "rule element: cannot allocate predicate fail action");
   1906 							strcpy(a, LATEXT(1));
   1907 							act->pred_fail = a;
   1908 							>>
   1909 						}
   1910 						<<if ($first_on_line) {                      /* MR7 */
   1911                             CurAltStart=(Junction *)$$.left;         /* MR7 */
   1912                             altAdd(CurAltStart);                     /* MR7 */
   1913                           };>>
   1914 						<<$node = (Node *)act;>>
   1915 
   1916 						/* for now, just snag context */
   1917 						<<
   1918 						pred = computePredFromContextGuard(blk,&predMsgDone);           /* MR10 */
   1919 						if ( pred==NULL) {                                              /* MR10 */
   1920                           if ( !predMsgDone) err("invalid or missing context guard");   /* MR10 */
   1921                           predMsgDone=1;                                                /* MR10 */
   1922 						} else {                                                        /* MR10 */
   1923                             act->guardNodes=(Junction *)blk.left;                       /* MR11 */
   1924 							pred->expr = act->action;
   1925 							pred->source = act;
   1926 /* MR10 */                  pred->ampersandStyle = ampersandStyle;  /* 0 means (g)? => ... 1 means (g)? && ... */
   1927 /* MR13 */                  if (pred->tcontext != NULL) {
   1928 /* MR13 */                    height=MR_max_height_of_tree(pred->tcontext);
   1929 /* MR13 */                    equal_height=MR_all_leaves_same_height(pred->tcontext,height);
   1930 /* MR13 */                    if (! equal_height) {
   1931 /* MR13 */                       errFL("in guarded predicates all tokens in the guard must be at the same height",
   1932 /* MR13 */                              FileStr[act->file],act->line);
   1933 /* MR13 */                    };
   1934 /* MR13 */                  }
   1935 /* MR10 */                  if (ampersandStyle) {
   1936 /* MR10 */			  		  act->ampersandPred = pred;
   1937 /* MR11 */                    if (! HoistPredicateContext) {
   1938 /* MR11 */                      errFL("without \"-prc on\" (guard)? && <<pred>>? ... doesn't make sense",
   1939 /* MR11 */                              FileStr[act->file],act->line);
   1940 /* MR11 */                    };
   1941 /* MR10 */                  } else {
   1942 /* MR10 */			  		  act->guardpred = pred;
   1943 /* MR10 */                  };
   1944 /* MR10 */                  if (pred->k != semDepth) {
   1945 /* MR10 */                     warn(eMsgd2("length of guard (%d) does not match the length of semantic predicate (%d)",
   1946 /* MR10 */                                  pred->k,semDepth));
   1947 /* MR10 */                  };
   1948 						}
   1949 						>>
   1950 					|	<<$$ = makeBlk($$,approx,pFirstSetSymbol);
   1951 						  FoundGuessBlk = 1;
   1952 						  ((Junction *) ((Junction *)$$.left)->p1)->guess=1;
   1953 						  if ( !$first_on_line ) {
   1954 							err("(...)? predicate must be first element of production");
   1955 						  }
   1956 						>>
   1957 					)
   1958 				|	<<$$ = makeBlk($$,approx,pFirstSetSymbol);>>
   1959 				)
   1960 				<<
   1961 				if ( pred==NULL && !predMsgDone) {                                      /* MR10 */
   1962 					((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID;
   1963 					((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd;
   1964 					((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd;
   1965 					if ( $first_on_line ) {                         /* MR7 */
   1966 					   CurAltStart = (Junction *)((Junction *)((Junction *)$$.left)->p1);  /* MR7 */
   1967                        altAdd(CurAltStart);                         /* MR7 */
   1968                     };                                              /* MR7 */
   1969 					$node = (Node *) ((Junction *)$$.left)->p1;
   1970 				}
   1971 				>>
   1972 
   1973 			|	"\{"	block[&toksrefd,&rulesrefd]
   1974 						<<$$ = makeOpt($2,approx,pFirstSetSymbol);
   1975                                 /* MR23 */      CurBlockID_array[BlkLevel] = (-1);
   1976                                 /* MR23 */      CurAltNum_array[BlkLevel] = (-1);
   1977                                 --BlkLevel;
   1978                         >>
   1979 				"\}"
   1980 				<<
   1981 				((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID;
   1982 				((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd;
   1983 				((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd;
   1984 				>>
   1985 				<<if ( $first_on_line ) {                            /* MR7 */
   1986 					CurAltStart = (Junction *) ((Junction *)((Junction *)$$.left)->p1);  /* MR7 */
   1987                     altAdd(CurAltStart);                             /* MR7 */
   1988                   };
   1989 				>>
   1990 				<<$node = (Node *) ((Junction *)$$.left)->p1;>>
   1991 
   1992 			)
   1993 
   1994 /* Error catching alternatives */
   1995 		|	"\*"	<<warn("don't you want a ')' with that '*'?"); CannotContinue=TRUE;>>
   1996 		|	"\+"	<<warn("don't you want a ')' with that '+'?"); CannotContinue=TRUE;>>
   1997 		|	"\>"	<<warn("'>' can only appear after a nonterminal"); CannotContinue=TRUE;>>
   1998 		|	PassAction <<warn("[...] out of context 'rule > [...]'");
   1999 						 CannotContinue=TRUE;>>
   2000 		;
   2001 		<<CannotContinue=TRUE;>>
   2002 
   2003 /* rule default_exception_handler */
   2004 
   2005 default_exception_handler
   2006 	:	exception_group > [DefaultExGroup]
   2007 	;
   2008 
   2009 /* rule exception_group */
   2010 
   2011 exception_group > [ExceptionGroup *eg]
   2012 	:	<<ExceptionHandler *h; LabelEntry *label=NULL;	  /* MR6 */
   2013 		  FoundException = 1; FoundExceptionGroup = 1;>>  /* MR6 */
   2014 
   2015 		"exception"	 <<$eg = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup));>>
   2016 		{	<<char *p;>>
   2017 			PassAction		/* did they attach a label? */
   2018 			<<
   2019 			p = LATEXT(1)+1;
   2020 			p[strlen(p)-1] = '\0';		/* kill trailing space */
   2021 			label = (LabelEntry *) hash_get(Elabel, LATEXT(1)+1);
   2022 			if ( label==NULL )
   2023 			{
   2024 				err(eMsg1("unknown label in exception handler: '%s'", LATEXT(1)+1));
   2025 			}
   2026 			>>
   2027 		}
   2028 		(	exception_handler > [h]
   2029 			<<list_add(&($eg->handlers), (void *)h);>>
   2030 		)*
   2031 		{	"default" ":" Action
   2032 			<<{
   2033 			ExceptionHandler *eh = (ExceptionHandler *)
   2034 				calloc(1, sizeof(ExceptionHandler));
   2035 			char *a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
   2036 			require(eh!=NULL, "exception: cannot allocate handler");
   2037 			require(a!=NULL, "exception: cannot allocate action");
   2038 			strcpy(a, LATEXT(1));
   2039 			eh->action = a;
   2040 			eh->signalname = (char *) calloc(strlen("default")+1, sizeof(char));
   2041 			require(eh->signalname!=NULL, "exception: cannot allocate sig name");
   2042 			strcpy(eh->signalname, "default");
   2043 			list_add(&($eg->handlers), (void *)eh);
   2044 			}>>
   2045 		}
   2046 
   2047 		<<
   2048 		if ( label!=NULL ) {
   2049             	/* Record ex group in sym tab for this label */
   2050 		   if ( label->ex_group!=NULL ) {
   2051 		      err(eMsg1("duplicate exception handler for label '%s'",label->str));
   2052 		   } else {
   2053 			  label->ex_group = $eg;
   2054 				/* Label the exception group itself */
   2055 			  $eg->label = label->str;
   2056 				/* Make the labelled element pt to the exception also */
   2057 /* MR6 */	  if (label->elem == NULL) {
   2058 /* MR6 */	     err(eMsg1("reference in exception handler to undefined label '%s'",label->str));
   2059 /* MR6 */	  } else {
   2060 			   	 switch ( label->elem->ntype ) {
   2061 				    case nRuleRef :
   2062                         {
   2063     					    RuleRefNode *r = (RuleRefNode *)label->elem;
   2064     					    r->ex_group = $eg;
   2065     				    	break;
   2066                         }
   2067      	            case nToken :
   2068 				        {
   2069 					        TokNode *t = (TokNode *)label->elem;
   2070 					        t->ex_group = $eg;
   2071 					        break;
   2072 				        }
   2073 				 } /* end switch */
   2074 /* MR6 */	  }; /* end test on label->elem */
   2075 		    } /* end test on label->ex_group */
   2076 
   2077 		} /* end test on exception label */
   2078 
   2079 /* MR7 */
   2080 /* MR7 */   if (BlkLevel == 1 && label == NULL) {
   2081 /* MR7 */     $eg->forRule=1;
   2082 /* MR7 */   } else if (label == NULL) {
   2083 /* MR7 */     $eg->altID = makeAltID(CurBlockID_array[BlkLevel], CurAltNum_array[BlkLevel]);
   2084 /* MR7 */     egAdd($eg);
   2085 /* MR7 */   } else {
   2086 /* MR7 */     $eg->labelEntry=label;
   2087 /* MR7 */   };
   2088 /* MR7 */
   2089 /* MR7 */	    /* You may want to remove this exc from the rule list  */
   2090 /* MR7 */		/* and handle at the labeled element site.             */
   2091 /* MR7 */
   2092 /* MR7 */   if (label != NULL) {
   2093 /* MR7 */     $eg = NULL;
   2094 /* MR7 */   };
   2095 
   2096 		>>
   2097 	;
   2098 	<<CannotContinue=TRUE;>>
   2099 
   2100 /* rule exception_handler */
   2101 
   2102 exception_handler > [ExceptionHandler *eh]
   2103 	:	<<;>>                               /* MR9 Removed unreferenced variable "a" */
   2104 		"catch"
   2105 		<<
   2106 		$eh = (ExceptionHandler *)calloc(1, sizeof(ExceptionHandler));
   2107 		require($eh!=NULL, "exception: cannot allocate handler");
   2108 		>>
   2109 		(	NonTerminal
   2110 			<<
   2111 			$eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
   2112 			require($eh->signalname!=NULL, "exception: cannot allocate sig name");
   2113 			strcpy($eh->signalname, LATEXT(1));
   2114 			>>
   2115 		|	TokenTerm
   2116 			<<
   2117 			$eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
   2118 			require($eh->signalname!=NULL, "exception: cannot allocate sig name");
   2119 			strcpy($eh->signalname, LATEXT(1));
   2120 			>>
   2121 		)
   2122 		":"
   2123 		{	<<$eh->action = NULL;>>
   2124 			Action
   2125 			<<
   2126 			$eh->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char));
   2127 			require($eh->action!=NULL, "exception: cannot allocate action");
   2128 			strcpy($eh->action, LATEXT(1));
   2129 			>>
   2130 		}
   2131 	;
   2132 	<<CannotContinue=TRUE;>>
   2133 
   2134 #token NonTerminal		"[a-z] [A-Za-z0-9_]*"
   2135 							<<
   2136 							while ( zzchar==' ' || zzchar=='\t' ) {
   2137 								zzadvance();
   2138 							}
   2139 							if ( zzchar == ':' && inAlt ) NLA = LABEL;
   2140 							>>
   2141 #token TokenTerm		"[A-Z] [A-Za-z0-9_]*"
   2142 							<<
   2143 							while ( zzchar==' ' || zzchar=='\t' ) {
   2144 								zzadvance();
   2145 							}
   2146 							if ( zzchar == ':' && inAlt ) NLA = LABEL;
   2147 							>>
   2148 #token "{\\}#[A-Za-z0-9_]*"	<<warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); >>
   2149 
   2150 #lexclass PARSE_ENUM_FILE
   2151 
   2152 #token "[\t\ ]+"			<< zzskip(); >>				/* Ignore White */
   2153 #token "\n|\r|\r\n"			<< zzline++; zzskip(); >>	/* Track Line # */
   2154 #token "//"					<< zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); >>
   2155 #token "/\*"				<< zzmode(TOK_DEF_COMMENTS); zzskip(); >>
   2156 #token "#ifdef"				<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
   2157 #token "#if"				<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
   2158 #token "#ifndef"			<< ; >>
   2159 #token "#else"				<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
   2160 #token "#endif"				<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
   2161 #token "#undef"				<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
   2162 #token "#import"			<< zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >>
   2163 #token "@"					<< ; >>
   2164 
   2165 /* rule enum_file */
   2166 
   2167 enum_file[char *fname]
   2168 	:	{	"#ifndef" ID
   2169 			{	"#define" ID /* ignore if it smells like a gate */
   2170 				/* First #define after the first #ifndef (if any) is ignored */
   2171 			}
   2172 		}
   2173 		(	( enum_def[$fname] )+
   2174 		|	defines[$fname]
   2175 		)
   2176 	|
   2177 	;
   2178 
   2179 /* rule defines */
   2180 
   2181 defines[char *fname]
   2182 	:	<<int v; int maxt=(-1); char *t;>>		/* MR3 */
   2183 		(
   2184 			"#define" ID
   2185 			<<t = mystrdup(LATEXT(1));>>
   2186 			INT
   2187 			<<
   2188 			v = atoi(LATEXT(1));
   2189 /*			fprintf(stderr, "#token %s=%d\n", t, v);*/
   2190 
   2191 	/* MR2 Andreas Magnusson (Andreas.Magnusson (at) mailbox.swipnet.se) */
   2192 	/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs            */
   2193 	/* MR2 Don't let #tokdefs be confused by 			*/
   2194 	/* MR2   DLGminToken and DLGmaxToken     			*/
   2195 
   2196 			if ( ! isDLGmaxToken(t)) {		/* MR2 */
   2197 			  TokenNum = v;
   2198 			  if ( v>maxt ) maxt=v;
   2199 			  if ( Tnum( t ) == 0 ) {
   2200 			    addForcedTname( t, v );
   2201 			  } else {
   2202 			    warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline);
   2203 			  };
   2204 	                };
   2205 			>>
   2206 		)+
   2207 		<<TokenNum = maxt + 1;>>
   2208 	;
   2209 
   2210 /* rule enum_def */
   2211 
   2212 enum_def[char *fname]
   2213 	:	<<int v= 0; int maxt=(-1); char *t;>>			/* MR3 */
   2214 		"enum" ID
   2215 		"\{"
   2216 			ID
   2217 			<<t = mystrdup(LATEXT(1));>>
   2218 			(	"=" INT	<<v=atoi(LATEXT(1));>>
   2219 			|			<<v++;>>
   2220 			)
   2221 			<<
   2222 /*			fprintf(stderr, "#token %s=%d\n", t, v);*/
   2223 			TokenNum = v;
   2224 			if ( v>maxt ) maxt=v;				/* MR3 */
   2225 			if ( Tnum( t ) == 0 ) addForcedTname( t, v );
   2226 			else {
   2227 				warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline);
   2228 			}
   2229 			>>
   2230 			(	","
   2231 
   2232 				/* MR2 Andreas Magnusson (Andreas.Magnusson (at) mailbox.swipnet.se) */
   2233 				/* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs            */
   2234 				/* MR2 Don't let #tokdefs be confused by 			*/
   2235 				/* MR2   DLGminToken and DLGmaxToken     			*/
   2236 
   2237 				{
   2238 				  <<isDLGmaxToken(LATEXT(1))>>? ID { "=" INT }		/* MR2 */
   2239 				| ID					                /* MR2 */
   2240 					<<t = mystrdup(LATEXT(1));>>
   2241 					(	"=" INT	<<v=atoi(LATEXT(1));>>
   2242 					|			<<v++;>>
   2243 					)
   2244 					<<
   2245 /*					fprintf(stderr, "#token %s=%d\n", t, v);*/
   2246 					TokenNum = v;
   2247 					if ( v>maxt ) maxt=v;				/* MR3 */
   2248 					if ( Tnum( t ) == 0 ) addForcedTname( t, v );
   2249 					else {
   2250 						warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline);
   2251 					}
   2252 					>>
   2253 				}
   2254 			)*
   2255 		"\}"
   2256 		";"
   2257 		<<TokenNum = maxt + 1;>>					/* MR3 */
   2258 	;
   2259 
   2260 #token INT	"[0-9]+"
   2261 #token ID	"[a-zA-Z_][_a-zA-Z0-9]*"
   2262 
   2263 #lexclass START
   2264 
   2265 /* MR14 Arpad Beszedes  26-May-98
   2266         Add support for #line directives when antlr source is pre-processed
   2267 */
   2268 
   2269 #lexaction
   2270 <<
   2271 
   2272 static char *
   2273 #ifdef __USE_PROTOS
   2274 getFileNameFromTheLineInfo(char *toStr, char *fromStr)
   2275 #else
   2276 getFileNameFromTheLineInfo(toStr, fromStr)
   2277 char *toStr, *fromStr;
   2278 #endif
   2279 {
   2280   int i, j, k;
   2281 
   2282   if (!fromStr || !toStr) return toStr;
   2283 
   2284   /* find the first " */
   2285 
   2286   for (i=0;
   2287         (i<MaxFileName) &&
   2288         (fromStr[i] != '\n') &&
   2289         (fromStr[i] != '\r') &&
   2290         (fromStr[i] != '\"');
   2291       i++) /* nothing */ ;
   2292 
   2293   if ( (i == MaxFileName) ||
   2294        (fromStr[i] == '\n') ||
   2295        (fromStr[i] == '\r') ) {
   2296     return toStr;
   2297   }
   2298 
   2299   /* find the second " */
   2300 
   2301   for (j=i+1;
   2302         (j<MaxFileName) &&
   2303         (fromStr[j] != '\n') &&
   2304         (fromStr[j] != '\r') &&
   2305         (fromStr[j] != '\"');
   2306        j++) /* nothing */ ;
   2307 
   2308   if ((j == MaxFileName) ||
   2309       (fromStr[j] == '\n') ||
   2310       (fromStr[j] == '\r') ) {
   2311     return toStr;
   2312   }
   2313 
   2314   /* go back until the last / or \ */
   2315 
   2316   for (k=j-1;
   2317         (fromStr[k] != '\"') &&
   2318         (fromStr[k] != '/') &&
   2319         (fromStr[k] != '\\');
   2320        k--) /* nothing */ ;
   2321 
   2322   /* copy the string after " / or \ into toStr */
   2323 
   2324   for (i=k+1; fromStr[i] != '\"'; i++) {
   2325     toStr[i-k-1] = fromStr[i];
   2326   }
   2327 
   2328   toStr[i-k-1] = '\0';
   2329 
   2330   return toStr;
   2331 }
   2332 
   2333 /* MR14 end of a block to support #line in antlr source code */
   2334 
   2335 >>
   2336 
   2337 <<
   2338 
   2339 /* MR2 Andreas Magnusson (Andreas.Magnusson (at) mailbox.swipnet.se) */
   2340 /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs            */
   2341 /* MR2 Don't let #tokdefs be confused by 			*/
   2342 /* MR2   DLGminToken and DLGmaxToken     			*/
   2343 
   2344 /* semantic check on DLGminToken and DLGmaxmaxToken in #tokdefs */
   2345 
   2346 #ifdef __USE_PROTOS
   2347 static int isDLGmaxToken(char *Token)
   2348 #else
   2349 static int isDLGmaxToken(Token)
   2350   char *	Token;
   2351 #endif
   2352 {
   2353    static char checkStr1[] = "DLGmaxToken";
   2354    static char checkStr2[] = "DLGminToken";
   2355 
   2356    if (strcmp(Token, checkStr1) == 0)
   2357       return 1;
   2358    else if (strcmp(Token, checkStr2) == 0)
   2359       return 1;
   2360    else
   2361       return 0;
   2362 }
   2363 
   2364 /* semantics of #token */
   2365 static void
   2366 #ifdef __USE_PROTOS
   2367 chkToken(char *t, char *e, char *a, int tnum)
   2368 #else
   2369 chkToken(t,e,a,tnum)
   2370 char *t, *e, *a;
   2371 int tnum;
   2372 #endif
   2373 {
   2374 	TermEntry *p;
   2375 
   2376 	/* check to see that they don't try to redefine a token as a token class */
   2377 	if ( t!=NULL ) {
   2378 		p = (TermEntry *) hash_get(Tname, t);
   2379 		if ( p!=NULL && p->classname ) {
   2380 			err(eMsg1("redefinition of #tokclass '%s' to #token not allowed; ignored",t));
   2381 			if ( a!=NULL ) free((char *)a);
   2382 			return;
   2383 		}
   2384 	}
   2385 
   2386 	if ( t==NULL && e==NULL ) {			/* none found */
   2387 		err("#token requires at least token name or rexpr");
   2388 	}
   2389 	else if ( t!=NULL && e!=NULL ) {	/* both found */
   2390 		if ( UserDefdTokens ) {			/* if #tokdefs, must not define new */
   2391 			p = (TermEntry *) hash_get(Tname, t);
   2392 			if ( p == NULL) {
   2393 err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t));
   2394 	    		return;
   2395             };
   2396 		}
   2397 		Tklink(t, e);
   2398 		if ( a!=NULL ) {
   2399 			if ( hasAction(e) ) {
   2400 				err(eMsg1("redefinition of action for %s; ignored",e));
   2401 			}
   2402 			else setHasAction(e, a);
   2403 		}
   2404 	}
   2405 	else if ( t!=NULL ) {				/* only one found */
   2406 		if ( UserDefdTokens ) {
   2407 			p = (TermEntry *) hash_get(Tname, t);
   2408             if (p == NULL) {
   2409 err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",t));
   2410             };
   2411    		    return;
   2412 		}
   2413 		if ( Tnum( t ) == 0 ) addTname( t );
   2414 		else {
   2415 			err(eMsg1("redefinition of token %s; ignored",t));
   2416 		}
   2417 		if ( a!=NULL ) {
   2418 			err(eMsg1("action cannot be attached to a token name (%s); ignored",t));
   2419 			free((char *)a);
   2420 		}
   2421 	}
   2422 	else if ( e!=NULL ) {
   2423 		if ( Tnum( e ) == 0 ) addTexpr( e );
   2424 		else {
   2425 			if ( hasAction(e) ) {
   2426 				err(eMsg1("redefinition of action for expr %s; ignored",e));
   2427 			}
   2428 			else if ( a==NULL ) {
   2429 				err(eMsg1("redefinition of expr %s; ignored",e));
   2430 			}
   2431 		}
   2432 		if ( a!=NULL ) setHasAction(e, a);
   2433 	}
   2434 
   2435 	/* if a token type number was specified, then add the token ID and 'tnum'
   2436 	 * pair to the ForcedTokens list.  (only applies if an id was given)
   2437 	 */
   2438 	if ( t!=NULL && tnum>0 )
   2439 	{
   2440 		if ( set_el(tnum, reserved_positions) )
   2441 		{
   2442 			err(eMsgd("a token has already been forced to token number %d; ignored", tnum));
   2443 		}
   2444 		else
   2445 		{
   2446 			list_add(&ForcedTokens, newForcedToken(t,tnum));
   2447 			set_orel(tnum, &reserved_positions);
   2448 		}
   2449 	}
   2450 }
   2451 >>
   2452 
   2453 <<
   2454 static int
   2455 #ifdef __USE_PROTOS
   2456 match_token(char *s, char **nxt)
   2457 #else
   2458 match_token(s,nxt)
   2459 char *s;
   2460 char **nxt;
   2461 #endif
   2462 {
   2463     if ( !(*s>='A' && *s<='Z') ) return 0;
   2464 	s++;
   2465     while ( (*s>='a' && *s<='z') ||
   2466 		    (*s>='A' && *s<='Z') ||
   2467 		    (*s>='0' && *s<='9') ||
   2468 		    *s=='_' )
   2469     {
   2470 	   s++;
   2471 	}
   2472 	if ( *s!=' ' && *s!='}' ) return 0;
   2473 	*nxt = s;
   2474 	return 1;
   2475 }
   2476 
   2477 static int
   2478 #ifdef __USE_PROTOS
   2479 match_rexpr(char *s, char **nxt)
   2480 #else
   2481 match_rexpr(s,nxt)
   2482 char *s;
   2483 char **nxt;
   2484 #endif
   2485 {
   2486     if ( *s!='"' ) return 0;
   2487 	s++;
   2488     while ( *s!='"' )
   2489     {
   2490 	   if ( *s=='\n' || *s=='\r' )                   /* MR13 */
   2491 		  warn("eoln found in regular expression");
   2492 	   if ( *s=='\\' ) s++;
   2493 	   s++;
   2494 	}
   2495 	*nxt = s+1;
   2496 	return 1;
   2497 }
   2498 
   2499 /*
   2500  * Walk a string "{ A .. Z }" where A..Z is a space separated list
   2501  * of token references (either labels or reg exprs).  Return a
   2502  * string "inlineX_set" for some unique integer X.  Basically,
   2503  * we pretend as if we had seen "#tokclass inlineX { A .. Z }"
   2504  * on the input stream outside of an action.
   2505  */
   2506 char *
   2507 #ifdef __USE_PROTOS
   2508 inline_set(char *s)
   2509 #else
   2510 inline_set(s)
   2511 char *s;
   2512 #endif
   2513 {
   2514 	char *nxt;
   2515     fprintf(stderr, "found consumeUntil( {...} )\n");
   2516 	while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}
   2517 	if ( *s!='{' )
   2518 	{
   2519 	   err("malformed consumeUntil( {...} ); missing '{'");
   2520 	   return "bad_set";
   2521 	}
   2522 	s++;
   2523 	while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}
   2524 	while ( *s!='}' )
   2525 	{
   2526 	    if ( match_token(s,&nxt) ) fprintf(stderr, "found token %s\n", s);
   2527 		else if ( match_rexpr(s,&nxt) ) fprintf(stderr, "found rexpr %s\n", s);
   2528 		else {
   2529 		    err("invalid element in consumeUntil( {...} )");
   2530 			return "bad_set";
   2531 		}
   2532 		s = nxt;
   2533 		while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;}
   2534 	}
   2535 	return "inlineX_set";
   2536 }
   2537 >>
   2538 
   2539 <<
   2540 /* ANTLR-specific syntax error message generator
   2541  * (define USER_ZZSYN when compiling so don't get 2 definitions)
   2542  */
   2543 void
   2544 #ifdef __USE_PROTOS
   2545 zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok,
   2546 int k, char *bad_text)
   2547 #else
   2548 zzsyn(text, tok, egroup, eset, etok, k, bad_text)
   2549 char *text, *egroup, *bad_text;
   2550 int tok;
   2551 int etok;
   2552 int k;
   2553 SetWordType *eset;
   2554 #endif
   2555 {
   2556 	fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline);
   2557 	fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text);
   2558 	if ( !etok && !eset ) {fprintf(stderr, "\n"); return;}
   2559 	if ( k==1 ) fprintf(stderr, " missing");
   2560 	else
   2561 	{
   2562 		fprintf(stderr, "; \"%s\" not", bad_text);
   2563 		if ( zzset_deg(eset)>1 ) fprintf(stderr, " in");
   2564 	}
   2565 	if ( zzset_deg(eset)>0 ) zzedecode(eset);
   2566 	else fprintf(stderr, " %s", zztokens[etok]);
   2567 	if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup);
   2568 	fprintf(stderr, "\n");
   2569 }
   2570 >>
   2571 
   2572 #lexaction <<
   2573 #ifdef __USE_PROTOS
   2574 void mark_label_used_in_sem_pred(LabelEntry *le)              /* MR10 */
   2575 #else
   2576 void mark_label_used_in_sem_pred(le)                          /* MR10 */
   2577   LabelEntry    *le;
   2578 #endif
   2579 {
   2580   TokNode   *tn;
   2581   require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken");
   2582   tn=(TokNode *)le->elem;
   2583   require (tn->label != 0,"mark_label_used... TokNode has no label");
   2584   tn->label_used_in_semantic_pred=1;
   2585 }
   2586 >>
   2587