| /* |
| * antlr.g -- PCCTS Version 1.xx ANTLR |
| * |
| * $Id: antlr.g,v 1.7 95/10/05 11:57:12 parrt Exp $ |
| * $Revision: 1.7 $ |
| * |
| * Parse an antlr input grammar and build a syntax-diagram. |
| * |
| * Written in itself (needs at least 1.06 to work) |
| * |
| * SOFTWARE RIGHTS |
| * |
| * We reserve no LEGAL rights to the Purdue Compiler Construction Tool |
| * Set (PCCTS) -- PCCTS is in the public domain. An individual or |
| * company may do whatever they wish with source code distributed with |
| * PCCTS or the code generated by PCCTS, including the incorporation of |
| * PCCTS, or its output, into commerical software. |
| * |
| * We encourage users to develop software with PCCTS. However, we do ask |
| * that credit is given to us for developing PCCTS. By "credit", |
| * we mean that if you incorporate our source code into one of your |
| * programs (commercial product, research project, or otherwise) that you |
| * acknowledge this fact somewhere in the documentation, research report, |
| * etc... If you like PCCTS and have developed a nice tool with the |
| * output, please mention that you developed it using PCCTS. In |
| * addition, we ask that this header remain intact in our source code. |
| * As long as these guidelines are kept, we expect to continue enhancing |
| * this system and expect to make other tools available as they are |
| * completed. |
| * |
| * ANTLR 1.33 |
| * Terence Parr |
| * Parr Research Corporation |
| * with Purdue University and AHPCRC, University of Minnesota |
| * 1989-1995 |
| */ |
| |
| /* MR1 */ |
| /* MR1 10-Apr-97 MR1 Replace #if logic with #include "config.h" */ |
| /* MR1 */ |
| |
| #header << |
| #include "config.h" |
| #include "set.h" |
| #include <ctype.h> |
| #include "syn.h" |
| #include "hash.h" |
| #include "generic.h" |
| #define zzcr_attr(attr,tok,t) |
| >> |
| |
| << |
| #ifdef __USE_PROTOS |
| static void chkToken(char *, char *, char *, int); |
| #else |
| static void chkToken(); |
| #endif |
| |
| #ifdef __USE_PROTOS |
| static int isDLGmaxToken(char *Token); /* MR3 */ |
| #else |
| static int isDLGmaxToken(); /* MR3 */ |
| #endif |
| |
| static int class_nest_level = 0; |
| extern int inAlt; |
| extern set attribsRefdFromAction; |
| extern int UsedOldStyleAttrib; |
| extern int UsedNewStyleLabel; |
| >> |
| |
| #lexaction << |
| /* maintained, but not used for now */ |
| set AST_nodes_refd_in_actions = set_init; |
| int inAlt = 0; |
| set attribsRefdFromAction; |
| int UsedOldStyleAttrib = 0; |
| int UsedNewStyleLabel = 0; |
| #ifdef __USE_PROTOS |
| char *inline_set(char *); |
| #else |
| char *inline_set(); |
| #endif |
| |
| /* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ |
| /* MR1 in DLG action */ |
| |
| int tokenActionActive=0; /* MR1 */ |
| >> |
| |
| #lexclass STRINGS |
| #token QuotedTerm "\"" << zzmode(START); >> |
| #token "[\n\r]" << |
| zzline++; |
| warn("eoln found in string"); |
| zzskip(); |
| >> |
| #token "\\[\n\r]" << zzline++; zzmore(); >> |
| #token "\\~[]" << zzmore(); >> |
| #token "~[\n\r\"\\]+" << zzmore(); >> |
| |
| #lexclass ACTION_STRINGS |
| #token "\"" << zzmode(ACTIONS); zzmore(); >> |
| #token "[\n\r]" << |
| zzline++; |
| warn("eoln found in string (in user action)"); |
| zzskip(); |
| >> |
| #token "\\[\n\r]" << zzline++; zzmore(); >> |
| #token "\\~[]" << zzmore(); >> |
| #token "~[\n\r\"\\]+" << zzmore(); >> |
| |
| #lexclass ACTION_CHARS |
| #token "'" << zzmode(ACTIONS); zzmore(); >> |
| #token "[\n\r]" << |
| zzline++; |
| warn("eoln found in char literal (in user action)"); |
| zzskip(); |
| >> |
| #token "\\~[]" << zzmore(); >> |
| #token "~[\n\r'\\]+" << zzmore(); >> |
| |
| #lexclass ACTION_COMMENTS |
| #token "\*/" << zzmode(ACTIONS); zzmore(); >> |
| #token "\*" << zzmore(); >> |
| #token "[\n\r]" << zzline++; zzmore(); DAWDLE; >> |
| #token "~[\n\r\*]+" << zzmore(); >> |
| |
| #lexclass TOK_DEF_COMMENTS |
| #token "\*/" << zzmode(PARSE_ENUM_FILE); |
| zzmore(); >> |
| #token "\*" << zzmore(); >> |
| #token "[\n\r]" << zzline++; zzmore(); DAWDLE; >> |
| #token "~[\n\r\*]+" << zzmore(); >> |
| |
| #lexclass TOK_DEF_CPP_COMMENTS |
| #token "[\n\r]" << zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; >> |
| #token "~[\n\r]+" << zzskip(); >> |
| |
| #lexclass ACTION_CPP_COMMENTS |
| #token "[\n\r]" << zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; >> |
| #token "~[\n\r]+" << zzmore(); >> |
| |
| #lexclass CPP_COMMENTS |
| #token "[\n\r]" << zzline++; zzmode(START); zzskip(); DAWDLE; >> |
| #token "~[\n\r]+" << zzskip(); >> |
| |
| #lexclass COMMENTS |
| #token "\*/" << zzmode(START); zzskip(); >> |
| #token "\*" << zzskip(); >> |
| #token "[\n\r]" << zzline++; zzskip(); DAWDLE; >> |
| #token "~[\n\r\*]+" << zzskip(); >> |
| |
| /* |
| * This lexical class accepts actions of type [..] and <<..>> |
| * |
| * It translates the following special items for C: |
| * |
| * $j --> "zzaArg(current zztasp, j)" |
| * $i.j --> "zzaArg(zztaspi, j)" |
| * $i.nondigit> "zzaArg(current zztasp, i).nondigit" |
| * $$ --> "zzaRet" |
| * $alnum --> "alnum" (used to ref parameters) |
| * $rule --> "zzaRet" |
| * $retval --> "_retv.retval" if > 1 return values else "_retv" |
| * $[token, text] --> "zzconstr_attr(token, text)" |
| * $[] --> "zzempty_attr()" |
| * |
| * It translates the following special items for C++: |
| * (attributes are now stored with 'Token' and $i's are only |
| * pointers to the Tokens. Rules don't have attributes now.) |
| * |
| * $j --> "_tbj" where b is the block level |
| * $i.j --> "_tij" |
| * $j->nondigit> "_tbj->nondigit" |
| * $$ --> "$$" |
| * $alnum --> "alnum" (used to ref parameters) |
| * $rule --> "$rule" |
| * $retval --> "_retv.retval" if > 1 return values else "_retv" |
| * $[token, text] --> invalid |
| * $[] --> invalid |
| * |
| * And, for trees: |
| * |
| * #0 --> "(*_root)" |
| * #i --> "zzastArg(i)" |
| * #[args] --> "zzmk_ast(zzastnew(), args)" |
| * #[] --> "zzastnew()" |
| * #( root, child1, ..., childn ) |
| * --> "zztmake(root, child1, ...., childn, NULL)" |
| * #() --> "NULL" |
| * |
| * For C++, ... |
| * |
| * #0 --> "(*_root)" |
| * #i --> "_astbi" where b is the block level |
| * #alnum --> "alnum_ast" (used to ref #label) |
| * #[args] --> "new AST(args)" |
| * #[] --> "new AST" |
| * #( root, child1, ..., childn ) |
| * --> "AST::tmake(root, child1, ...., childn, NULL)" |
| * #() --> "NULL" |
| * |
| * To escape, |
| * |
| * \] --> ] |
| * \) --> ) |
| * \$ --> $ |
| * \# --> # |
| * |
| * A stack is used to nest action terminators because they can be nested |
| * like crazy: << #[$[..],..] >> |
| */ |
| #lexclass ACTIONS |
| #token Action "\>\>" << /* these do not nest */ |
| zzmode(START); |
| NLATEXT[0] = ' '; |
| NLATEXT[1] = ' '; |
| zzbegexpr[0] = ' '; |
| zzbegexpr[1] = ' '; |
| if ( zzbufovf ) { |
| err( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE)); |
| } |
| |
| /* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ |
| /* MR1 in DLG action */ |
| /* MR1 Doesn't matter what kind of action it is - reset*/ |
| |
| tokenActionActive=0; /* MR1 */ |
| >> |
| #token Pred "\>\>?" << /* these do not nest */ |
| zzmode(START); |
| NLATEXT[0] = ' '; |
| NLATEXT[1] = ' '; |
| zzbegexpr[0] = '\0'; |
| if ( zzbufovf ) { |
| err( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE)); |
| } |
| >> |
| #token PassAction "\]" << if ( topint() == ']' ) { |
| popint(); |
| if ( istackempty() ) /* terminate action */ |
| { |
| zzmode(START); |
| NLATEXT[0] = ' '; |
| zzbegexpr[0] = ' '; |
| if ( zzbufovf ) { |
| err( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE)); |
| } |
| } |
| else { |
| /* terminate $[..] and #[..] */ |
| if ( GenCC ) zzreplstr("))"); |
| else zzreplstr(")"); |
| zzmore(); |
| } |
| } |
| else if ( topint() == '|' ) { /* end of simple [...] */ |
| popint(); |
| zzmore(); |
| } |
| else zzmore(); |
| >> |
| #token "consumeUntil\( [\ \t]* \{~[\}]+\} [\ \t]* \)" |
| << |
| zzmore(); |
| zzreplstr(inline_set(zzbegexpr+ |
| strlen("consumeUntil("))); |
| >> |
| #token "consumeUntil\( ~[\)]+ \)" |
| << zzmore(); >> |
| #token "[\n\r]" << zzline++; zzmore(); DAWDLE; >> |
| #token "\>" << zzmore(); >> |
| #token "$" << zzmore(); >> |
| #token "$$" << if ( !GenCC ) {zzreplstr("zzaRet"); zzmore();} |
| else err("$$ use invalid in C++ mode"); >> |
| |
| #token "$\[\]" << if ( !GenCC ) {zzreplstr("zzempty_attr"); zzmore();} |
| else err("$[] use invalid in C++ mode"); >> |
| #token "$\[" << |
| pushint(']'); |
| if ( !GenCC ) zzreplstr("zzconstr_attr("); |
| else err("$[..] use invalid in C++ mode"); |
| zzmore(); |
| >> |
| #token "$[0-9]+" <<{ |
| static char buf[100]; |
| if ( strlen(zzbegexpr)>(size_t)85 ) |
| fatal("$i attrib ref too big"); |
| set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); |
| if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s)", |
| BlkLevel-1,zzbegexpr+1); |
| else sprintf(buf,"_t%d%s", |
| BlkLevel-1,zzbegexpr+1); |
| zzreplstr(buf); |
| zzmore(); |
| UsedOldStyleAttrib = 1; |
| if ( UsedNewStyleLabel ) |
| err("cannot mix old-style $i with new-style labels"); |
| } |
| >> |
| #token "$[0-9]+." <<{ |
| static char buf[100]; |
| if ( strlen(zzbegexpr)>(size_t)85 ) |
| fatal("$i.field attrib ref too big"); |
| zzbegexpr[strlen(zzbegexpr)-1] = ' '; |
| set_orel(atoi(zzbegexpr+1), &attribsRefdFromAction); |
| if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%d,%s).", |
| BlkLevel-1,zzbegexpr+1); |
| else sprintf(buf,"_t%d%s.", |
| BlkLevel-1,zzbegexpr+1); |
| zzreplstr(buf); |
| zzmore(); |
| UsedOldStyleAttrib = 1; |
| if ( UsedNewStyleLabel ) |
| err("cannot mix old-style $i with new-style labels"); |
| } |
| >> |
| #token "$[0-9]+.[0-9]+" <<{ |
| static char buf[100]; |
| static char i[20], j[20]; |
| char *p,*q; |
| if (strlen(zzbegexpr)>(size_t)85) fatal("$i.j attrib ref too big"); |
| for (p=zzbegexpr+1,q= &i[0]; *p!='.'; p++) { |
| if ( q == &i[20] ) |
| fatalFL("i of $i.j attrib ref too big", |
| FileStr[CurFile], zzline ); |
| *q++ = *p; |
| } |
| *q = '\0'; |
| for (p++, q= &j[0]; *p!='\0'; p++) { |
| if ( q == &j[20] ) |
| fatalFL("j of $i.j attrib ref too big", |
| FileStr[CurFile], zzline ); |
| *q++ = *p; |
| } |
| *q = '\0'; |
| if ( !GenCC ) sprintf(buf,"zzaArg(zztasp%s,%s)",i,j); |
| else sprintf(buf,"_t%s%s",i,j); |
| zzreplstr(buf); |
| zzmore(); |
| UsedOldStyleAttrib = 1; |
| if ( UsedNewStyleLabel ) |
| err("cannot mix old-style $i with new-style labels"); |
| } |
| >> |
| #token "$[_a-zA-Z][_a-zA-Z0-9]*" |
| <<{ static char buf[300]; LabelEntry *el; |
| zzbegexpr[0] = ' '; |
| if ( CurRule != NULL && |
| strcmp(CurRule, &zzbegexpr[1])==0 ) { |
| if ( !GenCC ) zzreplstr("zzaRet"); |
| } |
| else if ( CurRetDef != NULL && |
| strmember(CurRetDef, &zzbegexpr[1])) { |
| if ( HasComma( CurRetDef ) ) { |
| require (strlen(zzbegexpr)<=(size_t)285, |
| "$retval attrib ref too big"); |
| sprintf(buf,"_retv.%s",&zzbegexpr[1]); |
| zzreplstr(buf); |
| } |
| else zzreplstr("_retv"); |
| } |
| else if ( CurParmDef != NULL && |
| strmember(CurParmDef, &zzbegexpr[1])) { |
| ; |
| } |
| else if ( Elabel==NULL ) { |
| { err("$-variables in actions outside of rules are not allowed"); } |
| } else if ( (el=(LabelEntry *)hash_get(Elabel, &zzbegexpr[1]))!=NULL ) { |
| if ( GenCC && (el->elem==NULL || el->elem->ntype==nRuleRef) ) |
| { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); } |
| } |
| else |
| warn(eMsg1("$%s not parameter, return value, or element label",&zzbegexpr[1])); |
| } |
| zzmore(); |
| >> |
| #token "#0" << zzreplstr("(*_root)"); zzmore(); chkGTFlag(); >> |
| #token "#\[\]" << if ( GenCC ) {zzreplstr("(new AST)");} |
| else {zzreplstr("zzastnew()");} zzmore(); |
| chkGTFlag(); |
| >> |
| #token "#\(\)" << zzreplstr("NULL"); zzmore(); chkGTFlag(); >> |
| #token "#[0-9]+" <<{ |
| static char buf[100]; |
| if ( strlen(zzbegexpr)>(size_t)85 ) |
| fatal("#i AST ref too big"); |
| if ( GenCC ) sprintf(buf,"_ast%d%s",BlkLevel-1,zzbegexpr+1); |
| else sprintf(buf,"zzastArg(%s)",zzbegexpr+1); |
| zzreplstr(buf); |
| zzmore(); |
| set_orel(atoi(zzbegexpr+1), &AST_nodes_refd_in_actions); |
| chkGTFlag(); |
| } |
| >> |
| #token "#[_a-zA-Z][_a-zA-Z0-9]*" |
| << |
| if ( !(strcmp(zzbegexpr, "#ifdef")==0 || |
| strcmp(zzbegexpr, "#if")==0 || |
| strcmp(zzbegexpr, "#else")==0 || |
| strcmp(zzbegexpr, "#endif")==0 || |
| strcmp(zzbegexpr, "#ifndef")==0 || |
| strcmp(zzbegexpr, "#define")==0 || |
| strcmp(zzbegexpr, "#pragma")==0 || |
| strcmp(zzbegexpr, "#undef")==0 || |
| strcmp(zzbegexpr, "#import")==0 || |
| strcmp(zzbegexpr, "#line")==0 || |
| strcmp(zzbegexpr, "#include")==0 || |
| strcmp(zzbegexpr, "#error")==0) ) |
| { |
| static char buf[100]; |
| sprintf(buf, "%s_ast", zzbegexpr+1); |
| zzreplstr(buf); |
| chkGTFlag(); |
| } |
| zzmore(); |
| >> |
| #token "#\[" << |
| pushint(']'); |
| if ( GenCC ) zzreplstr("(new AST("); |
| else zzreplstr("zzmk_ast(zzastnew(),"); |
| zzmore(); |
| chkGTFlag(); |
| >> |
| #token "#\(" << |
| pushint('}'); |
| if ( GenCC ) zzreplstr("ASTBase::tmake("); |
| else zzreplstr("zztmake("); |
| zzmore(); |
| chkGTFlag(); |
| >> |
| #token "#" << zzmore(); >> |
| #token "\)" << |
| if ( istackempty() ) |
| zzmore(); |
| else if ( topint()==')' ) { |
| popint(); |
| } |
| else if ( topint()=='}' ) { |
| popint(); |
| /* terminate #(..) */ |
| zzreplstr(", NULL)"); |
| } |
| zzmore(); |
| >> |
| #token "\[" << |
| pushint('|'); /* look for '|' to terminate simple [...] */ |
| zzmore(); |
| >> |
| #token "\(" << |
| pushint(')'); |
| zzmore(); |
| >> |
| |
| #token "\\\]" << zzreplstr("]"); zzmore(); >> |
| #token "\\\)" << zzreplstr(")"); zzmore(); >> |
| |
| /* MR1 10-Apr-97 MR1 Previously unable to put right shift operator */ |
| /* MR1 in DLG action */ |
| |
| #token "\\>" << if (! tokenActionActive) zzreplstr(">"); /* MR1 */ |
| zzmore(); /* MR1 */ |
| >> /* MR1 */ |
| |
| |
| #token "'" << zzmode(ACTION_CHARS); zzmore();>> |
| #token "\"" << zzmode(ACTION_STRINGS); zzmore();>> |
| #token "\\$" << zzreplstr("$"); zzmore(); >> |
| #token "\\#" << zzreplstr("#"); zzmore(); >> |
| #token "\\[\n\r]" << zzline++; zzmore(); >> |
| #token "\\~[\]\)>$#]" << zzmore(); >> /* escaped char, always ignore */ |
| #token "/" << zzmore(); >> |
| #token "/\*" << zzmode(ACTION_COMMENTS); zzmore(); >> |
| #token "\*/" << warn("Missing /*; found dangling */ in action"); zzmore(); >> |
| #token "//" << zzmode(ACTION_CPP_COMMENTS); zzmore(); >> |
| #token "~[\n\r\)\(\\$#\>\]\[\"'/]+" << zzmore(); >> |
| |
| #lexclass START |
| #token "[\t\ ]+" << zzskip(); >> /* Ignore White */ |
| #token "[\n\r]" << zzline++; zzskip(); >> /* Track Line # */ |
| #token "\[" << zzmode(ACTIONS); zzmore(); |
| istackreset(); |
| pushint(']'); >> |
| #token "\<\<" << action_file=CurFile; action_line=zzline; |
| zzmode(ACTIONS); zzmore(); |
| istackreset(); |
| pushint('>'); >> |
| #token "\"" << zzmode(STRINGS); zzmore(); >> |
| #token "/\*" << zzmode(COMMENTS); zzskip(); >> |
| #token "\*/" << warn("Missing /*; found dangling */"); zzskip(); >> |
| #token "//" << zzmode(CPP_COMMENTS); zzskip(); >> |
| |
| /* */ |
| /* 8-Apr-97 Regularize escape sequence for ">>" */ |
| /* appearing in string literals */ |
| /* */ |
| |
| #token "\>\>" << warn("Missing <<; found dangling \>\>"); zzskip(); >> // MR1 |
| #token WildCard "." |
| #token "\@" <<FoundException = 1; /* MR6 */ |
| FoundAtOperator = 1;>> /* MR6 */ |
| #token Eof "@" |
| << /* L o o k F o r A n o t h e r F i l e */ |
| { |
| FILE *new_input; |
| new_input = NextFile(); |
| if ( new_input == NULL ) { NLA=Eof; return; } |
| fclose( input ); |
| input = new_input; |
| zzrdstream( input ); |
| zzskip(); /* Skip the Eof (@) char i.e continue */ |
| } |
| >> |
| |
| #token LABEL |
| |
| #errclass "grammar-element" { element } |
| #errclass "meta-symbol" { "\}" "!" ";" "\|" "\~" "^" "\)" } |
| |
| /* |
| * Get a grammar -- Build a list of rules like: |
| * |
| * o-->Rule1--o |
| * | |
| * o-->Rule2--o |
| * | |
| * ... |
| * | |
| * o-->RuleN--o |
| */ |
| grammar : <<Graph g;>> |
| ( "#header" Action |
| << |
| if ( HdrAction==NULL ) { |
| HdrAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require(HdrAction!=NULL, "rule grammar: cannot allocate header action"); |
| strcpy(HdrAction, LATEXT(1)); |
| } |
| else warn("additional #header statement ignored"); |
| >> |
| | "#parser" QuotedTerm |
| << |
| if ( GenCC ) { |
| warn("#parser meta-op incompatible with -CC; ignored"); |
| } |
| else { |
| if ( strcmp(ParserName,"zzparser")==0 ) { |
| ParserName=StripQuotes(mystrdup(LATEXT(1))); |
| if ( RulePrefix[0]!='\0' ) |
| { |
| warn("#parser meta-op incompatible with '-gp prefix'; '-gp' ignored"); |
| RulePrefix[0]='\0'; |
| } |
| } |
| else warn("additional #parser statement ignored"); |
| } |
| >> |
| | "#tokdefs" QuotedTerm |
| <<{ |
| char *fname; |
| zzantlr_state st; FILE *f; struct zzdlg_state dst; |
| UserTokenDefsFile = mystrdup(LATEXT(1)); |
| zzsave_antlr_state(&st); |
| zzsave_dlg_state(&dst); |
| fname = mystrdup(LATEXT(1)); |
| f = fopen(StripQuotes(fname), "r"); |
| if ( f==NULL ) {warn(eMsg1("cannot open token defs file '%s'", fname+1));} |
| else { |
| ANTLRm(enum_file(fname+1), f, PARSE_ENUM_FILE); |
| UserDefdTokens = 1; |
| } |
| zzrestore_antlr_state(&st); |
| zzrestore_dlg_state(&dst); |
| }>> |
| )* |
| ( Action |
| <<{ |
| UserAction *ua = newUserAction(LATEXT(1)); |
| ua->file = action_file; ua->line = action_line; |
| if ( class_nest_level>0 ) list_add(&class_before_actions, ua); |
| else list_add(&BeforeActions, ua); |
| }>> |
| | laction |
| | lmember /* MR1 */ |
| | lprefix /* MR1 */ |
| | aLexclass |
| | token |
| | error |
| | tclass |
| | default_exception_handler |
| | class_def |
| | "\}" |
| << |
| if ( class_nest_level==0 ) |
| warn("missing class definition for trailing '}'"); |
| class_nest_level--; |
| >> |
| )* |
| rule <<g=$3; SynDiag = (Junction *) $3.left;>> |
| ( rule <<if ( $1.left!=NULL ) {g.right = NULL; g = Or(g, $1);}>> |
| | aLexclass |
| | token |
| | error |
| | tclass |
| | class_def |
| | "\}" |
| << |
| if ( class_nest_level==0 ) |
| warn("missing class definition for trailing '}'"); |
| class_nest_level--; |
| >> |
| )* |
| ( Action |
| <<{ |
| UserAction *ua = newUserAction(LATEXT(1)); |
| ua->file = action_file; ua->line = action_line; |
| if ( class_nest_level>0 ) list_add(&class_after_actions, ua); |
| else list_add(&AfterActions, ua); |
| }>> |
| | laction |
| | lmember /* MR1 */ |
| | lprefix /* MR1 */ |
| | error |
| | tclass |
| | class_def |
| | "\}" |
| << |
| if ( class_nest_level==0 ) |
| warn("missing class definition for trailing '}'"); |
| class_nest_level--; |
| >> |
| )* |
| Eof |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| class_def |
| : <<int go=1; char name[MaxRuleName+1];>> |
| "class" |
| ( NonTerminal <<if(go) strncpy(name,LATEXT(1),MaxRuleName);>> |
| | TokenTerm <<if(go) strncpy(name,LATEXT(1),MaxRuleName);>> |
| ) |
| << |
| if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0 |
| && GenCC ) { |
| err("only one grammar class allowed in this release"); |
| go = 0; |
| } |
| else strcpy(CurrentClassName, name); |
| >> |
| <<if ( !GenCC ) { err("class meta-op used without C++ option"); }>> |
| "\{" |
| << |
| no_classes_found = 0; |
| if ( class_nest_level>=1 ) {warn("cannot have nested classes");} |
| else class_nest_level++; |
| >> |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| /* |
| * Build -o-->o-R-o-->o- where -o-R-o- is the block from rule 'block'. |
| * Construct the RuleBlk front and EndRule node on the end of the |
| * block. This is used to add FOLLOW pointers to the rule end. Add the |
| * new rule name to the Rname hash table and sets its rulenum. |
| * Store the parameter definitions if any are found. |
| * |
| * Note that locks are required on the RuleBlk and EndRule nodes to thwart |
| * infinite recursion. |
| * |
| * Return the left graph pointer == NULL to indicate error/dupl rule def. |
| */ |
| rule : << |
| ListNode *ex_groups = NULL; |
| ExceptionGroup *eg; |
| RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e; |
| set toksrefd, rulesrefd; |
| char *pdecl=NULL, *ret=NULL, *a; CurRetDef = CurParmDef = NULL; |
| CurExGroups = NULL; |
| CurElementLabels = NULL; |
| /* We want a new element label hash table for each rule */ |
| if ( Elabel!=NULL ) killHashTable(Elabel); |
| Elabel = newHashTable(); |
| attribsRefdFromAction = empty; |
| >> |
| NonTerminal |
| <<q=NULL; |
| if ( hash_get(Rname, LATEXT(1))!=NULL ) { |
| err(eMsg1("duplicate rule definition: '%s'",LATEXT(1))); |
| CannotContinue=TRUE; |
| } |
| else |
| { |
| q = (RuleEntry *)hash_add(Rname, |
| LATEXT(1), |
| (Entry *)newRuleEntry(LATEXT(1))); |
| CurRule = q->str; |
| } |
| CurRuleNode = q; |
| f = CurFile; l = zzline; |
| NumRules++; |
| >> |
| { "!" <<if ( q!=NULL ) q->noAST = TRUE;>> } |
| { <<;>> |
| {"\<"} |
| PassAction |
| << pdecl = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require(pdecl!=NULL, "rule rule: cannot allocate param decl"); |
| strcpy(pdecl, LATEXT(1)); |
| CurParmDef = pdecl; |
| >> |
| } |
| { "\>" |
| PassAction |
| << ret = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require(ret!=NULL, "rule rule: cannot allocate ret type"); |
| strcpy(ret, LATEXT(1)); |
| CurRetDef = ret; |
| >> |
| } |
| { QuotedTerm <<if ( q!=NULL ) q->egroup=mystrdup(LATEXT(1));>> } |
| << |
| if ( GenEClasseForRules && q!=NULL ) { |
| e = newECnode; |
| require(e!=NULL, "cannot allocate error class node"); |
| if ( q->egroup == NULL ) {a = q->str; a[0] = (char)toupper(a[0]);} |
| else a = q->egroup; |
| if ( Tnum( a ) == 0 ) |
| { |
| e->tok = addTname( a ); |
| list_add(&eclasses, (char *)e); |
| if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]); |
| /* refers to itself */ |
| list_add(&(e->elist), mystrdup(q->str)); |
| } |
| else { |
| warn(eMsg1("default errclass for '%s' would conflict with token/errclass/tokclass",a)); |
| if ( q->egroup == NULL ) a[0] = (char)tolower(a[0]); |
| free((char *)e); |
| } |
| } |
| >> |
| <<BlkLevel++;>> |
| ":" <<inAlt=1;>> |
| block[&toksrefd, &rulesrefd] |
| <<r = makeBlk($7,0); |
| CurRuleBlk = (Junction *)r.left; |
| CurRuleBlk->blockid = CurBlockID; |
| CurRuleBlk->jtype = RuleBlk; |
| if ( q!=NULL ) CurRuleBlk->rname = q->str; |
| CurRuleBlk->file = f; |
| CurRuleBlk->line = l; |
| CurRuleBlk->pdecl = pdecl; |
| CurRuleBlk->ret = ret; |
| CurRuleBlk->lock = makelocks(); |
| CurRuleBlk->pred_lock = makelocks(); |
| CurRuleBlk->tokrefs = toksrefd; |
| CurRuleBlk->rulerefs = rulesrefd; |
| p = newJunction(); /* add EndRule Node */ |
| ((Junction *)r.right)->p1 = (Node *)p; |
| r.right = (Node *) p; |
| p->jtype = EndRule; |
| p->lock = makelocks(); |
| p->pred_lock = makelocks(); |
| CurRuleBlk->end = p; |
| if ( q!=NULL ) q->rulenum = NumRules; |
| $7 = r; |
| >> |
| <<--BlkLevel;>> |
| <<altFixup();leFixup();egFixup();>> /* MR7 */ |
| ";" <<inAlt=0;>> |
| { Action |
| << a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require(a!=NULL, "rule rule: cannot allocate error action"); |
| strcpy(a, LATEXT(1)); |
| CurRuleBlk->erraction = a; |
| >> |
| } |
| ( exception_group > [eg] |
| <<if ( eg!=NULL ) { |
| list_add(&CurExGroups, (void *)eg); |
| if ( eg->label=='\0' ) q->has_rule_exception = 1; |
| } |
| >> |
| )* |
| <<if ( q==NULL ) $0.left = NULL; else $0 = $7;>> |
| <<CurRuleNode = NULL;>> |
| <<CurRuleBlk->exceptions = CurExGroups;>> |
| <<CurRuleBlk->el_labels = CurElementLabels;>> |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| /* |
| pragma : "#pragma" "dup\-labeled\-tokens" |
| <<Pragma_DupLabeledTokens=1;>> |
| ; |
| */ |
| |
| laction : <<char *a;>> |
| "#lexaction" |
| Action |
| << |
| a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require(a!=NULL, "rule laction: cannot allocate action"); |
| strcpy(a, LATEXT(1)); |
| list_add(&LexActions, a); |
| >> |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| /* MR1 */ |
| /* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ |
| /* MR1 via #lexmember <<....>> & #lexprefix <<...>> */ |
| /* MR1 */ |
| |
| lmember: <<char *a;>> /* MR1 */ |
| /* MR1 */ "#lexmember" |
| /* MR1 */ Action |
| /* MR1 */ << |
| /* MR1 */ if (! GenCC) { |
| /* MR1 */ err("Use #lexmember only in C++ mode (to insert code in DLG class header"); |
| /* MR1 */ } else { |
| /* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| /* MR1 */ require(a!=NULL, "rule lmember: cannot allocate action"); |
| /* MR1 */ strcpy(a, LATEXT(1)); |
| /* MR1 */ list_add(&LexMemberActions, a); |
| /* MR1 */ }; |
| /* MR1 */ >> |
| /* MR1 */ ; |
| /* MR1 */ <<CannotContinue=TRUE;>> |
| |
| lprefix: <<char *a;>> /* MR1 */ |
| /* MR1 */ "#lexprefix" |
| /* MR1 */ Action |
| /* MR1 */ << |
| /* MR1 */ if (! GenCC) { |
| /* MR1 */ err("Use #lexprefixr only in C++ mode (to insert code in DLG class header"); |
| /* MR1 */ } else { |
| /* MR1 */ a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| /* MR1 */ require(a!=NULL, "rule lprefix: cannot allocate action"); |
| /* MR1 */ strcpy(a, LATEXT(1)); |
| /* MR1 */ list_add(&LexPrefixActions, a); |
| /* MR1 */ }; |
| /* MR1 */ >> |
| /* MR1 */ ; |
| /* MR1 */ <<CannotContinue=TRUE;>> |
| |
| aLexclass: "#lexclass" TokenTerm <<lexclass(mystrdup(LATEXT(1)));>> |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| error : <<char *t=NULL; ECnode *e; int go=1; TermEntry *p;>> |
| "#errclass" |
| (<<;>> TokenTerm <<t=mystrdup(LATEXT(1));>> |
| | QuotedTerm <<t=mystrdup(LATEXT(1));>> |
| ) |
| <<e = newECnode; |
| require(e!=NULL, "cannot allocate error class node"); |
| e->lexclass = CurrentLexClass; |
| if ( Tnum( (t=StripQuotes(t)) ) == 0 ) |
| { |
| if ( hash_get(Texpr, t) != NULL ) |
| warn(eMsg1("errclass name conflicts with regular expression '%s'",t)); |
| e->tok = addTname( t ); |
| set_orel(e->tok, &imag_tokens); |
| require((p=(TermEntry *)hash_get(Tname, t)) != NULL, |
| "hash table mechanism is broken"); |
| p->classname = 1; /* entry is errclass name, not token */ |
| list_add(&eclasses, (char *)e); |
| } |
| else |
| { |
| warn(eMsg1("redefinition of errclass or conflict w/token or tokclass '%s'; ignored",t)); |
| free( (char *)e ); |
| go=0; |
| } |
| >> |
| "\{" |
| ( NonTerminal <<if ( go ) t=mystrdup(LATEXT(1));>> |
| | TokenTerm <<if ( go ) t=mystrdup(LATEXT(1));>> |
| | QuotedTerm <<if ( go ) t=mystrdup(LATEXT(1));>> |
| ) |
| <<if ( go ) list_add(&(e->elist), t);>> |
| ( |
| ( NonTerminal <<if ( go ) t=mystrdup(LATEXT(1));>> |
| | TokenTerm <<if ( go ) t=mystrdup(LATEXT(1));>> |
| | QuotedTerm <<if ( go ) t=mystrdup(LATEXT(1));>> |
| ) |
| <<if ( go ) list_add(&(e->elist), t);>> |
| )* |
| "\}" |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| tclass : <<char *t=NULL; TCnode *e; int go=1,tok; TermEntry *p, *term;>> |
| "#tokclass" TokenTerm <<t=mystrdup(LATEXT(1));>> |
| <<e = newTCnode; |
| require(e!=NULL, "cannot allocate token class node"); |
| e->lexclass = CurrentLexClass; |
| if ( Tnum( t ) == 0 ) |
| { |
| e->tok = addTname( t ); |
| set_orel(e->tok, &imag_tokens); |
| set_orel(e->tok, &tokclasses); |
| require((p=(TermEntry *)hash_get(Tname, t)) != NULL, |
| "hash table mechanism is broken"); |
| p->classname = 1; /* entry is class name, not token */ |
| p->tclass = e; /* save ptr to this tclass def */ |
| list_add(&tclasses, (char *)e); |
| } |
| else |
| { |
| warn(eMsg1("redefinition of tokclass or conflict w/token '%s'; ignored",t)); |
| free( (char *)e ); |
| go=0; |
| } |
| >> |
| "\{" |
| ( |
| ( TokenTerm |
| <<if ( go ) { |
| term = (TermEntry *) hash_get(Tname, LATEXT(1)); |
| if ( term==NULL && UserDefdTokens ) { |
| err("implicit token definition not allowed with #tokdefs"); |
| go = 0; |
| } |
| else {t=mystrdup(LATEXT(1)); tok=addTname(LATEXT(1));} |
| }>> |
| | QuotedTerm |
| <<if ( go ) { |
| term = (TermEntry *) hash_get(Texpr, LATEXT(1)); |
| if ( term==NULL && UserDefdTokens ) { |
| err("implicit token definition not allowed with #tokdefs"); |
| go = 0; |
| } |
| else {t=mystrdup(LATEXT(1)); tok=addTexpr(LATEXT(1));} |
| }>> |
| ) |
| <<if ( go ) list_add(&(e->tlist), t);>> |
| )* |
| "\}" |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| token : <<char *t=NULL, *e=NULL, *a=NULL; int tnum=0;>> |
| "#token" |
| |
| /* MR1 10-Apr-97 MR1 Allow shift right operator in DLG actions */ |
| /* MR1 Danger when parser feedback to lexer */ |
| /* MR1 */ |
| |
| <<tokenActionActive=1;>> /* MR1 */ |
| { TokenTerm <<t=mystrdup(LATEXT(1));>> |
| { "=" "[0-9]+" /* define the token type number */ |
| <<tnum = atoi(LATEXT(1));>> |
| } |
| } |
| { QuotedTerm <<e=mystrdup(LATEXT(1));>> } |
| { Action |
| << |
| a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require(a!=NULL, "rule token: cannot allocate action"); |
| strcpy(a, LATEXT(1)); |
| >> |
| } |
| <<chkToken(t, e, a, tnum);>> |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| block[set *toksrefd, set *rulesrefd] |
| : << |
| Graph g, b; |
| set saveblah; |
| int saveinalt = inAlt; |
| ExceptionGroup *eg; |
| *$toksrefd = empty; |
| *$rulesrefd = empty; |
| set_clr(AST_nodes_refd_in_actions); |
| CurBlockID++; |
| CurAltNum = 1; |
| saveblah = attribsRefdFromAction; |
| attribsRefdFromAction = empty; |
| >> |
| alt[toksrefd,rulesrefd] <<b = g = $1;>> |
| << |
| if ( ((Junction *)g.left)->p1->ntype == nAction ) |
| { |
| if ( !((ActionNode *)(((Junction *)g.left)->p1))->is_predicate ) |
| { |
| ((ActionNode *)(((Junction *)g.left)->p1))->init_action = TRUE; |
| } |
| } |
| ((Junction *)g.left)->blockid = CurBlockID; |
| >> |
| |
| ( exception_group > [eg] |
| << |
| if ( eg!=NULL ) { |
| /* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/ |
| /* MR7 ***** CurAltStart->exception_label = eg->altID; *****/ |
| list_add(&CurExGroups, (void *)eg); |
| } |
| >> |
| )* |
| <<CurAltNum++;>> |
| |
| ( "\|" <<inAlt=1;>> |
| alt[toksrefd,rulesrefd] <<g = Or(g, $2);>> |
| << |
| ((Junction *)g.left)->blockid = CurBlockID; |
| >> |
| |
| ( exception_group > [eg] |
| << |
| if ( eg!=NULL ) { |
| /* MR7 ***** eg->altID = makeAltID(CurBlockID,CurAltNum); *****/ |
| /* MR7 ***** CurAltStart->exception_label = eg->altID; *****/ |
| list_add(&CurExGroups, (void *)eg); |
| } |
| >> |
| )* |
| |
| <<CurAltNum++;>> |
| |
| )* |
| <<$0 = b;>> |
| <<attribsRefdFromAction = saveblah; inAlt = saveinalt;>> |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| alt[set *toksrefd, set *rulesrefd] |
| : <<int n=0,ne=0; Graph g; int e_num=0, not=0; Node *node; set elems, dif; |
| int first_on_line = 1, use_def_MT_handler = 0; |
| g.left=NULL; g.right=NULL; |
| |
| CurAltStart = NULL; |
| elems = empty; |
| inAlt = 1; |
| >> |
| { "\@" /* handle MismatchedToken signals with default handler */ |
| <<use_def_MT_handler = 1;>> |
| } |
| ( <<int tok;>> |
| { <<not=0;>> "\~" <<not=1;>> } |
| element[not, first_on_line, use_def_MT_handler] > [node] |
| <<if ( node!=NULL && node->ntype!=nAction ) first_on_line = 0;>> |
| << |
| if ( $2.left!=NULL ) { |
| g = Cat(g, $2); |
| n++; |
| if ( node!=NULL ) { |
| if ( node->ntype!=nAction ) e_num++; |
| /* record record number of all rule and token refs */ |
| if ( node->ntype==nToken ) { |
| TokNode *tk = (TokNode *)((Junction *)$2.left)->p1; |
| tk->elnum = e_num; |
| set_orel(e_num, &elems); |
| } |
| else if ( node->ntype==nRuleRef ) { |
| RuleRefNode *rn = (RuleRefNode *)((Junction *)$2.left)->p1; |
| rn->elnum = e_num; |
| set_orel(e_num, $rulesrefd); |
| } |
| } |
| } |
| >> |
| )* |
| <<if ( n == 0 ) g = emptyAlt(); |
| $0 = g; |
| /* We want to reduce number of LT(i) calls and the number of |
| * local attribute variables in C++ mode (for moment, later we'll |
| * do for C also). However, if trees are being built, they |
| * require most of the attrib variables to create the tree nodes |
| * with; therefore, we gen a token ptr for each token ref in C++ |
| */ |
| if ( GenCC && !GenAST ) |
| { |
| /* This now free's the temp set -ATG 5/6/95 */ |
| set temp; |
| temp = set_and(elems, attribsRefdFromAction); |
| set_orin($toksrefd, temp); |
| set_free(temp); |
| } |
| else set_orin($toksrefd, elems); |
| if ( GenCC ) { |
| dif = set_dif(attribsRefdFromAction, elems); |
| if ( set_deg(dif)>0 ) |
| err("one or more $i in action(s) refer to non-token elements"); |
| set_free(dif); |
| } |
| set_free(elems); |
| set_free(attribsRefdFromAction); |
| inAlt = 0; |
| >> |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| element_label > [LabelEntry *label] |
| : <<TermEntry *t=NULL; LabelEntry *l=NULL; RuleEntry *r=NULL; char *lab;>> |
| LABEL <<lab = mystrdup(LATEXT(1));>> |
| << |
| UsedNewStyleLabel = 1; |
| if ( UsedOldStyleAttrib ) err("cannot mix with new-style labels with old-style $i"); |
| t = (TermEntry *) hash_get(Tname, lab); |
| if ( t==NULL ) t = (TermEntry *) hash_get(Texpr, lab); |
| if ( t==NULL ) r = (RuleEntry *) hash_get(Rname, lab); |
| if ( t!=NULL ) { |
| err(eMsg1("label definition clashes with token/tokclass definition: '%s'", lab)); |
| $label = NULL; |
| } |
| else if ( r!=NULL ) { |
| err(eMsg1("label definition clashes with rule definition: '%s'", lab)); |
| $label = NULL; |
| } |
| else { |
| /* we don't clash with anybody else */ |
| l = (LabelEntry *) hash_get(Elabel, lab); |
| if ( l==NULL ) { /* ok to add new element label */ |
| l = (LabelEntry *)hash_add(Elabel, |
| lab, |
| (Entry *)newLabelEntry(lab)); |
| /* add to list of element labels for this rule */ |
| list_add(&CurElementLabels, (void *)lab); |
| /* MR7 */ leAdd(l); /* list of labels waiting for exception group definitions */ |
| $label = l; |
| } |
| else { |
| err(eMsg1("label definitions must be unique per rule: '%s'", lab)); |
| $label = NULL; |
| } |
| } |
| >> |
| ":" |
| ; |
| |
| element[int not, int first_on_line, int use_def_MT_handler] > [Node *node] |
| : << |
| Attrib blk; |
| Predicate *pred = NULL; |
| int local_use_def_MT_handler=0; |
| ActionNode *act; |
| RuleRefNode *rr; |
| set toksrefd, rulesrefd; |
| TermEntry *term; |
| TokNode *p=NULL; RuleRefNode *q; int approx=0; |
| LabelEntry *label=NULL; |
| $node = NULL; |
| >> |
| {element_label>[label]} |
| ( TokenTerm |
| << |
| term = (TermEntry *) hash_get(Tname, LATEXT(1)); |
| if ( term==NULL && UserDefdTokens ) { |
| err("implicit token definition not allowed with #tokdefs"); |
| $$.left = $$.right = NULL; |
| } |
| else { |
| $$ = buildToken(LATEXT(1)); |
| p=((TokNode *)((Junction *)$$.left)->p1); |
| term = (TermEntry *) hash_get(Tname, LATEXT(1)); |
| require( term!= NULL, "hash table mechanism is broken"); |
| p->tclass = term->tclass; |
| p->complement = $not; |
| if ( label!=NULL ) { |
| p->el_label = label->str; |
| label->elem = (Node *)p; |
| } |
| } |
| >> |
| { ".." |
| ( QuotedTerm |
| <<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>> |
| | TokenTerm |
| <<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>> |
| ) |
| } |
| << |
| if ( p!=NULL && (p->upper_range!=0 || p->tclass || $not) ) |
| list_add(&MetaTokenNodes, (void *)p); |
| >> |
| ( "^" <<if ( p!=NULL ) p->astnode=ASTroot;>> |
| | <<if ( p!=NULL ) p->astnode=ASTchild;>> |
| | "!" <<if ( p!=NULL ) p->astnode=ASTexclude;>> |
| ) |
| { "\@" <<local_use_def_MT_handler = 1;>> } |
| << |
| if ( p!=NULL && $first_on_line ) { |
| CurAltStart = (Junction *)$$.left; |
| altAdd(CurAltStart); /* MR7 */ |
| p->altstart = CurAltStart; |
| } |
| if ( p!=NULL ) |
| p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler; |
| $node = (Node *)p; |
| >> |
| | QuotedTerm |
| << |
| term = (TermEntry *) hash_get(Texpr, LATEXT(1)); |
| if ( term==NULL && UserDefdTokens ) { |
| err("implicit token definition not allowed with #tokdefs"); |
| $$.left = $$.right = NULL; |
| } |
| else { |
| $$ = buildToken(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1); |
| p->complement = $not; |
| if ( label!=NULL ) { |
| p->el_label = label->str; |
| label->elem = (Node *)p; |
| } |
| } |
| >> |
| { ".." |
| ( QuotedTerm |
| <<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>> |
| | TokenTerm |
| <<if ( p!=NULL ) setUpperRange(p, LATEXT(1));>> |
| ) |
| } |
| ( "^" <<if ( p!=NULL ) p->astnode=ASTroot;>> |
| | <<if ( p!=NULL ) p->astnode=ASTchild;>> |
| | "!" <<if ( p!=NULL ) p->astnode=ASTexclude;>> |
| ) |
| { "\@" <<local_use_def_MT_handler = 1;>> } |
| << |
| if ( p!=NULL && (p->upper_range!=0 || p->tclass || $not) ) |
| list_add(&MetaTokenNodes, (void *)p); |
| >> |
| << |
| if ( $first_on_line ) { |
| CurAltStart = (Junction *)$$.left; |
| altAdd(CurAltStart); /* MR7 */ |
| p->altstart = CurAltStart; |
| } |
| if ( p!=NULL ) |
| p->use_def_MT_handler = $use_def_MT_handler || local_use_def_MT_handler; |
| $node = (Node *)p; |
| >> |
| |
| | <<if ( $not ) warn("~ WILDCARD is an undefined operation (implies 'nothing')");>> |
| "." |
| <<$$ = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);>> |
| ( "^" <<p->astnode=ASTroot;>> |
| | <<p->astnode=ASTchild;>> |
| | "!" <<p->astnode=ASTexclude;>> |
| ) |
| <<list_add(&MetaTokenNodes, (void *)p);>> |
| << |
| if ( $first_on_line ) { |
| CurAltStart = (Junction *)$$.left; |
| altAdd(CurAltStart); /* MR7 */ |
| p->altstart = CurAltStart; |
| if ( label!=NULL ) { |
| p->el_label = label->str; |
| label->elem = (Node *)p; |
| } |
| } |
| $node = (Node *)p; |
| >> |
| |
| | <<if ( $not ) warn("~ NONTERMINAL is an undefined operation");>> |
| NonTerminal |
| <<$$ = buildRuleRef(LATEXT(1));>> |
| { "!" <<q = (RuleRefNode *) ((Junction *)$$.left)->p1; |
| q->astnode=ASTexclude;>> |
| } |
| { {"\<"} |
| PassAction <<addParm(((Junction *)$$.left)->p1, LATEXT(1));>> |
| } |
| <<rr=(RuleRefNode *) ((Junction *)$$.left)->p1;>> |
| { <<char *a;>> |
| "\>" |
| PassAction |
| << |
| a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require(a!=NULL, "rule element: cannot allocate assignment"); |
| strcpy(a, LATEXT(1)); |
| rr->assign = a; |
| >> |
| } |
| << |
| if ( label!=NULL ) { |
| rr->el_label = label->str; |
| label->elem = (Node *)rr; |
| } |
| if ( $first_on_line ) { |
| CurAltStart = (Junction *)$$.left; |
| altAdd(CurAltStart); /* MR7 */ |
| ((RuleRefNode *)((Junction *)$$.left)->p1)->altstart = CurAltStart; |
| } |
| $node = (Node *)rr; |
| >> |
| ) |
| |
| | <<if ( $not ) warn("~ ACTION is an undefined operation");>> |
| Action <<$0 = buildAction(LATEXT(1),action_file,action_line, 0);>> |
| <<if ( $first_on_line ) { /* MR7 */ |
| CurAltStart = (Junction *)$0.left; /* MR7 */ |
| altAdd(CurAltStart); /* MR7 */ |
| };>> /* MR7 */ |
| <<$node = (Node *) ((Junction *)$0.left)->p1;>> |
| |
| | <<if ( $not ) warn("~ SEMANTIC-PREDICATE is an undefined operation");>> |
| Pred <<$0 = buildAction(LATEXT(1),action_file,action_line, 1);>> |
| <<act = (ActionNode *) ((Junction *)$0.left)->p1;>> |
| { <<char *a;>> |
| PassAction |
| << |
| a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require(a!=NULL, "rule element: cannot allocate predicate fail action"); |
| strcpy(a, LATEXT(1)); |
| act->pred_fail = a; |
| >> |
| } |
| <<if ( $first_on_line ) { /* MR7 */ |
| CurAltStart = (Junction *)$0.left; /* MR7 */ |
| altAdd(CurAltStart); /* MR7 */ |
| };>> /* MR7 */ |
| <<$node = (Node *)act;>> |
| |
| | <<if ( $not ) warn("~ BLOCK is an undefined operation");>> |
| <<BlkLevel++;>> |
| { "#pragma" |
| ( "approx" <<approx=LL_k;>> |
| | "LL(1)" <<approx = 1;>> |
| | "LL(2)" <<approx = 2;>> |
| ) |
| } |
| ( "\(" block[&toksrefd,&rulesrefd] "\)" |
| <<blk = $$ = $2; --BlkLevel;>> |
| ( "\*" <<$$ = makeLoop($$,approx);>> |
| | "\+" <<$$ = makePlus($$,approx);>> |
| | "?" |
| ( "=>" Pred /* generalized predicate */ |
| /* first make into a predicate */ |
| <<$$ = buildAction(LATEXT(1),action_file,action_line,1);>> |
| <<act = (ActionNode *) ((Junction *)$$.left)->p1;>> |
| { <<char *a;>> |
| PassAction |
| << |
| a = (char *)calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require(a!=NULL, "rule element: cannot allocate predicate fail action"); |
| strcpy(a, LATEXT(1)); |
| act->pred_fail = a; |
| >> |
| } |
| <<if ($first_on_line) { /* MR7 */ |
| CurAltStart=(Junction *)$$.left; /* MR7 */ |
| altAdd(CurAltStart); /* MR7 */ |
| };>> |
| <<$node = (Node *)act;>> |
| |
| /* for now, just snag context */ |
| << |
| pred = computePredicateFromContextGuard(blk); |
| if ( pred==NULL ) |
| err("invalid or missing context guard"); |
| else { |
| pred->expr = act->action; |
| pred->source = act; |
| act->guardpred = pred; |
| } |
| >> |
| | <<$$ = makeBlk($$,approx); |
| FoundGuessBlk = 1; |
| ((Junction *) ((Junction *)$$.left)->p1)->guess=1; |
| if ( !$first_on_line ) { |
| err("(...)? predicate must be first element of production"); |
| } |
| >> |
| ) |
| | <<$$ = makeBlk($$,approx);>> |
| ) |
| << |
| if ( pred==NULL ) { |
| ((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID; |
| ((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd; |
| ((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd; |
| if ( $first_on_line ) { /* MR7 */ |
| CurAltStart = (Junction *)((Junction *)((Junction *)$$.left)->p1); /* MR7 */ |
| altAdd(CurAltStart); /* MR7 */ |
| }; /* MR7 */ |
| $node = (Node *) ((Junction *)$$.left)->p1; |
| } |
| >> |
| |
| | "\{" block[&toksrefd,&rulesrefd] |
| <<$$ = makeOpt($2,approx); --BlkLevel;>> |
| "\}" |
| << |
| ((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID; |
| ((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd; |
| ((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd; |
| >> |
| <<if ( $first_on_line ) { /* MR7 */ |
| CurAltStart = (Junction *) ((Junction *)((Junction *)$$.left)->p1); /* MR7 */ |
| altAdd(CurAltStart); /* MR7 */ |
| }; |
| >> |
| <<$node = (Node *) ((Junction *)$$.left)->p1;>> |
| |
| ) |
| |
| /* Error catching alternatives */ |
| | "\*" <<warn("don't you want a ')' with that '*'?"); CannotContinue=TRUE;>> |
| | "\+" <<warn("don't you want a ')' with that '+'?"); CannotContinue=TRUE;>> |
| | "\>" <<warn("'>' can only appear after a nonterminal"); CannotContinue=TRUE;>> |
| | PassAction <<warn("[...] out of context 'rule > [...]'"); |
| CannotContinue=TRUE;>> |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| default_exception_handler |
| : exception_group > [DefaultExGroup] |
| ; |
| |
| exception_group > [ExceptionGroup *eg] |
| : <<ExceptionHandler *h; LabelEntry *label=NULL; /* MR6 */ |
| FoundException = 1; FoundExceptionGroup = 1;>> /* MR6 */ |
| |
| "exception" <<$eg = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup));>> |
| { <<char *p;>> |
| PassAction /* did they attach a label? */ |
| << |
| p = LATEXT(1)+1; |
| p[strlen(p)-1] = '\0'; /* kill trailing space */ |
| label = (LabelEntry *) hash_get(Elabel, LATEXT(1)+1); |
| if ( label==NULL ) |
| { |
| err(eMsg1("unknown label in exception handler: '%s'", LATEXT(1)+1)); |
| } |
| >> |
| } |
| ( exception_handler > [h] |
| <<list_add(&($eg->handlers), (void *)h);>> |
| )* |
| { "default" ":" Action |
| <<{ |
| ExceptionHandler *eh = (ExceptionHandler *) |
| calloc(1, sizeof(ExceptionHandler)); |
| char *a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require(eh!=NULL, "exception: cannot allocate handler"); |
| require(a!=NULL, "exception: cannot allocate action"); |
| strcpy(a, LATEXT(1)); |
| eh->action = a; |
| eh->signalname = (char *) calloc(strlen("default")+1, sizeof(char)); |
| require(eh->signalname!=NULL, "exception: cannot allocate sig name"); |
| strcpy(eh->signalname, "default"); |
| list_add(&($eg->handlers), (void *)eh); |
| }>> |
| } |
| |
| << |
| if ( label!=NULL ) { |
| /* Record ex group in sym tab for this label */ |
| if ( label->ex_group!=NULL ) { |
| err(eMsg1("duplicate exception handler for label '%s'",label->str)); |
| } else { |
| label->ex_group = $eg; |
| /* Label the exception group itself */ |
| $eg->label = label->str; |
| /* Make the labelled element pt to the exception also */ |
| /* MR6 */ if (label->elem == NULL) { |
| /* MR6 */ err(eMsg1("reference in exception handler to undefined label '%s'",label->str)); |
| /* MR6 */ } else { |
| switch ( label->elem->ntype ) { |
| case nRuleRef : |
| { |
| RuleRefNode *r = (RuleRefNode *)label->elem; |
| r->ex_group = $eg; |
| break; |
| } |
| case nToken : |
| { |
| TokNode *t = (TokNode *)label->elem; |
| t->ex_group = $eg; |
| break; |
| } |
| } /* end switch */ |
| /* MR6 */ }; /* end test on label->elem */ |
| } /* end test on label->ex_group */ |
| |
| } /* end test on exception label */ |
| |
| /* MR7 */ |
| /* MR7 */ if (BlkLevel == 1 && label == NULL) { |
| /* MR7 */ $eg->forRule=1; |
| /* MR7 */ } else if (label == NULL) { |
| /* MR7 */ $eg->altID = makeAltID(CurBlockID,CurAltNum); |
| /* MR7 */ egAdd($eg); |
| /* MR7 */ } else { |
| /* MR7 */ $eg->labelEntry=label; |
| /* MR7 */ }; |
| /* MR7 */ |
| /* MR7 */ /* You may want to remove this exc from the rule list */ |
| /* MR7 */ /* and handle at the labeled element site. */ |
| /* MR7 */ |
| /* MR7 */ if (label != NULL) { |
| /* MR7 */ $eg = NULL; |
| /* MR7 */ }; |
| |
| >> |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| exception_handler > [ExceptionHandler *eh] |
| : <<char *a;>> |
| "catch" |
| << |
| $eh = (ExceptionHandler *)calloc(1, sizeof(ExceptionHandler)); |
| require($eh!=NULL, "exception: cannot allocate handler"); |
| >> |
| ( NonTerminal |
| << |
| $eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require($eh->signalname!=NULL, "exception: cannot allocate sig name"); |
| strcpy($eh->signalname, LATEXT(1)); |
| >> |
| | TokenTerm |
| << |
| $eh->signalname = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require($eh->signalname!=NULL, "exception: cannot allocate sig name"); |
| strcpy($eh->signalname, LATEXT(1)); |
| >> |
| ) |
| ":" |
| { <<$eh->action = NULL;>> |
| Action |
| << |
| $eh->action = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); |
| require($eh->action!=NULL, "exception: cannot allocate action"); |
| strcpy($eh->action, LATEXT(1)); |
| >> |
| } |
| ; |
| <<CannotContinue=TRUE;>> |
| |
| #token NonTerminal "[a-z] [A-Za-z0-9_]*" |
| << |
| while ( zzchar==' ' || zzchar=='\t' ) { |
| zzadvance(); |
| } |
| if ( zzchar == ':' && inAlt ) NLA = LABEL; |
| >> |
| #token TokenTerm "[A-Z] [A-Za-z0-9_]*" |
| << |
| while ( zzchar==' ' || zzchar=='\t' ) { |
| zzadvance(); |
| } |
| if ( zzchar == ':' && inAlt ) NLA = LABEL; |
| >> |
| #token "#[A-Za-z0-9_]*" <<warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); >> |
| |
| #lexclass PARSE_ENUM_FILE |
| |
| #token "[\t\ ]+" << zzskip(); >> /* Ignore White */ |
| #token "[\n\r]" << zzline++; zzskip(); >> /* Track Line # */ |
| #token "//" << zzmode(TOK_DEF_CPP_COMMENTS); zzmore(); >> |
| #token "/\*" << zzmode(TOK_DEF_COMMENTS); zzskip(); >> |
| #token "#ifdef" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> |
| #token "#if" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> |
| #token "#ifndef" << ; >> |
| #token "#else" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> |
| #token "#endif" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> |
| #token "#undef" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> |
| #token "#import" << zzmode(TOK_DEF_CPP_COMMENTS); zzskip(); >> |
| #token "@" << ; >> |
| |
| enum_file[char *fname] |
| : { "#ifndef" ID |
| { "#define" ID /* ignore if it smells like a gate */ |
| /* First #define after the first #ifndef (if any) is ignored */ |
| } |
| } |
| ( ( enum_def[$fname] )+ |
| | defines[$fname] |
| ) |
| | |
| ; |
| |
| defines[char *fname] |
| : <<int v; int maxt=(-1); char *t;>> /* MR3 */ |
| ( |
| "#define" ID |
| <<t = mystrdup(LATEXT(1));>> |
| INT |
| << |
| v = atoi(LATEXT(1)); |
| /* fprintf(stderr, "#token %s=%d\n", t, v);*/ |
| |
| /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ |
| /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ |
| /* MR2 Don't let #tokdefs be confused by */ |
| /* MR2 DLGminToken and DLGmaxToken */ |
| |
| if ( ! isDLGmaxToken(t)) { /* MR2 */ |
| TokenNum = v; |
| if ( v>maxt ) maxt=v; |
| if ( Tnum( t ) == 0 ) { |
| addForcedTname( t, v ); |
| } else { |
| warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline); |
| }; |
| }; |
| >> |
| )+ |
| <<TokenNum = maxt + 1;>> |
| ; |
| |
| enum_def[char *fname] |
| : <<int v= 0; int maxt=(-1); char *t;>> /* MR3 */ |
| "enum" ID |
| "\{" |
| ID |
| <<t = mystrdup(LATEXT(1));>> |
| ( "=" INT <<v=atoi(LATEXT(1));>> |
| | <<v++;>> |
| ) |
| << |
| /* fprintf(stderr, "#token %s=%d\n", t, v);*/ |
| TokenNum = v; |
| if ( v>maxt ) maxt=v; /* MR3 */ |
| if ( Tnum( t ) == 0 ) addForcedTname( t, v ); |
| else { |
| warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline); |
| } |
| >> |
| ( "," |
| |
| /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ |
| /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ |
| /* MR2 Don't let #tokdefs be confused by */ |
| /* MR2 DLGminToken and DLGmaxToken */ |
| |
| { |
| <<isDLGmaxToken(LATEXT(1))>>? ID { "=" INT } /* MR2 */ |
| | ID /* MR2 */ |
| <<t = mystrdup(LATEXT(1));>> |
| ( "=" INT <<v=atoi(LATEXT(1));>> |
| | <<v++;>> |
| ) |
| << |
| /* fprintf(stderr, "#token %s=%d\n", t, v);*/ |
| TokenNum = v; |
| if ( v>maxt ) maxt=v; /* MR3 */ |
| if ( Tnum( t ) == 0 ) addForcedTname( t, v ); |
| else { |
| warnFL(eMsg1("redefinition of token %s; ignored",t),$fname,zzline); |
| } |
| >> |
| } |
| )* |
| "\}" |
| ";" |
| <<TokenNum = maxt + 1;>> /* MR3 */ |
| ; |
| |
| #token INT "[0-9]+" |
| #token ID "[a-zA-Z_][_a-zA-Z0-9]*" |
| |
| #lexclass START |
| |
| << |
| |
| /* MR2 Andreas Magnusson (Andreas.Magnusson@mailbox.swipnet.se) */ |
| /* MR2 Fix to bug introduced by 1.33MR1 for #tokdefs */ |
| /* MR2 Don't let #tokdefs be confused by */ |
| /* MR2 DLGminToken and DLGmaxToken */ |
| |
| /* semantic check on DLGminToken and DLGmaxmaxToken in #tokdefs */ |
| |
| #ifdef __USE_PROTOS |
| static int isDLGmaxToken(char *Token) |
| #else |
| static int isDLGmaxToken(Token) |
| char * Token; |
| #endif |
| { |
| static char checkStr1[] = "DLGmaxToken"; |
| static char checkStr2[] = "DLGminToken"; |
| |
| if (strcmp(Token, checkStr1) == 0) |
| return 1; |
| else if (strcmp(Token, checkStr2) == 0) |
| return 1; |
| else |
| return 0; |
| } |
| |
| /* semantics of #token */ |
| static void |
| #ifdef __USE_PROTOS |
| chkToken(char *t, char *e, char *a, int tnum) |
| #else |
| chkToken(t,e,a,tnum) |
| char *t, *e, *a; |
| int tnum; |
| #endif |
| { |
| TermEntry *p; |
| |
| /* check to see that they don't try to redefine a token as a token class */ |
| if ( t!=NULL ) { |
| p = (TermEntry *) hash_get(Tname, t); |
| if ( p!=NULL && p->classname ) { |
| err(eMsg1("redefinition of #tokclass '%s' to #token not allowed; ignored",t)); |
| if ( a!=NULL ) free((char *)a); |
| return; |
| } |
| } |
| |
| if ( t==NULL && e==NULL ) { /* none found */ |
| err("#token requires at least token name or rexpr"); |
| } |
| else if ( t!=NULL && e!=NULL ) { /* both found */ |
| if ( UserDefdTokens ) { /* if #tokdefs, must not define new */ |
| p = (TermEntry *) hash_get(Tname, t); |
| if ( p==NULL ) { |
| err(eMsg1("#token definition '%s' not allowed with #tokdefs; ignored",t)); |
| return; |
| } |
| } |
| Tklink(t, e); |
| if ( a!=NULL ) { |
| if ( hasAction(e) ) { |
| err(eMsg1("redefinition of action for %s; ignored",e)); |
| } |
| else setHasAction(e, a); |
| } |
| } |
| else if ( t!=NULL ) { /* only one found */ |
| if ( UserDefdTokens ) { |
| err(eMsg1("#token definition '%s' not allowed with #tokdefs; ignored",t)); |
| return; |
| } |
| if ( Tnum( t ) == 0 ) addTname( t ); |
| else { |
| err(eMsg1("redefinition of token %s; ignored",t)); |
| } |
| if ( a!=NULL ) { |
| err(eMsg1("action cannot be attached to a token name (%s); ignored",t)); |
| free((char *)a); |
| } |
| } |
| else if ( e!=NULL ) { |
| if ( Tnum( e ) == 0 ) addTexpr( e ); |
| else { |
| if ( hasAction(e) ) { |
| err(eMsg1("redefinition of action for expr %s; ignored",e)); |
| } |
| else if ( a==NULL ) { |
| err(eMsg1("redefinition of expr %s; ignored",e)); |
| } |
| } |
| if ( a!=NULL ) setHasAction(e, a); |
| } |
| |
| /* if a token type number was specified, then add the token ID and 'tnum' |
| * pair to the ForcedTokens list. (only applies if an id was given) |
| */ |
| if ( t!=NULL && tnum>0 ) |
| { |
| if ( set_el(tnum, reserved_positions) ) |
| { |
| err(eMsgd("a token has already been forced to token number %d; ignored", tnum)); |
| } |
| else |
| { |
| list_add(&ForcedTokens, newForcedToken(t,tnum)); |
| set_orel(tnum, &reserved_positions); |
| } |
| } |
| } |
| >> |
| |
| << |
| static int |
| #ifdef __USE_PROTOS |
| match_token(char *s, char **nxt) |
| #else |
| match_token(s,nxt) |
| char *s; |
| char **nxt; |
| #endif |
| { |
| if ( !(*s>='A' && *s<='Z') ) return 0; |
| s++; |
| while ( (*s>='a' && *s<='z') || |
| (*s>='A' && *s<='Z') || |
| (*s>='0' && *s<='9') || |
| *s=='_' ) |
| { |
| s++; |
| } |
| if ( *s!=' ' && *s!='}' ) return 0; |
| *nxt = s; |
| return 1; |
| } |
| |
| static int |
| #ifdef __USE_PROTOS |
| match_rexpr(char *s, char **nxt) |
| #else |
| match_rexpr(s,nxt) |
| char *s; |
| char **nxt; |
| #endif |
| { |
| if ( *s!='"' ) return 0; |
| s++; |
| while ( *s!='"' ) |
| { |
| if ( *s=='\n' ) |
| warn("eoln found in regular expression"); |
| if ( *s=='\\' ) s++; |
| s++; |
| } |
| *nxt = s+1; |
| return 1; |
| } |
| |
| /* |
| * Walk a string "{ A .. Z }" where A..Z is a space separated list |
| * of token references (either labels or reg exprs). Return a |
| * string "inlineX_set" for some unique integer X. Basically, |
| * we pretend as if we had seen "#tokclass inlineX { A .. Z }" |
| * on the input stream outside of an action. |
| */ |
| char * |
| #ifdef __USE_PROTOS |
| inline_set(char *s) |
| #else |
| inline_set(s) |
| char *s; |
| #endif |
| { |
| char *nxt; |
| fprintf(stderr, "found consumeUntil( {...} )\n"); |
| while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} |
| if ( *s!='{' ) |
| { |
| err("malformed consumeUntil( {...} ); missing '{'"); |
| return "bad_set"; |
| } |
| s++; |
| while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} |
| while ( *s!='}' ) |
| { |
| if ( match_token(s,&nxt) ) fprintf(stderr, "found token %s\n", s); |
| else if ( match_rexpr(s,&nxt) ) fprintf(stderr, "found rexpr %s\n", s); |
| else { |
| err("invalid element in consumeUntil( {...} )"); |
| return "bad_set"; |
| } |
| s = nxt; |
| while ( *s==' ' || *s=='\t' || *s=='\n' || *s=='\r' ) {s++;} |
| } |
| return "inlineX_set"; |
| } |
| >> |
| |
| << |
| /* ANTLR-specific syntax error message generator |
| * (define USER_ZZSYN when compiling so don't get 2 definitions) |
| */ |
| void |
| #ifdef __USE_PROTOS |
| zzsyn(char *text, int tok, char *egroup, SetWordType *eset, int etok, |
| int k, char *bad_text) |
| #else |
| zzsyn(text, tok, egroup, eset, etok, k, bad_text) |
| char *text, *egroup, *bad_text; |
| int tok; |
| int etok; |
| int k; |
| SetWordType *eset; |
| #endif |
| { |
| fprintf(stderr, ErrHdr, FileStr[CurFile]!=NULL?FileStr[CurFile]:"stdin", zzline); |
| fprintf(stderr, " syntax error at \"%s\"", (tok==zzEOF_TOKEN)?"EOF":text); |
| if ( !etok && !eset ) {fprintf(stderr, "\n"); return;} |
| if ( k==1 ) fprintf(stderr, " missing"); |
| else |
| { |
| fprintf(stderr, "; \"%s\" not", bad_text); |
| if ( zzset_deg(eset)>1 ) fprintf(stderr, " in"); |
| } |
| if ( zzset_deg(eset)>0 ) zzedecode(eset); |
| else fprintf(stderr, " %s", zztokens[etok]); |
| if ( strlen(egroup) > (size_t)0 ) fprintf(stderr, " in %s", egroup); |
| fprintf(stderr, "\n"); |
| } |
| >> |