/* * antlr.g -- PCCTS Version 1.xx ANTLR * * 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 "pcctscfg.h" */ /* MR1 */ #header << #include "pcctscfg.h" #include "set.h" #include #include "syn.h" #include "hash.h" #include "generic.h" #define zzcr_attr(attr,tok,t) >> << /* MR20 G. Hobbelt For Borland C++ 4.x & 5.x compiling with ALL warnings enabled */ #if defined(__TURBOC__) #pragma warn -aus /* unused assignment of 'xxx' */ #endif #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; /* MR20 G. Hobbelt extern definitions moved to antlr.h */ >> #lexaction << /* maintained, but not used for now */ set AST_nodes_refd_in_actions = set_init; int inAlt = 0; set attribsRefdFromAction = set_init; /* MR20 */ 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|\r\n" << zzline++; warn("eoln found in string"); zzskip(); >> #token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >> #token "\\~[]" << zzmore(); >> #token "~[\n\r\"\\]+" << zzmore(); >> #lexclass ACTION_STRINGS #token "\"" << zzmode(ACTIONS); zzmore(); >> #token "\n|\r|\r\n" << zzline++; warn("eoln found in string (in user action)"); zzskip(); >> #token "\\(\n|\r|\r\n)" << zzline++; zzmore(); >> #token "\\~[]" << zzmore(); >> #token "~[\n\r\"\\]+" << zzmore(); >> #lexclass ACTION_CHARS #token "'" << zzmode(ACTIONS); zzmore(); >> #token "\n|\r|\r\n" << 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|\r\n" << zzline++; zzmore(); DAWDLE; >> #token "~[\n\r\*]+" << zzmore(); >> #lexclass TOK_DEF_COMMENTS #token "\*/" << zzmode(PARSE_ENUM_FILE); zzmore(); >> #token "\*" << zzmore(); >> #token "\n|\r|\r\n" << zzline++; zzmore(); DAWDLE; >> #token "~[\n\r\*]+" << zzmore(); >> #lexclass TOK_DEF_CPP_COMMENTS #token "\n|\r|\r\n" << zzline++; zzmode(PARSE_ENUM_FILE); zzskip(); DAWDLE; >> #token "~[\n\r]+" << zzskip(); >> #lexclass ACTION_CPP_COMMENTS #token "\n|\r|\r\n" << zzline++; zzmode(ACTIONS); zzmore(); DAWDLE; >> #token "~[\n\r]+" << zzmore(); >> #lexclass CPP_COMMENTS #token "\n|\r|\r\n" << zzline++; zzmode(START); zzskip(); DAWDLE; >> #token "~[\n\r]+" << zzskip(); >> #lexclass COMMENTS #token "\*/" << zzmode(START); zzskip(); >> #token "\*" << zzskip(); >> #token "\n|\r|\r\n" << 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)); }; #ifdef __cplusplus__ /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); #else #ifdef __STDC__ /* MR10 */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); #else #ifdef __USE_PROTOS /* MRxx */ list_apply(CurActionLabels, (void (*)(void *))mark_label_used_in_sem_pred); #else /* MR10 */ list_apply(CurActionLabels,mark_label_used_in_sem_pred); #endif #endif #endif >> #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|\r\n" << 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]; numericActionLabel=1; /* MR10 */ 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]; numericActionLabel=1; /* MR10 */ 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; numericActionLabel=1; /* MR10 */ 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 ( hasMultipleOperands( 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 ) { /* MR10 */ /* MR10 */ /* element labels might exist without an elem when */ /* MR10 */ /* it is a forward reference (to a rule) */ /* MR10 */ /* MR10 */ if ( GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) ) /* MR10 */ { err(eMsg1("There are no token ptrs for rule references: '$%s'",&zzbegexpr[1])); } /* MR10 */ /* MR10 */ if ( !GenCC && (el->elem == NULL || el->elem->ntype==nRuleRef) && GenAST) { /* MR10 */ err("You can no longer use attributes returned by rules when also using ASTs"); /* MR10 */ err(" Use upward inheritance (\"rule >[Attrib a] : ... <<$a=...\>\>\")"); /* MR10 */ }; /* MR10 */ /* MR10 */ /* keep track of <<... $label ...>> for semantic predicates in guess mode */ /* MR10 */ /* element labels contain pointer to the owners node */ /* MR10 */ /* MR10 */ if (el->elem != NULL && el->elem->ntype == nToken) { /* MR10 */ list_add(&CurActionLabels,el); /* MR10 */ }; } else warn(eMsg1("$%s not parameter, return value, (defined) element label",&zzbegexpr[1])); } zzmore(); >> #token "#0" << zzreplstr("(*_root)"); zzmore(); chkGTFlag(); >> #token "#\[\]" << if ( GenCC ) { if (NewAST) zzreplstr("(newAST)"); else 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(); } >> /* MR14 Arpad Beszedes 26-May-98 Add support for #line directives when antlr source is pre-processed #lexclass ACTIONS */ #token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)" << zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); >> #token "#line ~[\n\r]* (\n|\r|\r\n)" << zzline++; zzmore(); >> /* MR14 end of a block to support #line in antlr source code */ #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); /* MR27 */ list_add(&CurAstLabelsInActions, mystrdup(zzbegexpr+1)); zzreplstr(buf); chkGTFlag(); } zzmore(); >> #token "#\[" << pushint(']'); if ( GenCC ) { if (NewAST) zzreplstr("(newAST("); else zzreplstr("(new AST("); } else zzreplstr("zzmk_ast(zzastnew(),"); zzmore(); chkGTFlag(); >> #token "#\(" << pushint('}'); if ( GenCC ) { if (tmakeInParser) { zzreplstr("tmake("); } else { 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|\r\n)" << 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|\r\n" << zzline++; zzskip(); >> /* Track Line # */ #token "\[" << zzmode(ACTIONS); zzmore(); istackreset(); pushint(']'); >> #token "\<\<" << action_file=CurFile; action_line=zzline; zzmode(ACTIONS); zzmore(); list_free(&CurActionLabels,0); /* MR10 */ numericActionLabel=0; /* MR10 */ istackreset(); pushint('>'); >> #token "\"" << zzmode(STRINGS); zzmore(); >> #token "/\*" << zzmode(COMMENTS); zzskip(); >> #token "\*/" << warn("Missing /*; found dangling */"); zzskip(); >> #token "//" << zzmode(CPP_COMMENTS); zzskip(); >> /* MR14 Arpad Beszedes 26-May-98 Add support for #line directives when antlr source is pre-processed #lexclass START */ #token "#line[\ \t]* [0-9]+ {[\ \t]* \"~[\"]+\" ([\ \t]* [0-9]*)* } (\n|\r|\r\n)" << zzline = atoi(zzbegexpr+5) - 1; zzline++; zzmore(); getFileNameFromTheLineInfo(FileStr[CurFile], zzbegexpr); >> #token "#line ~[\n\r]* (\n|\r|\r\n)" << zzline++; zzmore(); >> /* MR14 end of a block to support #line in antlr source code */ /* */ /* 8-Apr-97 Regularize escape sequence for ">>" */ /* appearing in string literals */ /* */ #token "\>\>" << warn("Missing <<; found dangling \>\>"); zzskip(); >> /* MR1 */ #token WildCard "." #token "\@" <> /* 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" { "\}" "!" ";" "\|" "\~" "^" "\)" } #token Pragma "{\\}#pragma" /* MR21 */ #token FirstSetSymbol "{\\}#FirstSetSymbol" /* MR21 */ /* * Get a grammar -- Build a list of rules like: * * o-->Rule1--o * | * o-->Rule2--o * | * ... * | * o-->RuleN--o */ /* rule grammar */ grammar : <> ( "{\\}#header" Action /* MR13 */ << 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"); >> | "{\\}#first" Action << if ( FirstAction==NULL ) { FirstAction = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); require(FirstAction!=NULL, "rule grammar: cannot allocate #first action"); strcpy(FirstAction, LATEXT(1)); } else { warn("additional #first 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 | aPred /* MR11 */ | default_exception_handler | class_def | "\}" << if ( class_nest_level==0 ) warn("missing class definition for trailing '}'"); class_nest_level--; >> )* rule <> ( rule <> | aLexclass | token | error | tclass | aPred /* MR11 */ | 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 | aPred /* MR11 */ | "\}" << if ( class_nest_level==0 ) warn("missing class definition for trailing '}'"); class_nest_level--; >> )* Eof ; <> /* rule class_def */ class_def : <> "class" ( NonTerminal <> | TokenTerm <> ) << if ( CurrentClassName[0]!='\0' && strcmp(CurrentClassName,name)!=0 && GenCC ) { err("only one grammar class allowed in this release"); go = 0; } else strcpy(CurrentClassName, name); >> <> /* MR10 */ (~ "\{" /* MR10 */ <> /* MR10 */ )* "\{" << no_classes_found = 0; if ( class_nest_level>=1 ) {warn("cannot have nested classes");} else class_nest_level++; >> ; <> /* * 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 rule */ rule : << 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; CurAstLabelsInActions = NULL; /* MR27 */ /* We want a new element label hash table for each rule */ if ( Elabel!=NULL ) killHashTable(Elabel); Elabel = newHashTable(); attribsRefdFromAction = empty; >> NonTerminal <str; } CurRuleNode = q; f = CurFile; l = zzline; NumRules++; >> { "!" <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 <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); } } >> <= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; >> ":" <> block[&toksrefd, &rulesrefd] <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; >> << /* MR23 */ CurBlockID_array[BlkLevel] = (-1); /* MR23 */ CurAltNum_array[BlkLevel] = (-1); --BlkLevel; >> <> /* MR7 */ ";" <> { 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] <label == NULL || *eg->label=='\0' ) q->has_rule_exception = 1; } >> )* <> <exceptions = CurExGroups;>> <el_labels = CurElementLabels;>> <ast_labels_in_actions = CurAstLabelsInActions;>> /* MR27 */ <> /* MR27 Moved */ ; <> /* * pragma : "{\\}#pragma" "dup\-labeled\-tokens" * <> * ; */ /* rule laction */ laction : <> "{\\}#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); >> ; <> /* MR1 */ /* MR1 11-Apr-97 Provide mechanism for inserting code into DLG class */ /* MR1 via #lexmember <<....>> & #lexprefix <<...>> */ /* MR1 */ /* rule lmember */ lmember: <> /* 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 */ <> /* rule lprefix */ lprefix: <> /* MR1 */ /* MR1 */ "{\\}#lexprefix" /* MR1 */ Action /* MR1 */ << /* MR1 */ if (! GenCC) { /* MR1 */ err("Use #lexprefix 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 */ <> /* * #pred upper <>? predicate literal * #pred lower <>? predicate literal * #pred up_or_low upper || lower predicate expression * concealed interdependence * #pred up_or_low_2 <>? A || B predicate literal equals predicate expr * analyze using lower||upper * generate using isLetter() */ /* rule aPref */ aPred: <> "{\\}#pred" << MR_usingPredNames=1; /* will need to use -mrhoist version of genPredTree */ >> /* used to allow NonTerminal but it caused problems when a rule name immediately followed a #pred statement */ TokenTerm <> << /* don't free - referenced in predicates */ CurPredName=(char *)calloc(1,strlen(name) + 10); strcat(CurPredName,"#pred "); strcat(CurPredName,name); predEntry=(PredEntry *) hash_get(Pname,name); if (predEntry != NULL) { warnFL(eMsg1("#pred %s previously defined - ignored",name), FileStr[action_file],action_line); name=NULL; }; >> ( Pred <> { predOrExpr>[predExpr] <> } <file=save_file; predEntry->line=save_line; predExpr=MR_predFlatten(predExpr); predEntry->predLiteral=predLiteral; if (! predExprPresent || predExpr == NULL) { predExpr=new_pred(); predExpr->expr=predLiteral; predExpr->source=newActionNode(); predExpr->source->action=predExpr->expr; predExpr->source->rname=CurPredName; predExpr->source->line=action_line; predExpr->source->file=action_file; predExpr->source->is_predicate=1; predExpr->k=predicateLookaheadDepth(predExpr->source); }; predEntry->pred=predExpr; hash_add(Pname,name,(Entry *)predEntry); predExpr=NULL; }; predicate_free(predExpr); >> | <> predOrExpr>[predExpr] <file=CurFile; predEntry->line=zzline; predExpr=MR_predFlatten(predExpr); predEntry->pred=predExpr; hash_add(Pname,name,(Entry *)predEntry); predExpr=NULL; }; predicate_free(predExpr); >> ) {";"} ; /* fail */ <> /* rule predOrExpr */ predOrExpr>[Predicate *result] : <> predAndExpr>[predExpr] << ORnode=new_pred(); ORnode->expr=PRED_OR_LIST; if (predExpr != NULL) { ORnode->down=predExpr; tail=&predExpr->right; }; >> ( "\|\|" predAndExpr>[predExpr] << if (predExpr != NULL) { *tail=predExpr; tail=&predExpr->right; }; >> )* << $result=ORnode; ORnode=NULL; >> ; /* fail */ <> /* rule predAndExpr */ predAndExpr>[Predicate *result] : <> predPrimary>[predExpr] << ANDnode=new_pred(); ANDnode->expr=PRED_AND_LIST; if (predExpr != NULL) { ANDnode->down=predExpr; tail=&predExpr->right; }; >> ( "&&" predPrimary>[predExpr] << if (predExpr != NULL) { *tail=predExpr; tail=&predExpr->right; }; >> )* << $result=ANDnode; ANDnode=NULL; >> ; /* fail */ <> /* rule predPrimary */ predPrimary>[Predicate *result] : << char *name=NULL; PredEntry *predEntry=NULL; Predicate *predExpr=NULL; >> TokenTerm <> << predEntry=(PredEntry *) hash_get(Pname,name); if (predEntry == NULL) { warnFL(eMsg1("no previously defined #pred with name \"%s\"",name), FileStr[CurFile],zzline); name=NULL; $result=NULL; } else { predExpr=predicate_dup(predEntry->pred); predExpr->predEntry=predEntry; $result=predExpr; }; >> | "\(" predOrExpr>[predExpr] "\)" << $result=predExpr; >> | "!" predPrimary>[predExpr] << predExpr->inverted=!predExpr->inverted; $result=predExpr; >> ; /* fail */ << predicate_free(predExpr); >> /* rule aLexclass */ aLexclass: "{\\}#lexclass" TokenTerm <> ; <> /* rule error */ error : <> "{\\}#errclass" (<<;>> TokenTerm <> | QuotedTerm <> ) <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 <> | TokenTerm <> | QuotedTerm <> ) <elist), t);>> ( ( NonTerminal <> | TokenTerm <> | QuotedTerm <> ) <elist), t);>> )* "\}" ; <> /* rule tclass */ tclass : <> <> <> "{\\}#tokclass" TokenTerm <> <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; } >> /* MR23 */ { /* MR23 */ "\(" /* MR23 */ QuotedTerm /* MR23 */ <> /* MR23 */ "\)" /* MR23 */ } /* MR23 */ /* MR23 */ /* MR23 */ << /* MR23 */ if (p!= NULL && akaString != NULL) { /* MR23 */ if (p->akaString != NULL) { /* MR23 */ if (strcmp(p->akaString,akaString) != 0) { /* MR23 */ warnFL(eMsg2("this #tokclass statment conflicts with a previous #tokclass %s(\"%s\") statement", /* MR23 */ t,p->akaString), /* MR23 */ FileStr[save_file],save_line); /* MR23 */ }; /* MR23 */ } else { /* MR23 */ p->akaString=akaString; /* MR23 */ }; /* MR23 */ }; /* MR23 */ >> "\{" ( ( TokenTerm <> { ".." TokenTerm <> } | QuotedTerm <> ) <tlist), t); } else { list_add(&(e->tlist),".."); list_add(&(e->tlist),t); list_add(&(e->tlist),totext); } totext=NULL; } >> )+ // MR15 Manfred Kogler - forbid empty #tokclass sets (was "+") "\}" ; <> /* rule token */ token : <> <> /* MR11 */ "{\\}#token" /* MR1 10-Apr-97 MR1 Allow shift right operator in DLG actions */ /* MR1 Danger when parser feedback to lexer */ /* MR1 */ <> /* MR1 */ { TokenTerm <> /* MR11 */ { /* MR11 */ "\(" /* MR11 */ QuotedTerm /* MR11 */ <> /* MR11 */ "\)" /* MR11 */ } { "=" "[0-9]+" /* define the token type number */ <> } } { QuotedTerm <> } { Action << a = (char *) calloc(strlen(LATEXT(1))+1, sizeof(char)); require(a!=NULL, "rule token: cannot allocate action"); strcpy(a, LATEXT(1)); >> } { ";" } /* MR11 */ <> <akaString != NULL) { if (strcmp(te->akaString,akaString) != 0) { warnFL(eMsg2("this #token statment conflicts with a previous #token %s(\"%s\") statement", t,te->akaString), FileStr[save_file],save_line); }; } else { te->akaString=akaString; }; }; }; >> ; <> /* rule block */ 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++; /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; CurAltNum = 1; /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; saveblah = attribsRefdFromAction; attribsRefdFromAction = empty; >> alt[toksrefd,rulesrefd] <> << if ( ((Junction *)g.left)->p1->ntype == nAction ) { ActionNode *actionNode=(ActionNode *) ( ( (Junction *)g.left) ->p1); if (!actionNode->is_predicate ) { actionNode->init_action = TRUE; /* MR12c */ if (actionNode->noHoist) { /* MR12c */ errFL("<> appears as init-action - use <<>> <>", /* MR12c */ FileStr[actionNode->file],actionNode->line); /* MR12c */ }; } } ((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); } >> )* <> ( "\|" <> alt[toksrefd,rulesrefd] <> << ((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); } >> )* <> )* <<$0 = b;>> <> ; <> /* rule alt */ alt[set *toksrefd, set *rulesrefd] : <> { "\@" /* handle MismatchedToken signals with default handler */ <> } ( <<;>> /* MR9 Removed unreferenced variable "tok" */ { <> "\~" <> } element[old_not, first_on_line, use_def_MT_handler] > [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); } } } >> )* <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; >> ; <> /* rule element_label */ element_label > [LabelEntry *label] : <> LABEL <> << 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; } } >> ":" ; /* rule element */ element[int old_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; int predMsgDone=0; int semDepth=0; int ampersandStyle; int height; /* MR11 */ int equal_height; /* MR11 */ char* pFirstSetSymbol = NULL; /* MR21 */ $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 = $old_not; if ( label!=NULL ) { p->el_label = label->str; label->elem = (Node *)p; } } >> { ".." ( QuotedTerm <> | TokenTerm <> ) } << if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_not) ) list_add(&MetaTokenNodes, (void *)p); >> ( "^" <astnode=ASTroot;>> | <astnode=ASTchild;>> | "!" <astnode=ASTexclude;>> ) { "\@" <> } << 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 = $old_not; if ( label!=NULL ) { p->el_label = label->str; label->elem = (Node *)p; } } >> { ".." ( QuotedTerm <> | TokenTerm <> ) } ( "^" <astnode=ASTroot;>> | <astnode=ASTchild;>> | "!" <astnode=ASTexclude;>> ) { "\@" <> } << if ( p!=NULL && (p->upper_range!=0 || p->tclass || $old_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; >> | <> "." <<$$ = buildWildCard(LATEXT(1)); p=((TokNode *)((Junction *)$$.left)->p1);>> ( "^" <astnode=ASTroot;>> | <astnode=ASTchild;>> | "!" <astnode=ASTexclude;>> ) <> << 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; >> | <> NonTerminal <<$$ = buildRuleRef(LATEXT(1));>> { "!" <p1; q->astnode=ASTexclude;>> } { {"\<"} PassAction <p1, LATEXT(1));>> } <p1;>> { <> "\>" 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; >> ) | <> Action <<$0 = buildAction(LATEXT(1),action_file,action_line, 0);>> <> /* MR7 */ <<$node = (Node *) ((Junction *)$0.left)->p1;>> | <> Pred <<$0 = buildAction(LATEXT(1),action_file,action_line, 1);>> <p1;>> <> { <> 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; >> } <> /* MR7 */ <<$node = (Node *)act;>> | <> <= MAX_BLK_LEVEL) fatal("Blocks nested too deeply"); /* MR23 */ CurBlockID_array[BlkLevel] = CurBlockID; /* MR23 */ CurAltNum_array[BlkLevel] = CurAltNum; >> { Pragma ( "approx" <> | "LL\(1\)" <> /* MR20 */ | "LL\(2\)" <> /* MR20 */ ) } /* MR21 */ { FirstSetSymbol /* MR21 */ "\(" /* MR21 */ ( NonTerminal /* MR21 */ << /* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1, /* MR21 */ sizeof(char)); /* MR21 */ require(pFirstSetSymbol!=NULL, /* MR21 */ "cannot allocate first set name"); /* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1)); /* MR21 */ >> /* MR21 */ | TokenTerm /* MR21 */ << /* MR21 */ pFirstSetSymbol = (char *) calloc(strlen(LATEXT(1))+1, /* MR21 */ sizeof(char)); /* MR21 */ require(pFirstSetSymbol!=NULL, /* MR21 */ "cannot allocate first set name"); /* MR21 */ strcpy(pFirstSetSymbol, LATEXT(1)); /* MR21 */ >> /* MR21 */ ) /* MR21 */ "\)" /* MR21 */ } ( "\(" block[&toksrefd,&rulesrefd] "\)" <> ( "\*" <<$$ = makeLoop($$,approx,pFirstSetSymbol);>> | "\+" <<$$ = makePlus($$,approx,pFirstSetSymbol);>> | "?" ( ( "=>" <> | "&&" <> /* MR10 (g)? && <

>? */ ) Pred /* generalized predicate */ /* first make into a predicate */ <<$$ = buildAction(LATEXT(1),action_file,action_line,1);>> <p1;>> <> /* MR10 */ <> { <> 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; >> } <> <<$node = (Node *)act;>> /* for now, just snag context */ << pred = computePredFromContextGuard(blk,&predMsgDone); /* MR10 */ if ( pred==NULL) { /* MR10 */ if ( !predMsgDone) err("invalid or missing context guard"); /* MR10 */ predMsgDone=1; /* MR10 */ } else { /* MR10 */ act->guardNodes=(Junction *)blk.left; /* MR11 */ pred->expr = act->action; pred->source = act; /* MR10 */ pred->ampersandStyle = ampersandStyle; /* 0 means (g)? => ... 1 means (g)? && ... */ /* MR13 */ if (pred->tcontext != NULL) { /* MR13 */ height=MR_max_height_of_tree(pred->tcontext); /* MR13 */ equal_height=MR_all_leaves_same_height(pred->tcontext,height); /* MR13 */ if (! equal_height) { /* MR13 */ errFL("in guarded predicates all tokens in the guard must be at the same height", /* MR13 */ FileStr[act->file],act->line); /* MR13 */ }; /* MR13 */ } /* MR10 */ if (ampersandStyle) { /* MR10 */ act->ampersandPred = pred; /* MR11 */ if (! HoistPredicateContext) { /* MR11 */ errFL("without \"-prc on\" (guard)? && <>? ... doesn't make sense", /* MR11 */ FileStr[act->file],act->line); /* MR11 */ }; /* MR10 */ } else { /* MR10 */ act->guardpred = pred; /* MR10 */ }; /* MR10 */ if (pred->k != semDepth) { /* MR10 */ warn(eMsgd2("length of guard (%d) does not match the length of semantic predicate (%d)", /* MR10 */ pred->k,semDepth)); /* MR10 */ }; } >> | <<$$ = makeBlk($$,approx,pFirstSetSymbol); FoundGuessBlk = 1; ((Junction *) ((Junction *)$$.left)->p1)->guess=1; if ( !$first_on_line ) { err("(...)? predicate must be first element of production"); } >> ) | <<$$ = makeBlk($$,approx,pFirstSetSymbol);>> ) << if ( pred==NULL && !predMsgDone) { /* MR10 */ ((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,pFirstSetSymbol); /* MR23 */ CurBlockID_array[BlkLevel] = (-1); /* MR23 */ CurAltNum_array[BlkLevel] = (-1); --BlkLevel; >> "\}" << ((Junction *)((Junction *)$$.left)->p1)->blockid = CurBlockID; ((Junction *)((Junction *)$$.left)->p1)->tokrefs = toksrefd; ((Junction *)((Junction *)$$.left)->p1)->rulerefs = rulesrefd; >> <p1); /* MR7 */ altAdd(CurAltStart); /* MR7 */ }; >> <<$node = (Node *) ((Junction *)$$.left)->p1;>> ) /* Error catching alternatives */ | "\*" <> | "\+" <> | "\>" <' can only appear after a nonterminal"); CannotContinue=TRUE;>> | PassAction < [...]'"); CannotContinue=TRUE;>> ; <> /* rule default_exception_handler */ default_exception_handler : exception_group > [DefaultExGroup] ; /* rule exception_group */ exception_group > [ExceptionGroup *eg] : <> /* MR6 */ "exception" <<$eg = (ExceptionGroup *)calloc(1, sizeof(ExceptionGroup));>> { <> 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] <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_array[BlkLevel], CurAltNum_array[BlkLevel]); /* 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 */ }; >> ; <> /* rule exception_handler */ exception_handler > [ExceptionHandler *eh] : <<;>> /* MR9 Removed unreferenced variable "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)); >> } ; <> #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_]*" <> #lexclass PARSE_ENUM_FILE #token "[\t\ ]+" << zzskip(); >> /* Ignore White */ #token "\n|\r|\r\n" << 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 "@" << ; >> /* rule enum_file */ 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] ) | ; /* rule defines */ defines[char *fname] : <> /* MR3 */ ( "#define" ID <> 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); }; }; >> )+ <> ; /* rule enum_def */ enum_def[char *fname] : <> /* MR3 */ "enum" ID "\{" ID <> ( "=" INT <> | <> ) << /* 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 */ { <>? ID { "=" INT } /* MR2 */ | ID /* MR2 */ <> ( "=" INT <> | <> ) << /* 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); } >> } )* "\}" ";" <> /* MR3 */ ; #token INT "[0-9]+" #token ID "[a-zA-Z_][_a-zA-Z0-9]*" #lexclass START /* MR14 Arpad Beszedes 26-May-98 Add support for #line directives when antlr source is pre-processed */ #lexaction << static char * #ifdef __USE_PROTOS getFileNameFromTheLineInfo(char *toStr, char *fromStr) #else getFileNameFromTheLineInfo(toStr, fromStr) char *toStr, *fromStr; #endif { int i, j, k; if (!fromStr || !toStr) return toStr; /* find the first " */ for (i=0; (i> << /* 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("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",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 ) { p = (TermEntry *) hash_get(Tname, t); if (p == NULL) { err(eMsg1("new token definition '%s' not allowed - only #token with name already defined by #tokdefs file allowed",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' || *s=='\r' ) /* MR13 */ 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"); } >> #lexaction << #ifdef __USE_PROTOS void mark_label_used_in_sem_pred(LabelEntry *le) /* MR10 */ #else void mark_label_used_in_sem_pred(le) /* MR10 */ LabelEntry *le; #endif { TokNode *tn; require (le->elem->ntype == nToken,"mark_label_used... ntype != nToken"); tn=(TokNode *)le->elem; require (tn->label != 0,"mark_label_used... TokNode has no label"); tn->label_used_in_semantic_pred=1; } >>