cat << \EOF_antlr.bag | sed 's/^>//' > antlr.bag >cat << \EOF_antlr.g | sed 's/^>//' > antlr.g >>/* >> * antlr.g -- PCCTS Version 1.xx ANTLR >> * >> * Parse an antlr input grammar and build a syntax-diagram. >> * >> * Terence Parr >> * Purdue University >> * August 1990 >> * >> * Rewritten in itself (needs at least 1.00 to work) May 1992--TJP >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#header <<#include "set.h" >> #include >> #include "syn.h" >> #include "hash.h" >> #include "generic.h" >> #define zzcr_attr(attr,tok,t) >> >> >> >><< >>#ifdef __STDC__ >>static void chkToken(char *, char *, char *); >>#else >>static void chkToken(); >>#endif >>>> >> >>#lexclass STRINGS >>#token QuotedTerm "\"" << zzmode(START); >> >>#token "\\\"" << zzmore(); >> >>#token "\n" << >> zzline++; >> warn("eoln found in string (in user action)"); >> zzskip(); >> >> >>#token "\\~[\"]" << zzmore(); >> >>#token "~[\n\"\\]+" << zzmore(); >> >> >>#lexclass COMMENTS >>#token "\*/" << zzmode(START); zzskip(); >> >>#token "\*" << zzskip(); >> >>#token "\n" << zzline++; zzskip(); >> >>#token "~[\n\*]+" << zzskip(); >> >> >>/* >> * This lexical class accepts actions of type [..] and <<..>> >> * >> * It translates the following special items: >> * >> * $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()" >> * >> * And, for trees: >> * >> * #0 --> "(*_root)" >> * #i --> "zzastArg(i)" >> * #[args] --> "zzmk_ast(zzastnew(), args)" >> * #[] --> "zzastnew()" >> * #( root, child1, ..., childn ) >> --> "zztmake(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 ) { >> warn( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE)); >> } >> >> >>#token Pred "\>\>?" << /* these do not nest */ >> zzmode(START); >> NLATEXT[0] = ' '; >> NLATEXT[1] = ' '; >> zzbegexpr[0] = ' '; >> zzbegexpr[1] = ' '; >> zzbegexpr[2] = ' '; >> if ( zzbufovf ) { >> warn( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE)); >> } >> >> >>#token PassAction "\]" << if ( topint() == ']' ) { >> popint(); >> if ( istackempty() ) /* terminate action */ >> { >> zzmode(START); >> NLATEXT[0] = ' '; >> zzbegexpr[0] = ' '; >> if ( zzbufovf ) { >> warn( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE)); >> } >> } >> else { >> /* terminate $[..] and #[..] */ >> zzreplstr(")"); >> zzmore(); >> } >> } >> else if ( topint() == '|' ) { /* end of simple [...] */ >> popint(); >> zzmore(); >> } >> else zzmore(); >> >> >>#token "\n" << zzline++; zzmore(); >> >>#token "\>" << zzmore(); >> >>#token "$" << zzmore(); >> >>#token "$$" << zzreplstr("zzaRet"); zzmore(); >> >>#token "$\[\]" << zzreplstr("zzempty_attr"); zzmore(); >> >>#token "$\[" << >> pushint(']'); >> zzreplstr("zzconstr_attr("); >> zzmore(); >> >> >>#token "$[0-9]+" <<{ >> static char buf[100]; >> if ( strlen(zzbegexpr)>85 ) >> fatal("$i attrib ref too big"); >> sprintf(buf,"zzaArg(zztasp%d,%s)", >> BlkLevel-1,zzbegexpr+1); >> zzreplstr(buf); >> zzmore(); >> } >> >> >>#token "$[0-9]+." <<{ >> static char buf[100]; >> if ( strlen(zzbegexpr)>85 ) >> fatal("$i.field attrib ref too big"); >> zzbegexpr[strlen(zzbegexpr)-1] = ' '; >> sprintf(buf,"zzaArg(zztasp%d,%s).", >> BlkLevel-1,zzbegexpr+1); >> zzreplstr(buf); >> zzmore(); >> } >> >> >>#token "$[0-9]+.[0-9]+" <<{ >> static char buf[100]; >> static char i[20], j[20]; >> char *p,*q; >> if (strlen(zzbegexpr)>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'; >> sprintf(buf,"zzaArg(zztasp%s,%s)",i,j); >> zzreplstr(buf); >> zzmore(); >> } >> >> >>#token "$[_a-zA-Z][_a-zA-Z0-9]*" >> <<{ static char buf[300]; >> zzbegexpr[0] = ' '; >> if ( CurRule != NULL && >> strcmp(CurRule, &zzbegexpr[1])==0 ) { >> zzreplstr("zzaRet"); >> } >> else if ( CurRetDef != NULL ) { >> if ( strmember(CurRetDef, &zzbegexpr[1]) ) { >> if ( HasComma( CurRetDef ) ) { >> require (strlen(zzbegexpr)<=285, >> "$retval attrib ref too big"); >> sprintf(buf,"_retv.%s",&zzbegexpr[1]); >> zzreplstr(buf); >> } >> else zzreplstr("_retv"); >> } >> else if ( CurParmDef != NULL ) { >> if ( !strmember(CurParmDef, &zzbegexpr[1]) ) >> warn(eMsg1("$%s not parameter or return value",&zzbegexpr[1])); >> } >> else warn(eMsg1("$%s not parameter or return value",&zzbegexpr[1])); >> } >> } >> zzmore(); >> >> >>#token "#0" << zzreplstr("(*_root)"); zzmore(); >> >>#token "#\[\]" << zzreplstr("zzastnew()"); zzmore(); >> >>#token "#\(\)" << zzreplstr("NULL"); zzmore(); >> >>#token "#[0-9]+" <<{ >> static char buf[100]; >> if ( strlen(zzbegexpr)>85 ) >> fatal("#i AST ref too big"); >> sprintf(buf,"zzastArg(%s)",zzbegexpr+1); >> zzreplstr(buf); >> zzmore(); >> } >> >> >>#token "#\[" << >> pushint(']'); >> zzreplstr("zzmk_ast(zzastnew(),"); >> zzmore(); >> >> >>#token "#\(" << >> pushint('}'); >> zzreplstr("zztmake("); >> zzmore(); >> >> >>#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(); >> >>#token "\\>" << zzreplstr(">"); zzmore(); >> >>#token "\\$" << zzreplstr("$"); zzmore(); >> >>#token "\\#" << zzreplstr("#"); zzmore(); >> >>#token "\\\\" << zzmore(); >> /* need this for some reason */ >>#token "\\~[\]\)>$#\\]" << zzmore(); >> /* escaped char, always ignore */ >>#token "~[\n\)\(\\$#\>\]\[]+" << 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 "\>\>" << warn("Missing <<; found dangling \\>\\>"); zzskip(); >> >>#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 ) return; >> fclose( input ); >> input = new_input; >> zzrdstream( input ); >> /*zzadvance(); /* Get 1st char of this file */ >> zzskip(); /* Skip the Eof (@) char i.e continue */ >> } >> >> >> >>/* >> * Get a grammar -- Build a list of rules like: >> * >> * o-->Rule1--o >> * | >> * o-->Rule2--o >> * | >> * ... >> * | >> * o-->RuleN--o >> */ >>grammar : <> >> { "#header" Action >> << >> HdrAction = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(HdrAction!=NULL, "rule grammar: cannot allocate header action"); >> strcpy(HdrAction, LATEXT(1)); >> >> >> } >> ( <> >> Action >> << >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule grammar: cannot allocate action"); >> strcpy(a, LATEXT(1)); >> list_add(&BeforeActions, a); >> >> >> | laction >> | aLexclass >> | token >> | error >> )* >> rule <> >> ( rule <> >> | aLexclass >> | token >> | error >> )* >> ( <> >> Action >> << >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule grammar: cannot allocate action"); >> strcpy(a, LATEXT(1)); >> list_add(&AfterActions, a); >> >> >> | laction >> | error >> )* >> Eof >> ; >> <> >> >>/* >> * 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 : <> char *pdecl=NULL, *ret=NULL, *a;>> >> NonTerminal >> <> if ( hash_get(Rname, LATEXT(1))!=NULL ) { >> warn(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++; >> >> >> { "!" <noAST = TRUE;>> } >> { <<;>> >> {"\<"} >> PassAction >> << pdecl = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(pdecl!=NULL, "rule rule: cannot allocate param decl"); >> strcpy(pdecl, LATEXT(1)); >> CurParmDef = pdecl; >> >> >> } >> { "\>" >> PassAction >> << ret = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(ret!=NULL, "rule rule: cannot allocate ret type"); >> strcpy(ret, LATEXT(1)); >> CurRetDef = ret; >> >> >> } >> { QuotedTerm <egroup=strdup(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] = 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] = tolower(a[0]); >> /* refers to itself */ >> list_add(&(e->elist), strdup(q->str)); >> } >> else { >> warn(eMsg1("default errclass for '%s' would conflict with token/errclass",a)); >> if ( q->egroup == NULL ) a[0] = tolower(a[0]); >> free(e); >> } >> } >> >> >> <> >> ":" block <> ((Junction *)r.left)->jtype = RuleBlk; >> if ( q!=NULL ) ((Junction *)r.left)->rname = q->str; >> ((Junction *)r.left)->file = f; >> ((Junction *)r.left)->line = l; >> ((Junction *)r.left)->pdecl = pdecl; >> ((Junction *)r.left)->ret = ret; >> ((Junction *)r.left)->lock = makelocks(); >> ((Junction *)r.left)->pred_lock = makelocks(); >> 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(); >> ((Junction *)r.left)->end = p; >> if ( q!=NULL ) q->rulenum = NumRules; >> $7 = r; >> >> >> <<--BlkLevel;>> >> ";" >> { Action >> << a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule rule: cannot allocate error action"); >> strcpy(a, LATEXT(1)); >> ((Junction *)r.left)->erraction = a; >> >> >> } >> <> >> <> >> ; >> <> >> >>laction : <> >> "#lexaction" >> Action >> << >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule laction: cannot allocate action"); >> strcpy(a, LATEXT(1)); >> list_add(&LexActions, a); >> >> >> ; >> >>aLexclass: "#lexclass" TokenTerm <> >> ; >> >>error : <> >> "#errclass" >> (<<;>> TokenTerm <> >> | QuotedTerm <> >> ) >> <> 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 ); >> require((p=(TermEntry *)hash_get(Tname, t)) != NULL, >> "hash table mechanism is broken"); >> p->errclassname = 1; /* entry is errclass name, not token */ >> list_add(&eclasses, (char *)e); >> } >> else >> { >> warn(eMsg1("redefinition of errclass or conflict w/token '%s'; ignored",t)); >> free( e ); >> go=0; >> } >> >> >> "\{" >> ( NonTerminal <> >> | TokenTerm <> >> | QuotedTerm <> >> ) >> <elist), t);>> >> ( >> ( NonTerminal <> >> | TokenTerm <> >> | QuotedTerm <> >> ) >> <elist), t);>> >> )* >> "\}" >> ; >> >>token : <> >> "#token" >> { TokenTerm <> } >> { QuotedTerm <> } >> { Action >> << >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule token: cannot allocate action"); >> strcpy(a, LATEXT(1)); >> >> >> } >> <> >> ; >> <> >> >>block : <> >> alt <> >> << >> if ( ((Junction *)g.left)->p1->ntype == nAction ) >> { >> if ( !((ActionNode *)(((Junction *)g.left)->p1))->is_predicate ) >> { >> ((ActionNode *)(((Junction *)g.left)->p1))->init_action = TRUE; >> } >> } >> >> >> ( "\|" >> alt <> >> )* >> <<$0 = b;>> >> ; >> <> >> >>alt : <> >> ( element <> >> )* >> <> $0 = g; >> >> >> ; >> <> >> >>element : <> >> TokenTerm >> <<$0 = buildToken(LATEXT(1));>> >> ( <

p1;>> >> "^" <astnode=ASTroot;>> >> | <astnode=ASTchild;>> >> | "!" <astnode=ASTexclude;>> >> ) >> | QuotedTerm >> <<$0 = buildToken(LATEXT(1));>> >> ( <

p1;>> >> "^" <astnode=ASTroot;>> >> | <astnode=ASTchild;>> >> | "!" <astnode=ASTexclude;>> >> ) >> | NonTerminal >> <<$0 = buildRuleRef(LATEXT(1));>> >> { "!" <p1; >> q->astnode=ASTexclude;>> >> } >> { {"\<"} >> PassAction <p1, LATEXT(1));>> >> } >> { <p1; >> >> >> "\>" >> PassAction >> << >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule element: cannot allocate assignment"); >> strcpy(a, LATEXT(1)); >> rr->assign = a; >> >> >> } >> | Action <<$0 = buildAction(LATEXT(1),action_file,action_line, 0);>> >> | Pred <<$0 = buildAction(LATEXT(1),action_file,action_line, 1);>> >> { <p1;>> >> PassAction >> << >> a = 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; >> >> >> } >> | <> "\(" block <<$0 = $2; --BlkLevel;>> "\)" >> ( "\*" <<$$ = makeLoop($$);>> >> | "\+" <<$$ = makePlus($$);>> >> | <<$$ = makeBlk($$);>> >> ) >> { PassAction <p1, LATEXT(1));>> } >> | <> "\{" block <<$0 = makeOpt($2); --BlkLevel;>> "\}" >> { PassAction <p1, LATEXT(1));>> } >> | ":" <> CannotContinue=TRUE;>> >> | "\*" <> >> | "\+" <> >> | "\>" <' can only appear after a nonterminal"); CannotContinue=TRUE;>> >> | PassAction < [...]'"); >> CannotContinue=TRUE;>> >> ; >> <> >> >>#token NonTerminal "[a-z] [A-Za-z0-9_]*" >>#token TokenTerm "[A-Z] [A-Za-z0-9_]*" >>#token "#[A-Za-z0-9_]*" <> >> >><< >>/* semantics of #token */ >>static void >>chkToken(t,e,a) >>char *t, *e, *a; >>{ >> if ( t==NULL && e==NULL ) { /* none found */ >> warn("#token requires at least token name or rexpr"); >> } >> else if ( t!=NULL && e!=NULL ) { /* both found */ >> Tlink(t, e); >> if ( a!=NULL ) { >> if ( hasAction(e) ) { >> warn(eMsg1("redefinition of action for %s; ignored",e)); >> } >> else setHasAction(e, a); >> } >> } >> else if ( t!=NULL ) { /* only one found */ >> if ( Tnum( t ) == 0 ) addTname( t ); >> else { >> warn(eMsg1("redefinition of token %s; ignored",t)); >> } >> if ( a!=NULL ) { >> warn(eMsg1("action cannot be attached to a token name (%s); ignored",t)); >> } >> } >> else if ( e!=NULL ) { >> if ( Tnum( e ) == 0 ) addTexpr( e ); >> else { >> if ( hasAction(e) ) { >> warn(eMsg1("redefinition of action for %s; ignored",e)); >> } >> else if ( a==NULL ) { >> warn(eMsg1("redefinition of expr %s; ignored",e)); >> } >> } >> if ( a!=NULL ) setHasAction(e, a); >> } >>} >>>> >EOF_antlr.g >cat << \EOF_antlr.c | sed 's/^>//' > antlr.c >>/* >> * A n t l r T r a n s l a t i o n H e a d e r >> * >> * Terence Parr, Hank Dietz and Will Cohen: 1989-1992 >> * Purdue University Electrical Engineering >> * ANTLR Version 1.06 >> */ >>#include >>#include "set.h" >>#include >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#define zzcr_attr(attr,tok,t) >>#include "antlr.h" >>#include "tokens.h" >>#include "dlgdef.h" >>#include "mode.h" >>ANTLR_INFO >>#ifdef __STDC__ >>static void chkToken(char *, char *, char *); >>#else >>static void chkToken(); >>#endif >> >>#ifdef __STDC__ >>void >>grammar() >>#else >>grammar() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> Graph g; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==50) ) { >> zzmatch(50); zzCONSUME; >> zzmatch(Action); >> HdrAction = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(HdrAction!=NULL, "rule grammar: cannot allocate header action"); >> strcpy(HdrAction, LATEXT(1)); >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> char *a; >> while ( 1 ) { >> if ( (LA(1)==Action) ) { >> zzmatch(Action); >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule grammar: cannot allocate action"); >> strcpy(a, LATEXT(1)); >> list_add(&BeforeActions, a); >> zzCONSUME; >> } >> else if ( (LA(1)==57) ) { >> laction(); >> } >> else if ( (LA(1)==58) ) { >> aLexclass(); >> } >> else if ( (LA(1)==63) ) { >> token(); >> } >> else if ( (LA(1)==60) ) { >> error(); >> } >> else break; >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> rule(); >> g=zzaArg(zztasp1,3); SynDiag = (Junction *) zzaArg(zztasp1,3 ).left; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> while ( 1 ) { >> if ( (LA(1)==NonTerminal) ) { >> rule(); >> if ( zzaArg(zztasp2,1 ).left!=NULL ) {g.right = NULL; g = Or(g, zzaArg(zztasp2,1));} >> } >> else if ( (LA(1)==58) ) { >> aLexclass(); >> } >> else if ( (LA(1)==63) ) { >> token(); >> } >> else if ( (LA(1)==60) ) { >> error(); >> } >> else break; >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> char *a; >> while ( 1 ) { >> if ( (LA(1)==Action) ) { >> zzmatch(Action); >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule grammar: cannot allocate action"); >> strcpy(a, LATEXT(1)); >> list_add(&AfterActions, a); >> zzCONSUME; >> } >> else if ( (LA(1)==57) ) { >> laction(); >> } >> else if ( (LA(1)==60) ) { >> error(); >> } >> else break; >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> zzmatch(Eof); zzCONSUME; >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> CannotContinue=TRUE; >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x1); >> } >>} >> >>#ifdef __STDC__ >>void >>rule() >>#else >>rule() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> RuleEntry *q; Junction *p; Graph r; int f, l; ECnode *e; >> char *pdecl=NULL, *ret=NULL, *a; >> zzmatch(NonTerminal); >> q=NULL; >> if ( hash_get(Rname, LATEXT(1))!=NULL ) { >> warn(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++; >> zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==52) ) { >> zzmatch(52); >> if ( q!=NULL ) q->noAST = TRUE; >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> ; >> if ( (setwd1[LA(1)]&0x2) ) { >> { >> zzBLOCK(zztasp3); >> zzMake0; >> { >> if ( (LA(1)==53) ) { >> zzmatch(53); zzCONSUME; >> } >> zzEXIT(zztasp3); >> } >> } >> zzmatch(PassAction); >> pdecl = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(pdecl!=NULL, "rule rule: cannot allocate param decl"); >> strcpy(pdecl, LATEXT(1)); >> CurParmDef = pdecl; >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==54) ) { >> zzmatch(54); zzCONSUME; >> zzmatch(PassAction); >> ret = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(ret!=NULL, "rule rule: cannot allocate ret type"); >> strcpy(ret, LATEXT(1)); >> CurRetDef = ret; >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==QuotedTerm) ) { >> zzmatch(QuotedTerm); >> if ( q!=NULL ) q->egroup=strdup(LATEXT(1)); >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> if ( GenEClasseForRules && q!=NULL ) { >> e = newECnode; >> require(e!=NULL, "cannot allocate error class node"); >> if ( q->egroup == NULL ) {a = q->str; a[0] = 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] = tolower(a[0]); >> /* refers to itself */ >> list_add(&(e->elist), strdup(q->str)); >> } >> else { >> warn(eMsg1("default errclass for '%s' would conflict with token/errclass",a)); >> if ( q->egroup == NULL ) a[0] = tolower(a[0]); >> free(e); >> } >> } >> BlkLevel++; >> zzmatch(55); zzCONSUME; >> block(); >> r = makeBlk(zzaArg(zztasp1,7)); >> ((Junction *)r.left)->jtype = RuleBlk; >> if ( q!=NULL ) ((Junction *)r.left)->rname = q->str; >> ((Junction *)r.left)->file = f; >> ((Junction *)r.left)->line = l; >> ((Junction *)r.left)->pdecl = pdecl; >> ((Junction *)r.left)->ret = ret; >> ((Junction *)r.left)->lock = makelocks(); >> ((Junction *)r.left)->pred_lock = makelocks(); >> 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(); >> ((Junction *)r.left)->end = p; >> if ( q!=NULL ) q->rulenum = NumRules; >> zzaArg(zztasp1,7) = r; >> --BlkLevel; >> zzmatch(56); zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==Action) ) { >> zzmatch(Action); >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule rule: cannot allocate error action"); >> strcpy(a, LATEXT(1)); >> ((Junction *)r.left)->erraction = a; >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> if ( q==NULL ) zzaArg(zztasp1,0 ).left = NULL; else zzaArg(zztasp1,0) = zzaArg(zztasp1,7); >> CurRuleNode = NULL; >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> CannotContinue=TRUE; >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x4); >> } >>} >> >>#ifdef __STDC__ >>void >>laction() >>#else >>laction() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> char *a; >> zzmatch(57); zzCONSUME; >> zzmatch(Action); >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule laction: cannot allocate action"); >> strcpy(a, LATEXT(1)); >> list_add(&LexActions, a); >> zzCONSUME; >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x8); >> } >>} >> >>#ifdef __STDC__ >>void >>aLexclass() >>#else >>aLexclass() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> zzmatch(58); zzCONSUME; >> zzmatch(TokenTerm); >> lexclass(strdup(LATEXT(1))); >> zzCONSUME; >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x10); >> } >>} >> >>#ifdef __STDC__ >>void >>error() >>#else >>error() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> char *t=NULL; ECnode *e; int go=1; TermEntry *p; >> zzmatch(60); zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> ; >> if ( (LA(1)==TokenTerm) ) { >> zzmatch(TokenTerm); >> t=strdup(LATEXT(1)); >> zzCONSUME; >> } >> else if ( (LA(1)==QuotedTerm) ) { >> zzmatch(QuotedTerm); >> t=strdup(LATEXT(1)); >> zzCONSUME; >> } >> else {zzFAIL(1,zzerr1,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp2); >> } >> } >> 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 ); >> require((p=(TermEntry *)hash_get(Tname, t)) != NULL, >> "hash table mechanism is broken"); >> p->errclassname = 1; /* entry is errclass name, not token */ >> list_add(&eclasses, (char *)e); >> } >> else >> { >> warn(eMsg1("redefinition of errclass or conflict w/token '%s'; ignored",t)); >> free( e ); >> go=0; >>} >> zzmatch(61); zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==NonTerminal) ) { >> zzmatch(NonTerminal); >> if ( go ) t=strdup(LATEXT(1)); >> zzCONSUME; >> } >> else if ( (LA(1)==TokenTerm) ) { >> zzmatch(TokenTerm); >> if ( go ) t=strdup(LATEXT(1)); >> zzCONSUME; >> } >> else if ( (LA(1)==QuotedTerm) ) { >> zzmatch(QuotedTerm); >> if ( go ) t=strdup(LATEXT(1)); >> zzCONSUME; >> } >> else {zzFAIL(1,zzerr2,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp2); >> } >> } >> if ( go ) list_add(&(e->elist), t); >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> while ( (setwd1[LA(1)]&0x20) ) { >> { >> zzBLOCK(zztasp3); >> zzMake0; >> { >> if ( (LA(1)==NonTerminal) ) { >> zzmatch(NonTerminal); >> if ( go ) t=strdup(LATEXT(1)); >> zzCONSUME; >> } >> else if ( (LA(1)==TokenTerm) ) { >> zzmatch(TokenTerm); >> if ( go ) t=strdup(LATEXT(1)); >> zzCONSUME; >> } >> else if ( (LA(1)==QuotedTerm) ) { >> zzmatch(QuotedTerm); >> if ( go ) t=strdup(LATEXT(1)); >> zzCONSUME; >> } >> else {zzFAIL(1,zzerr3,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp3); >> } >> } >> if ( go ) list_add(&(e->elist), t); >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> zzmatch(62); zzCONSUME; >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x40); >> } >>} >> >>#ifdef __STDC__ >>void >>token() >>#else >>token() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> char *t=NULL, *e=NULL, *a=NULL; >> zzmatch(63); zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==TokenTerm) ) { >> zzmatch(TokenTerm); >> t=strdup(LATEXT(1)); >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==QuotedTerm) ) { >> zzmatch(QuotedTerm); >> e=strdup(LATEXT(1)); >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==Action) ) { >> zzmatch(Action); >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule token: cannot allocate action"); >> strcpy(a, LATEXT(1)); >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> chkToken(t, e, a); >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> CannotContinue=TRUE; >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x80); >> } >>} >> >>#ifdef __STDC__ >>void >>block() >>#else >>block() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> Graph g, b; >> alt(); >> b = g = zzaArg(zztasp1,1); >> if ( ((Junction *)g.left)->p1->ntype == nAction ) >> { >> if ( !((ActionNode *)(((Junction *)g.left)->p1))->is_predicate ) >> { >> ((ActionNode *)(((Junction *)g.left)->p1))->init_action = TRUE; >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> while ( (LA(1)==64) ) { >> zzmatch(64); zzCONSUME; >> alt(); >> g = Or(g, zzaArg(zztasp2,2)); >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> zzaArg(zztasp1,0) = b; >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> CannotContinue=TRUE; >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x100); >> } >>} >> >>#ifdef __STDC__ >>void >>alt() >>#else >>alt() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> int n=0; Graph g; g.left=g.right=NULL; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> while ( (setwd1[LA(1)]&0x200) ) { >> element(); >> n++; g = Cat(g, zzaArg(zztasp2,1)); >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> if ( n == 0 ) g = emptyAlt(); >> zzaArg(zztasp1,0) = g; >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> CannotContinue=TRUE; >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x400); >> } >>} >> >>#ifdef __STDC__ >>void >>element() >>#else >>element() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> TokNode *p; RuleRefNode *q; >> if ( (LA(1)==TokenTerm) ) { >> zzmatch(TokenTerm); >> zzaArg(zztasp1,0) = buildToken(LATEXT(1)); >> zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> p = (TokNode *) ((Junction *)zzaRet.left)->p1; >> if ( (LA(1)==65) ) { >> zzmatch(65); >> p->astnode=ASTroot; >> zzCONSUME; >> } >> else if ( (setwd1[LA(1)]&0x800) ) { >> p->astnode=ASTchild; >> } >> else if ( (LA(1)==52) ) { >> zzmatch(52); >> p->astnode=ASTexclude; >> zzCONSUME; >> } >> else {zzFAIL(1,zzerr4,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp2); >> } >> } >> } >> else if ( (LA(1)==QuotedTerm) ) { >> zzmatch(QuotedTerm); >> zzaArg(zztasp1,0) = buildToken(LATEXT(1)); >> zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> p = (TokNode *) ((Junction *)zzaRet.left)->p1; >> if ( (LA(1)==65) ) { >> zzmatch(65); >> p->astnode=ASTroot; >> zzCONSUME; >> } >> else if ( (setwd1[LA(1)]&0x1000) ) { >> p->astnode=ASTchild; >> } >> else if ( (LA(1)==52) ) { >> zzmatch(52); >> p->astnode=ASTexclude; >> zzCONSUME; >> } >> else {zzFAIL(1,zzerr5,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp2); >> } >> } >> } >> else if ( (LA(1)==NonTerminal) ) { >> zzmatch(NonTerminal); >> zzaArg(zztasp1,0) = buildRuleRef(LATEXT(1)); >> zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==52) ) { >> zzmatch(52); >> q = (RuleRefNode *) ((Junction *)zzaRet.left)->p1; >> q->astnode=ASTexclude; >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (setwd1[LA(1)]&0x2000) ) { >> { >> zzBLOCK(zztasp3); >> zzMake0; >> { >> if ( (LA(1)==53) ) { >> zzmatch(53); zzCONSUME; >> } >> zzEXIT(zztasp3); >> } >> } >> zzmatch(PassAction); >> addParm(((Junction *)zzaRet.left)->p1, LATEXT(1)); >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> char *a; RuleRefNode *rr=(RuleRefNode *) ((Junction *)zzaRet.left)->p1; >> if ( (LA(1)==54) ) { >> zzmatch(54); zzCONSUME; >> zzmatch(PassAction); >> a = calloc(strlen(LATEXT(1))+1, sizeof(char)); >> require(a!=NULL, "rule element: cannot allocate assignment"); >> strcpy(a, LATEXT(1)); >> rr->assign = a; >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> } >> else if ( (LA(1)==Action) ) { >> zzmatch(Action); >> zzaArg(zztasp1,0) = buildAction(LATEXT(1),action_file,action_line, 0); >> zzCONSUME; >> } >> else if ( (LA(1)==Pred) ) { >> zzmatch(Pred); >> zzaArg(zztasp1,0) = buildAction(LATEXT(1),action_file,action_line, 1); >> zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> char *a; ActionNode *act = (ActionNode *) ((Junction *)zzaRet.left)->p1; >> if ( (LA(1)==PassAction) ) { >> zzmatch(PassAction); >> a = 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; >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> } >> else if ( (LA(1)==66) ) { >> BlkLevel++; >> zzmatch(66); zzCONSUME; >> block(); >> zzaArg(zztasp1,0) = zzaArg(zztasp1,2); --BlkLevel; >> zzmatch(67); zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==68) ) { >> zzmatch(68); >> zzaRet = makeLoop(zzaRet); >> zzCONSUME; >> } >> else if ( (LA(1)==69) ) { >> zzmatch(69); >> zzaRet = makePlus(zzaRet); >> zzCONSUME; >> } >> else if ( (setwd1[LA(1)]&0x4000) ) { >> zzaRet = makeBlk(zzaRet); >> } >> else {zzFAIL(1,zzerr6,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp2); >> } >> } >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==PassAction) ) { >> zzmatch(PassAction); >> addParm(((Junction *)zzaRet.left)->p1, LATEXT(1)); >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> } >> else if ( (LA(1)==61) ) { >> BlkLevel++; >> zzmatch(61); zzCONSUME; >> block(); >> zzaArg(zztasp1,0) = makeOpt(zzaArg(zztasp1,2)); --BlkLevel; >> zzmatch(62); zzCONSUME; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==PassAction) ) { >> zzmatch(PassAction); >> addParm(((Junction *)zzaRet.left)->p1, LATEXT(1)); >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> } >> else if ( (LA(1)==55) ) { >> zzmatch(55); >> warn(eMsg1("missing ';' on rule %s", CurRule)); >> CannotContinue=TRUE; >> zzCONSUME; >> } >> else if ( (LA(1)==68) ) { >> zzmatch(68); >> warn("don't you want a ')' with that '*'?"); CannotContinue=TRUE; >> zzCONSUME; >> } >> else if ( (LA(1)==69) ) { >> zzmatch(69); >> warn("don't you want a ')' with that '+'?"); CannotContinue=TRUE; >> zzCONSUME; >> } >> else if ( (LA(1)==54) ) { >> zzmatch(54); >> warn("'>' can only appear after a nonterminal"); CannotContinue=TRUE; >> zzCONSUME; >> } >> else if ( (LA(1)==PassAction) ) { >> zzmatch(PassAction); >> warn("[...] out of context 'rule > [...]'"); >> CannotContinue=TRUE; >> zzCONSUME; >> } >> else {zzFAIL(1,zzerr7,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> CannotContinue=TRUE; >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x8000); >> } >>} >>/* semantics of #token */ >>static void >>chkToken(t,e,a) >>char *t, *e, *a; >>{ >> if ( t==NULL && e==NULL ) { /* none found */ >> warn("#token requires at least token name or rexpr"); >> } >> else if ( t!=NULL && e!=NULL ) { /* both found */ >> Tlink(t, e); >> if ( a!=NULL ) { >> if ( hasAction(e) ) { >> warn(eMsg1("redefinition of action for %s; ignored",e)); >> } >> else setHasAction(e, a); >> } >> } >> else if ( t!=NULL ) { /* only one found */ >> if ( Tnum( t ) == 0 ) addTname( t ); >> else { >> warn(eMsg1("redefinition of token %s; ignored",t)); >> } >> if ( a!=NULL ) { >> warn(eMsg1("action cannot be attached to a token name (%s); ignored",t)); >> } >> } >> else if ( e!=NULL ) { >> if ( Tnum( e ) == 0 ) addTexpr( e ); >> else { >> if ( hasAction(e) ) { >> warn(eMsg1("redefinition of action for %s; ignored",e)); >> } >> else if ( a==NULL ) { >> warn(eMsg1("redefinition of expr %s; ignored",e)); >> } >> } >> if ( a!=NULL ) setHasAction(e, a); >> } >>} >EOF_antlr.c >cat << \EOF_scan.c | sed 's/^>//' > scan.c >> >>/* parser.dlg -- DLG Description of scanner >> * >> * Generated from: antlr.g >> * >> * Terence Parr, Hank Dietz and Will Cohen: 1989-1992 >> * Purdue University Electrical Engineering >> * ANTLR Version 1.06 >> */ >>#include >>#include "set.h" >>#include >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#define zzcr_attr(attr,tok,t) >>#include "antlr.h" >>#include "tokens.h" >>#include "dlgdef.h" >>LOOKAHEAD >>void zzerraction() >>{ >> (*zzerr)("invalid token"); >> zzadvance(); >> zzskip(); >>} >>/* >> * D L G tables >> * >> * Generated from: parser.dlg >> * >> * 1989-1992 by Will Cohen, Terence Parr, and Hank Dietz >> * Purdue University Electrical Engineering >> * DLG Version 1.06 >> */ >> >>#include "mode.h" >> >> >>static void >>act1() >>{ >> NLA = 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 ) return; >> fclose( input ); >> input = new_input; >> zzrdstream( input ); >> /*zzadvance(); /* Get 1st char of this file */ >> zzskip(); /* Skip the Eof (@) char i.e continue */ >> } >> } >> >>static void >>act2() >>{ >> NLA = 42; >> zzskip(); >> } >> >>static void >>act3() >>{ >> NLA = 43; >> zzline++; zzskip(); >> } >> >>static void >>act4() >>{ >> NLA = 44; >> zzmode(ACTIONS); zzmore(); >> istackreset(); >> pushint(']'); >> } >> >>static void >>act5() >>{ >> NLA = 45; >> action_file=CurFile; action_line=zzline; >> zzmode(ACTIONS); zzmore(); >> istackreset(); >> pushint('>'); >> } >> >>static void >>act6() >>{ >> NLA = 46; >> zzmode(STRINGS); zzmore(); >> } >> >>static void >>act7() >>{ >> NLA = 47; >> zzmode(COMMENTS); zzskip(); >> } >> >>static void >>act8() >>{ >> NLA = 48; >> warn("Missing /*; found dangling */"); zzskip(); >> } >> >>static void >>act9() >>{ >> NLA = 49; >> warn("Missing <<; found dangling \>\>"); zzskip(); >> } >> >>static void >>act10() >>{ >> NLA = 50; >> } >> >>static void >>act11() >>{ >> NLA = 52; >> } >> >>static void >>act12() >>{ >> NLA = 53; >> } >> >>static void >>act13() >>{ >> NLA = 54; >> } >> >>static void >>act14() >>{ >> NLA = 55; >> } >> >>static void >>act15() >>{ >> NLA = 56; >> } >> >>static void >>act16() >>{ >> NLA = 57; >> } >> >>static void >>act17() >>{ >> NLA = 58; >> } >> >>static void >>act18() >>{ >> NLA = 60; >> } >> >>static void >>act19() >>{ >> NLA = 61; >> } >> >>static void >>act20() >>{ >> NLA = 62; >> } >> >>static void >>act21() >>{ >> NLA = 63; >> } >> >>static void >>act22() >>{ >> NLA = 64; >> } >> >>static void >>act23() >>{ >> NLA = 65; >> } >> >>static void >>act24() >>{ >> NLA = 66; >> } >> >>static void >>act25() >>{ >> NLA = 67; >> } >> >>static void >>act26() >>{ >> NLA = 68; >> } >> >>static void >>act27() >>{ >> NLA = 69; >> } >> >>static void >>act28() >>{ >> NLA = NonTerminal; >> } >> >>static void >>act29() >>{ >> NLA = TokenTerm; >> } >> >>static void >>act30() >>{ >> NLA = 70; >> warn(eMsg1("unknown meta-op: %s",LATEXT(1))); zzskip(); >> } >> >>unsigned char shift0[257] = { >> 0, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 1, 2, 37, 37, 2, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 1, 15, 5, 9, 37, 37, 37, >> 37, 31, 32, 7, 33, 37, 37, 37, 6, 36, >> 36, 36, 36, 36, 36, 36, 36, 36, 36, 16, >> 17, 4, 37, 8, 37, 37, 35, 35, 35, 35, >> 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, >> 35, 35, 35, 35, 35, 35, 35, 35, 35, 35, >> 35, 35, 3, 37, 37, 30, 36, 37, 12, 34, >> 20, 13, 11, 34, 34, 10, 22, 34, 28, 18, >> 34, 24, 23, 34, 34, 14, 25, 21, 34, 34, >> 34, 19, 34, 34, 26, 29, 27, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37, 37, 37, 37, >> 37, 37, 37, 37, 37, 37, 37 >>}; >> >>static void >>act31() >>{ >> NLA = Eof; >> } >> >>static void >>act32() >>{ >> NLA = QuotedTerm; >> zzmode(START); >> } >> >>static void >>act33() >>{ >> NLA = 3; >> zzmore(); >> } >> >>static void >>act34() >>{ >> NLA = 4; >> zzline++; >> warn("eoln found in string (in user action)"); >> zzskip(); >> } >> >>static void >>act35() >>{ >> NLA = 5; >> zzmore(); >> } >> >>static void >>act36() >>{ >> NLA = 6; >> zzmore(); >> } >> >>unsigned char shift1[257] = { >> 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 1, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 5 >>}; >> >>static void >>act37() >>{ >> NLA = Eof; >> } >> >>static void >>act38() >>{ >> NLA = 7; >> zzmode(START); zzskip(); >> } >> >>static void >>act39() >>{ >> NLA = 8; >> zzskip(); >> } >> >>static void >>act40() >>{ >> NLA = 9; >> zzline++; zzskip(); >> } >> >>static void >>act41() >>{ >> NLA = 10; >> zzskip(); >> } >> >>unsigned char shift2[257] = { >> 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 1, 4, 4, 4, 4, 2, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 5 >>}; >> >>static void >>act42() >>{ >> NLA = Eof; >> } >> >>static void >>act43() >>{ >> NLA = Action; >> /* these do not nest */ >> zzmode(START); >> NLATEXT[0] = ' '; >> NLATEXT[1] = ' '; >> zzbegexpr[0] = ' '; >> zzbegexpr[1] = ' '; >> if ( zzbufovf ) { >> warn( eMsgd("action buffer overflow; size %d",ZZLEXBUFSIZE)); >> } >> } >> >>static void >>act44() >>{ >> NLA = Pred; >> /* these do not nest */ >> zzmode(START); >> NLATEXT[0] = ' '; >> NLATEXT[1] = ' '; >> zzbegexpr[0] = ' '; >> zzbegexpr[1] = ' '; >> zzbegexpr[2] = ' '; >> if ( zzbufovf ) { >> warn( eMsgd("predicate buffer overflow; size %d",ZZLEXBUFSIZE)); >> } >> } >> >>static void >>act45() >>{ >> NLA = PassAction; >> if ( topint() == ']' ) { >> popint(); >> if ( istackempty() ) /* terminate action */ >> { >> zzmode(START); >> NLATEXT[0] = ' '; >> zzbegexpr[0] = ' '; >> if ( zzbufovf ) { >> warn( eMsgd("parameter buffer overflow; size %d",ZZLEXBUFSIZE)); >> } >> } >> else { >> /* terminate zzconstr_attr(..) and zzmk_ast(zzastnew(),..) */ >> zzreplstr(")"); >> zzmore(); >> } >> } >> else if ( topint() == '|' ) { /* end of simple [...] */ >> popint(); >> zzmore(); >> } >> else zzmore(); >> } >> >>static void >>act46() >>{ >> NLA = 14; >> zzline++; zzmore(); >> } >> >>static void >>act47() >>{ >> NLA = 15; >> zzmore(); >> } >> >>static void >>act48() >>{ >> NLA = 16; >> zzmore(); >> } >> >>static void >>act49() >>{ >> NLA = 17; >> zzreplstr("zzaRet"); zzmore(); >> } >> >>static void >>act50() >>{ >> NLA = 18; >> zzreplstr("zzempty_attr"); zzmore(); >> } >> >>static void >>act51() >>{ >> NLA = 19; >> pushint(']'); >> zzreplstr("zzconstr_attr("); >> zzmore(); >> } >> >>static void >>act52() >>{ >> NLA = 20; >> { >> static char buf[100]; >> if ( strlen(zzbegexpr)>85 ) >> fatal(" i attrib ref too big"); >> sprintf(buf,"zzaArg(zztasp%d,%s)", >> BlkLevel-1,zzbegexpr+1); >> zzreplstr(buf); >> zzmore(); >> } >> } >> >>static void >>act53() >>{ >> NLA = 21; >> { >> static char buf[100]; >> if ( strlen(zzbegexpr)>85 ) >> fatal(" i.field attrib ref too big"); >> zzbegexpr[strlen(zzbegexpr)-1] = ' '; >> sprintf(buf,"zzaArg(zztasp%d,%s).", >> BlkLevel-1,zzbegexpr+1); >> zzreplstr(buf); >> zzmore(); >> } >> } >> >>static void >>act54() >>{ >> NLA = 22; >> { >> static char buf[100]; >> static char i[20], j[20]; >> char *p,*q; >> if (strlen(zzbegexpr)>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'; >> sprintf(buf,"zzaArg(zztasp%s,%s)",i,j); >> zzreplstr(buf); >> zzmore(); >> } >> } >> >>static void >>act55() >>{ >> NLA = 23; >> { static char buf[300]; >> zzbegexpr[0] = ' '; >> if ( CurRule != NULL && >> strcmp(CurRule, &zzbegexpr[1])==0 ) { >> zzreplstr("zzaRet"); >> } >> else if ( CurRetDef != NULL ) { >> if ( strmember(CurRetDef, &zzbegexpr[1]) ) { >> if ( HasComma( CurRetDef ) ) { >> require (strlen(zzbegexpr)<=285, >> " retval attrib ref too big"); >> sprintf(buf,"_retv.%s",&zzbegexpr[1]); >> zzreplstr(buf); >> } >> else zzreplstr("_retv"); >> } >> else if ( CurParmDef != NULL ) { >> if ( !strmember(CurParmDef, &zzbegexpr[1]) ) >> warn(eMsg1("$%s not parameter or return value",&zzbegexpr[1])); >> } >> else warn(eMsg1("$%s not parameter or return value",&zzbegexpr[1])); >> } >> } >> zzmore(); >> } >> >>static void >>act56() >>{ >> NLA = 24; >> zzreplstr("(*_root)"); zzmore(); >> } >> >>static void >>act57() >>{ >> NLA = 25; >> zzreplstr("zzastnew()"); zzmore(); >> } >> >>static void >>act58() >>{ >> NLA = 26; >> zzreplstr("NULL"); zzmore(); >> } >> >>static void >>act59() >>{ >> NLA = 27; >> { >> static char buf[100]; >> if ( strlen(zzbegexpr)>85 ) >> fatal("#i AST ref too big"); >> sprintf(buf,"zzastArg(%s)",zzbegexpr+1); >> zzreplstr(buf); >> zzmore(); >> } >> } >> >>static void >>act60() >>{ >> NLA = 28; >> pushint(']'); >> zzreplstr("zzmk_ast(zzastnew(),"); >> zzmore(); >> } >> >>static void >>act61() >>{ >> NLA = 29; >> pushint('}'); >> zzreplstr("zztmake("); >> zzmore(); >> } >> >>static void >>act62() >>{ >> NLA = 30; >> zzmore(); >> } >> >>static void >>act63() >>{ >> NLA = 31; >> if ( istackempty() ) >> zzmore(); >> else if ( topint()==')' ) { >> popint(); >> } >> else if ( topint()=='}' ) { >> popint(); >> /* terminate zztmake(.., NULL) */ >> zzreplstr(", NULL)"); >> } >> zzmore(); >> } >> >>static void >>act64() >>{ >> NLA = 32; >> pushint('|'); /* look for '|' to terminate simple [...] */ >> zzmore(); >> } >> >>static void >>act65() >>{ >> NLA = 33; >> pushint(')'); >> zzmore(); >> } >> >>static void >>act66() >>{ >> NLA = 34; >> zzreplstr("]"); zzmore(); >> } >> >>static void >>act67() >>{ >> NLA = 35; >> zzreplstr(")"); zzmore(); >> } >> >>static void >>act68() >>{ >> NLA = 36; >> zzreplstr(">"); zzmore(); >> } >> >>static void >>act69() >>{ >> NLA = 37; >> zzreplstr("$"); zzmore(); >> } >> >>static void >>act70() >>{ >> NLA = 38; >> zzreplstr("#"); zzmore(); >> } >> >>static void >>act71() >>{ >> NLA = 39; >> zzmore(); >> } >> >>static void >>act72() >>{ >> NLA = 40; >> zzmore(); >> } >> >>static void >>act73() >>{ >> NLA = 41; >> zzmore(); >> } >> >>unsigned char shift3[257] = { >> 0, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 4, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 11, 5, 15, 15, >> 15, 12, 13, 15, 15, 15, 15, 9, 15, 7, >> 8, 8, 8, 8, 8, 8, 8, 8, 8, 15, >> 15, 15, 15, 1, 2, 15, 10, 10, 10, 10, >> 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, >> 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, >> 10, 10, 6, 14, 3, 15, 10, 15, 10, 10, >> 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, >> 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, >> 10, 10, 10, 10, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 15, 15, 15, 15, >> 15, 15, 15, 15, 15, 15, 16 >>}; >> >>#define DfaStates 112 >>typedef unsigned char DfaState; >> >>static DfaState st0[38] = { >> 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, >> 11, 11, 11, 11, 11, 12, 13, 14, 11, 11, >> 11, 11, 11, 11, 11, 11, 15, 16, 11, 17, >> 18, 19, 20, 21, 11, 22, 112, 112 >>}; >> >>static DfaState st1[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st2[38] = { >> 112, 2, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st3[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st4[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st5[38] = { >> 112, 112, 112, 112, 23, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st6[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st7[38] = { >> 112, 112, 112, 112, 112, 112, 112, 24, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st8[38] = { >> 112, 112, 112, 112, 112, 112, 25, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st9[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 26, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st10[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 27, 28, 29, 29, 29, 112, 112, 112, 30, 29, >> 29, 31, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st11[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 32, 32, 32, 32, 32, 112, 112, 112, 32, 32, >> 32, 32, 32, 32, 32, 32, 112, 112, 32, 112, >> 112, 112, 112, 112, 32, 32, 32, 112 >>}; >> >>static DfaState st12[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st13[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st14[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st15[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st16[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st17[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st18[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st19[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st20[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st21[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st22[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 33, 33, 33, 33, 33, 112, 112, 112, 33, 33, >> 33, 33, 33, 33, 33, 33, 112, 112, 33, 112, >> 112, 112, 112, 112, 33, 33, 33, 112 >>}; >> >>static DfaState st23[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st24[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st25[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st26[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st27[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 34, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st28[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 35, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st29[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st30[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 36, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st31[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 37, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st32[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 32, 32, 32, 32, 32, 112, 112, 112, 32, 32, >> 32, 32, 32, 32, 32, 32, 112, 112, 32, 112, >> 112, 112, 112, 112, 32, 32, 32, 112 >>}; >> >>static DfaState st33[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 33, 33, 33, 33, 33, 112, 112, 112, 33, 33, >> 33, 33, 33, 33, 33, 33, 112, 112, 33, 112, >> 112, 112, 112, 112, 33, 33, 33, 112 >>}; >> >>static DfaState st34[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 38, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st35[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 39, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st36[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 40, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st37[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 41, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st38[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 42, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st39[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 43, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st40[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 44, 29, 29, 112, 112, 112, 29, 29, >> 45, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st41[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 46, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st42[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 47, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st43[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 48, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st44[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 49, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st45[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 50, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st46[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 51, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st47[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 52, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st48[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 53, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st49[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 54, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st50[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 55, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st51[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st52[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st53[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 56, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st54[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 57, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st55[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 58, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st56[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 59, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st57[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 60, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st58[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 61, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st59[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st60[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 62, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st61[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st62[38] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 29, 29, 29, 29, 29, 112, 112, 112, 29, 29, >> 29, 29, 29, 29, 29, 29, 112, 112, 29, 112, >> 112, 112, 112, 112, 29, 29, 29, 112 >>}; >> >>static DfaState st63[6] = { >> 64, 65, 66, 67, 68, 112 >>}; >> >>static DfaState st64[6] = { >> 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st65[6] = { >> 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st66[6] = { >> 112, 69, 70, 70, 70, 112 >>}; >> >>static DfaState st67[6] = { >> 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st68[6] = { >> 112, 112, 112, 112, 68, 112 >>}; >> >>static DfaState st69[6] = { >> 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st70[6] = { >> 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st71[6] = { >> 72, 73, 74, 75, 74, 112 >>}; >> >>static DfaState st72[6] = { >> 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st73[6] = { >> 112, 112, 76, 112, 112, 112 >>}; >> >>static DfaState st74[6] = { >> 112, 112, 74, 112, 74, 112 >>}; >> >>static DfaState st75[6] = { >> 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st76[6] = { >> 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st77[17] = { >> 78, 79, 80, 81, 82, 83, 84, 80, 80, 80, >> 80, 85, 86, 87, 88, 80, 112 >>}; >> >>static DfaState st78[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st79[17] = { >> 112, 89, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st80[17] = { >> 112, 112, 80, 112, 112, 112, 112, 80, 80, 80, >> 80, 112, 112, 112, 112, 80, 112 >>}; >> >>static DfaState st81[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st82[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st83[17] = { >> 112, 112, 112, 112, 112, 90, 91, 92, 92, 112, >> 93, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st84[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st85[17] = { >> 112, 112, 112, 112, 112, 112, 94, 95, 96, 112, >> 112, 112, 97, 112, 112, 112, 112 >>}; >> >>static DfaState st86[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st87[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st88[17] = { >> 112, 98, 99, 100, 99, 101, 99, 99, 99, 99, >> 99, 102, 99, 103, 104, 99, 112 >>}; >> >>static DfaState st89[17] = { >> 112, 112, 105, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st90[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st91[17] = { >> 112, 112, 112, 106, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st92[17] = { >> 112, 112, 112, 112, 112, 112, 112, 92, 92, 107, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st93[17] = { >> 112, 112, 112, 112, 112, 112, 112, 108, 108, 112, >> 108, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st94[17] = { >> 112, 112, 112, 109, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st95[17] = { >> 112, 112, 112, 112, 112, 112, 112, 96, 96, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st96[17] = { >> 112, 112, 112, 112, 112, 112, 112, 96, 96, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st97[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 110, 112, 112, 112 >>}; >> >>static DfaState st98[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st99[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st100[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st101[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st102[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st103[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st104[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st105[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st106[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st107[17] = { >> 112, 112, 112, 112, 112, 112, 112, 111, 111, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st108[17] = { >> 112, 112, 112, 112, 112, 112, 112, 108, 108, 112, >> 108, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st109[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st110[17] = { >> 112, 112, 112, 112, 112, 112, 112, 112, 112, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >>static DfaState st111[17] = { >> 112, 112, 112, 112, 112, 112, 112, 111, 111, 112, >> 112, 112, 112, 112, 112, 112, 112 >>}; >> >> >>DfaState *dfa[112] = { >> st0, >> st1, >> st2, >> st3, >> st4, >> st5, >> st6, >> st7, >> st8, >> st9, >> st10, >> st11, >> st12, >> st13, >> st14, >> st15, >> st16, >> st17, >> st18, >> st19, >> st20, >> st21, >> st22, >> st23, >> st24, >> st25, >> st26, >> st27, >> st28, >> st29, >> st30, >> st31, >> st32, >> st33, >> st34, >> st35, >> st36, >> st37, >> st38, >> st39, >> st40, >> st41, >> st42, >> st43, >> st44, >> st45, >> st46, >> st47, >> st48, >> st49, >> st50, >> st51, >> st52, >> st53, >> st54, >> st55, >> st56, >> st57, >> st58, >> st59, >> st60, >> st61, >> st62, >> st63, >> st64, >> st65, >> st66, >> st67, >> st68, >> st69, >> st70, >> st71, >> st72, >> st73, >> st74, >> st75, >> st76, >> st77, >> st78, >> st79, >> st80, >> st81, >> st82, >> st83, >> st84, >> st85, >> st86, >> st87, >> st88, >> st89, >> st90, >> st91, >> st92, >> st93, >> st94, >> st95, >> st96, >> st97, >> st98, >> st99, >> st100, >> st101, >> st102, >> st103, >> st104, >> st105, >> st106, >> st107, >> st108, >> st109, >> st110, >> st111 >>}; >> >> >>DfaState accepts[112] = { >> 0, 1, 2, 3, 4, 12, 6, 0, 26, 13, >> 30, 28, 11, 14, 15, 19, 20, 22, 23, 24, >> 25, 27, 29, 5, 7, 8, 9, 30, 30, 30, >> 30, 30, 28, 29, 30, 30, 30, 30, 30, 30, >> 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, >> 30, 21, 10, 30, 30, 30, 30, 30, 30, 18, >> 30, 17, 16, 0, 31, 32, 0, 34, 36, 33, >> 35, 0, 37, 39, 41, 40, 38, 0, 42, 47, >> 73, 45, 46, 48, 64, 62, 65, 63, 0, 43, >> 49, 51, 52, 55, 60, 56, 59, 61, 68, 72, >> 66, 69, 70, 67, 71, 44, 50, 53, 55, 57, >> 58, 54 >>}; >> >>void (*actions[74])() = { >> zzerraction, >> act1, >> act2, >> act3, >> act4, >> act5, >> act6, >> act7, >> act8, >> act9, >> act10, >> act11, >> act12, >> act13, >> act14, >> act15, >> act16, >> act17, >> act18, >> act19, >> act20, >> act21, >> act22, >> act23, >> act24, >> act25, >> act26, >> act27, >> act28, >> act29, >> act30, >> act31, >> act32, >> act33, >> act34, >> act35, >> act36, >> act37, >> act38, >> act39, >> act40, >> act41, >> act42, >> act43, >> act44, >> act45, >> act46, >> act47, >> act48, >> act49, >> act50, >> act51, >> act52, >> act53, >> act54, >> act55, >> act56, >> act57, >> act58, >> act59, >> act60, >> act61, >> act62, >> act63, >> act64, >> act65, >> act66, >> act67, >> act68, >> act69, >> act70, >> act71, >> act72, >> act73 >>}; >> >>static int dfa_base[] = { >> 0, >> 63, >> 71, >> 77 >>}; >> >>static int dfa_class_no[] = { >> 37, >> 5, >> 5, >> 16 >>}; >> >>static unsigned char *b_class_no[] = { >> shift0, >> shift1, >> shift2, >> shift3 >>}; >> >> >> >>#define ZZSHIFT(c) (b_class_no[zzauto][1+c]) >>#define MAX_MODE 4 >>#include "dlgauto.h" >EOF_scan.c >cat << \EOF_err.c | sed 's/^>//' > err.c >>/* >> * A n t l r S e t s / E r r o r F i l e H e a d e r >> * >> * Generated from: antlr.g >> * >> * Terence Parr, Hank Dietz and Will Cohen: 1989-1992 >> * Purdue University Electrical Engineering >> * ANTLR Version 1.06 >> */ >> >>#include >>#include "set.h" >>#include >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#define zzcr_attr(attr,tok,t) >>#define zzEOF_TOKEN 1 >>#define zzSET_SIZE 3 >>#include "antlr.h" >>#include "dlgdef.h" >>#include "err.h" >> >>char *zztokens[71]={ >> /* 00 */ "Invalid", >> /* 01 */ "Eof", >> /* 02 */ "QuotedTerm", >> /* 03 */ "\\\"", >> /* 04 */ "\\n", >> /* 05 */ "\\~[\"]", >> /* 06 */ "~[\\n\"\\]+", >> /* 07 */ "\\*/", >> /* 08 */ "\\*", >> /* 09 */ "\\n", >> /* 10 */ "~[\\n\\*]+", >> /* 11 */ "Action", >> /* 12 */ "Pred", >> /* 13 */ "PassAction", >> /* 14 */ "\\n", >> /* 15 */ "\\>", >> /* 16 */ "$", >> /* 17 */ "$$", >> /* 18 */ "$\\[\\]", >> /* 19 */ "$\\[", >> /* 20 */ "$[0-9]+", >> /* 21 */ "$[0-9]+.", >> /* 22 */ "$[0-9]+.[0-9]+", >> /* 23 */ "$[_a-zA-Z][_a-zA-Z0-9]*", >> /* 24 */ "#0", >> /* 25 */ "#\\[\\]", >> /* 26 */ "#\\(\\)", >> /* 27 */ "#[0-9]+", >> /* 28 */ "#\\[", >> /* 29 */ "#\\(", >> /* 30 */ "#", >> /* 31 */ "\\)", >> /* 32 */ "\\[", >> /* 33 */ "\\(", >> /* 34 */ "\\\\]", >> /* 35 */ "\\\\)", >> /* 36 */ "\\>", >> /* 37 */ "\\$", >> /* 38 */ "\\#", >> /* 39 */ "\\\\", >> /* 40 */ "\\~[\\]\\)>$#\\]", >> /* 41 */ "~[\\n\\)\\(\\$#\\>\\]\\[]+", >> /* 42 */ "[\\t\\ ]+", >> /* 43 */ "[\\n\\r]", >> /* 44 */ "\\[", >> /* 45 */ "\\<\\<", >> /* 46 */ "\"", >> /* 47 */ "/\\*", >> /* 48 */ "\\*/", >> /* 49 */ "\\>\\>", >> /* 50 */ "#header", >> /* 51 */ "NonTerminal", >> /* 52 */ "!", >> /* 53 */ "\\<", >> /* 54 */ "\\>", >> /* 55 */ ":", >> /* 56 */ ";", >> /* 57 */ "#lexaction", >> /* 58 */ "#lexclass", >> /* 59 */ "TokenTerm", >> /* 60 */ "#errclass", >> /* 61 */ "\\{", >> /* 62 */ "\\}", >> /* 63 */ "#token", >> /* 64 */ "\\|", >> /* 65 */ "^", >> /* 66 */ "\\(", >> /* 67 */ "\\)", >> /* 68 */ "\\*", >> /* 69 */ "\\+", >> /* 70 */ "#[A-Za-z0-9_]*" >>}; >>unsigned zzerr1[3] = {0x4, 0x8000000, 0x0}; >>unsigned zzerr2[3] = {0x4, 0x8080000, 0x0}; >>unsigned zzerr3[3] = {0x4, 0x8080000, 0x0}; >>unsigned zzerr4[3] = {0x3804, 0x69d80000, 0x3f}; >>unsigned zzerr5[3] = {0x3804, 0x69d80000, 0x3f}; >>unsigned zzerr6[3] = {0x3804, 0x69c80000, 0x3d}; >>unsigned zzerr7[3] = {0x3804, 0x28c80000, 0x34}; >>unsigned setwd1[71] = {0x0,0xdd,0xda20,0x0,0x0,0x0,0x0, >> 0x0,0x0,0x0,0x0,0xdadc,0xda00,0xfa02,0x0, >> 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, >> 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, >> 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, >> 0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0, >> 0x0,0x0,0x0,0x0,0xdafc,0x0,0x2002,0xda00, >> 0xda00,0xdd00,0xdc,0xdc,0xda20,0xdc,0xda00,0xdd00, >> 0xdc,0xdc00,0x0,0xda00,0xdd00,0xda00,0xda00,0x0}; >EOF_err.c >cat << \EOF_bits.c | sed 's/^>//' > bits.c >>/* >> * bits.c -- manage creation and output of bit sets used by the parser. >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#include >>#include >>#include "set.h" >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#include "dlgdef.h" >> >>#define BitsPerByte 8 >>#define BitsPerWord BitsPerByte*sizeof(unsigned) >> >>static unsigned *setwd = NULL; >>int setnum = -1; >>int wordnum = 0; >> >>int esetnum = 0; >> >>/* Create a new setwd (ignoring [Ep] token on end) */ >>void >>NewSetWd() >>{ >> unsigned *p; >> >> if ( setwd == NULL ) >> { >> setwd = (unsigned *) calloc(TokenNum, sizeof(unsigned)); >> require(setwd!=NULL, "NewSetWd: cannot alloc set wd\n"); >> } >> for (p = setwd; p<&(setwd[TokenNum]); p++) {*p=0;} >> wordnum++; >>} >> >>/* Dump the current setwd to ErrFile. 0..MaxTokenVal */ >>void >>DumpSetWd() >>{ >> int i,c=1; >> >> if ( setwd==NULL ) return; >> fprintf(DefFile, "extern unsigned setwd%d[];\n", wordnum); >> fprintf(ErrFile, "unsigned setwd%d[%d] = {", wordnum, TokenNum-1); >> for (i=0; i> { >> if ( i!=0 ) fprintf(ErrFile, ","); >> if ( c == 8 ) {fprintf(ErrFile, "\n\t"); c=1;} else c++; >> fprintf(ErrFile, "0x%x", setwd[i]); >> } >> fprintf(ErrFile, "};\n"); >>} >> >>/* Make a new set. Dump old setwd and create new setwd if current setwd is full */ >>void >>NewSet() >>{ >> setnum++; >> if ( setnum==BitsPerWord ) /* is current setwd full? */ >> { >> DumpSetWd(); NewSetWd(); setnum = 0; >> } >>} >> >>/* s is a set of tokens. Turn on bit at each token position in set 'setnum' */ >>void >>FillSet(s) >>set s; >>{ >> unsigned mask=(1<> int e; >> >> while ( !set_nil(s) ) >> { >> e = set_int(s); >> set_rm(e, s); >> setwd[e] |= mask; >> } >>} >> >> /* E r r o r C l a s s S t u f f */ >> >>/* compute the FIRST of a rule for the error class stuff */ >>static set >>Efirst(rule, eclass) >>char *rule; >>ECnode *eclass; >>{ >> set rk, a; >> Junction *r; >> RuleEntry *q = (RuleEntry *) hash_get(Rname, rule); >> >> if ( q == NULL ) >> { >> warnNoFL(eMsg2("undefined rule '%s' referenced in errclass '%s'; ignored", >> rule, TokenStr[eclass->tok])); >> return empty; >> } >> r = RulePtr[q->rulenum]; >> r->end->halt = TRUE; /* don't let reach fall off end of rule here */ >> rk = empty; >> REACH(r, 1, &rk, a); >> r->end->halt = FALSE; >> return a; >>} >> >>/* >> * scan the list of tokens/eclasses/nonterminals filling the new eclass >> * with the set described by the list. Note that an eclass can be >> * quoted to allow spaces etc... However, an eclass must not conflict >> * with a reg expr found elsewhere. The reg expr will be taken over >> * the eclass name. >> */ >>static void >>doEclass(eclass) >>char *eclass; /* pointer to Error Class */ >>{ >> TermEntry *q; >> ECnode *p; >> ListNode *e; >> int t, deg=0; >> set a; >> require(eclass!=NULL, "doEclass: NULL eset"); >> >> p = (ECnode *) eclass; >> lexmode(p->lexclass); /* switch to lexclass where errclass is defined */ >> p->eset = empty; >> for (e = (p->elist)->next; e!=NULL; e=e->next) >> { >> if ( islower( *(e->elem) ) ) /* is it a rule ref? (alias FIRST request) */ >> { >> a = Efirst(e->elem, p); >> set_orin(&p->eset, a); >> deg += set_deg(a); >> set_free( a ); >> continue; >> } >> else if ( *(e->elem)=='"' ) >> { >> t = 0; >> q = (TermEntry *) hash_get(Texpr, e->elem); >> if ( q == NULL ) >> { >> /* if quoted and not an expr look for eclass name */ >> q = (TermEntry *) hash_get(Tname, e->elem=StripQuotes(e->elem)); >> if ( q != NULL ) t = q->token; >> } >> else t = q->token; >> } >> else /* labelled token/eclass */ >> { >> q = (TermEntry *) hash_get(Tname, e->elem); >> if ( q != NULL ) t = q->token; else t=0; >> } >> if ( t!=0 ) >> { >> set_orel(t, &p->eset); >> deg++; >> } >> else warnNoFL(eMsg2("undefined token '%s' referenced in errclass '%s'; ignored", >> e->elem, TokenStr[p->tok])); >> } >> p->setdeg = deg; >>} >> >>void >>ComputeErrorSets() >>{ >> list_apply(eclasses, doEclass); >>} >> >>/* replace a subset of an error set with an error class name if a subset is found >> * repeat process until no replacements made >> */ >>void >>SubstErrorClass(f) >>set *f; >>{ >> int max, done = 0; >> ListNode *p; >> ECnode *ec, *maxclass = NULL; >> set a; >> require(f!=NULL, "SubstErrorClass: NULL eset"); >> >> if ( eclasses == NULL ) return; >> while ( !done ) >> { >> max = 0; >> maxclass = NULL; >> for (p=eclasses->next; p!=NULL; p=p->next) /* chk all error classes */ >> { >> ec = (ECnode *) p->elem; >> if ( ec->setdeg > max ) >> { >> if ( set_sub(ec->eset, *f) || set_equ(ec->eset, *f) ) >> {maxclass = ec; max=ec->setdeg;} >> } >> } >> if ( maxclass != NULL ) /* if subset found, replace with token */ >> { >> a = set_dif(*f, maxclass->eset); >> set_orel(maxclass->tok, &a); >> set_free(*f); >> *f = a; >> } >> else done = 1; >> } >>} >> >>/* Define a new error set. WARNING...set-implementation dependent */ >>int >>DefErrSet(f) >>set *f; >>{ >> unsigned *p, *endp; >> int e=1; >> require(!set_nil(*f), "DefErrSet: nil set to dump?"); >> >> SubstErrorClass(f); >> p = f->setword; >> endp = &(f->setword[NumWords(TokenNum-1)]); >> esetnum++; >> fprintf(DefFile, "extern unsigned zzerr%d[];\n", esetnum); >> fprintf(ErrFile, "unsigned zzerr%d[%d] = {", esetnum, NumWords(TokenNum-1)); >> while ( p < endp ) >> { >> if ( e > 1 ) fprintf(ErrFile, ", "); >> fprintf(ErrFile, "0x%x", *p++); >> if ( e == 7 ) >> { >> if ( p < endp ) fprintf(ErrFile, ","); >> fprintf(ErrFile, "\n\t"); >> e=1; >> } >> else e++; >> } >> fprintf(ErrFile, "};\n"); >> >> return esetnum; >>} >> >>void >>GenErrHdr() >>{ >> int i, j; >> >> fprintf(ErrFile, "/*\n"); >> fprintf(ErrFile, " * A n t l r S e t s / E r r o r F i l e H e a d e r\n"); >> fprintf(ErrFile, " *\n"); >> fprintf(ErrFile, " * Generated from:"); >> for (i=0; i> fprintf(ErrFile, "\n"); >> fprintf(ErrFile, " *\n"); >> fprintf(ErrFile, " * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n"); >> fprintf(ErrFile, " * Purdue University Electrical Engineering\n"); >> fprintf(ErrFile, " * ANTLR Version %s\n", Version); >> fprintf(ErrFile, " */\n\n"); >> fprintf(ErrFile, "#include \n"); >> if ( HdrAction != NULL ) dumpAction( HdrAction, ErrFile, 0, -1, 0, 1 ); >> if ( LL_k > 1 ) fprintf(ErrFile, "#define LL_K %d\n", OutputLL_k); >> fprintf(ErrFile, "#define zzEOF_TOKEN %d\n", EofToken); >> fprintf(ErrFile, "#define zzSET_SIZE %d\n", NumWords(TokenNum-1)); >> if ( DemandLookahead ) fprintf(ErrFile, "#define DEMAND_LOOK\n"); >> fprintf(ErrFile, "#include \"antlr.h\"\n"); >> fprintf(ErrFile, "#include \"dlgdef.h\"\n"); >> fprintf(ErrFile, "#include \"err.h\"\n\n"); >> >> /* Dump a zztokens for each automaton */ >> fprintf(ErrFile, "char *zztokens[%d]={\n", TokenNum-1); >> fprintf(ErrFile, "\t/* 00 */\t\"Invalid\",\n"); >> if ( TokenStr[EofToken] != NULL ) >> fprintf(ErrFile, "\t/* %02d */\t\"%s\"", EofToken, TokenStr[i]); >> else >> fprintf(ErrFile, "\t/* %02d */\t\"EOF\"", EofToken); >> for (i=TokenStart; i> { >> if ( i == EpToken ) continue; >> if ( TokenStr[i] != NULL ) >> fprintf(ErrFile, ",\n\t/* %02d */\t\"%s\"", i, TokenStr[i]); >> else >> { >> /* look in all lexclasses for the reg expr */ >> for (j=0; j> { >> lexmode(j); >> if ( ExprStr[i] != NULL ) >> { >> fprintf(ErrFile, ",\n\t/* %02d */\t", i); >> dumpExpr(ExprStr[i]); >> break; >> } >> } >> require(j> } >> } >> fprintf(ErrFile, "\n};\n"); >>} >> >>void >>dumpExpr(e) >>char *e; >>{ >> while ( *e!='\0' ) >> { >> if ( *e=='\\' && *(e+1)=='\\' ) >> {putc('\\', ErrFile); putc('\\', ErrFile); e+=2;} >> else if ( *e=='\\' && *(e+1)=='"' ) >> {putc('\\', ErrFile); putc('"', ErrFile); e+=2;} >> else if ( *e=='\\' ) {putc('\\', ErrFile); putc('\\', ErrFile); e++;} >> else {putc(*e, ErrFile); e++;} >> } >>} >> >EOF_bits.c >cat << \EOF_build.c | sed 's/^>//' > build.c >>/* >> * build.c -- functions associated with building syntax diagrams. >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#include >>#include "set.h" >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#include "dlgdef.h" >> >>#define SetBlk(g, t) { \ >> ((Junction *)g.left)->jtype = t; \ >> ((Junction *)g.left)->end = (Junction *) g.right; \ >> ((Junction *)g.right)->jtype = EndBlk;} >> >>/* Add the parameter string 'parm' to the parms field of a block-type junction >> * g.left points to the sentinel node on a block. i.e. g.left->p1 points to >> * the actual junction with its jtype == some block-type. >> */ >>void >>addParm(p,parm) >>Node *p; >>char *parm; >>{ >> char *q = malloc( strlen(parm) + 1 ); >> require(p!=NULL, "addParm: NULL object\n"); >> require(q!=NULL, "addParm: unable to alloc parameter\n"); >> >> strcpy(q, parm); >> if ( p->ntype == nRuleRef ) >> { >> ((RuleRefNode *)p)->parms = q; >> } >> else if ( p->ntype == nJunction ) >> { >> ((Junction *)p)->parm = q; /* only one parameter allowed on subrules */ >> } >> else fatal("addParm: invalid node for adding parm"); >>} >> >>/* >> * Build an action node for the syntax diagram >> * >> * buildAction(ACTION) ::= --o-->ACTION-->o-- >> * >> * Where o is a junction node. >> */ >>Graph >>buildAction(action, file, line, is_predicate) >>char *action; >>int file, line; >>int is_predicate; >>{ >> Junction *j1, *j2; >> Graph g; >> ActionNode *a; >> require(action!=NULL, "buildAction: invalid action"); >> >> j1 = newJunction(); >> j2 = newJunction(); >> a = newActionNode(); >> a->action = malloc( strlen(action)+1 ); >> require(a->action!=NULL, "buildAction: cannot alloc space for action\n"); >> strcpy(a->action, action); >> j1->p1 = (Node *) a; >> a->next = (Node *) j2; >> a->is_predicate = is_predicate; >> g.left = (Node *) j1; g.right = (Node *) j2; >> a->file = file; >> a->line = line; >> return g; >>} >> >>/* >> * Build a token node for the syntax diagram >> * >> * buildToken(TOKEN) ::= --o-->TOKEN-->o-- >> * >> * Where o is a junction node. >> */ >>Graph >>buildToken(text) >>char *text; >>{ >> Junction *j1, *j2; >> Graph g; >> TokNode *t; >> require(text!=NULL, "buildToken: invalid token name"); >> >> j1 = newJunction(); >> j2 = newJunction(); >> t = newTokNode(); >> if ( *text == '"' ) {t->label=FALSE; t->token = addTexpr( text );} >> else {t->label=TRUE; t->token = addTname( text );} >> j1->p1 = (Node *) t; >> t->next = (Node *) j2; >> g.left = (Node *) j1; g.right = (Node *) j2; >> return g; >>} >> >>/* >> * Build a rule reference node of the syntax diagram >> * >> * buildRuleRef(RULE) ::= --o-->RULE-->o-- >> * >> * Where o is a junction node. >> * >> * If rule 'text' has been defined already, don't alloc new space to store string. >> * Set r->text to point to old copy in string table. >> */ >>Graph >>buildRuleRef(text) >>char *text; >>{ >> Junction *j1, *j2; >> Graph g; >> RuleRefNode *r; >> RuleEntry *p; >> require(text!=NULL, "buildRuleRef: invalid rule name"); >> >> j1 = newJunction(); >> j2 = newJunction(); >> r = newRNode(); >> r->assign = NULL; >> if ( (p=(RuleEntry *)hash_get(Rname, text)) != NULL ) r->text = p->str; >> else r->text = strdup( text ); >> j1->p1 = (Node *) r; >> r->next = (Node *) j2; >> g.left = (Node *) j1; g.right = (Node *) j2; >> return g; >>} >> >>/* >> * Or two subgraphs into one graph via: >> * >> * Or(G1, G2) ::= --o-G1-o-- >> * | ^ >> * v | >> * o-G2-o >> * >> * Set the altnum of junction starting G2 to 1 + altnum of junction starting G1. >> * If, however, the G1 altnum is 0, make it 1 and then >> * make G2 altnum = G1 altnum + 1. >> */ >>Graph >>Or(g1,g2) >>Graph g1, g2; >>{ >> Graph g; >> require(g1.left != NULL, "Or: invalid graph"); >> require(g2.left != NULL && g2.right != NULL, "Or: invalid graph"); >> >> ((Junction *)g1.left)->p2 = g2.left; >> ((Junction *)g2.right)->p1 = g1.right; >> /* set altnums */ >> if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1; >> ((Junction *)g2.left)->altnum = ((Junction *)g1.left)->altnum + 1; >> g.left = g2.left; >> g.right = g1.right; >> return g; >>} >> >>/* >> * Catenate two subgraphs >> * >> * Cat(G1, G2) ::= --o-G1-o-->o-G2-o-- >> * Cat(NULL,G2)::= --o-G2-o-- >> * Cat(G1,NULL)::= --o-G1-o-- >> */ >>Graph >>Cat(g1,g2) >>Graph g1, g2; >>{ >> Graph g; >> >> if ( g1.left == NULL && g1.right == NULL ) return g2; >> if ( g2.left == NULL && g2.right == NULL ) return g1; >> ((Junction *)g1.right)->p1 = g2.left; >> g.left = g1.left; >> g.right = g2.right; >> return g; >>} >> >>/* >> * Make a subgraph an optional block >> * >> * makeOpt(G) ::= --o-->o-G-o-->o-- >> * | ^ >> * v | >> * o-------o >> * >> * Note that this constructs {A|B|...|Z} as if (A|B|...|Z|) was found. >> * >> * The node on the far right is added so that every block owns its own >> * EndBlk node. >> */ >>Graph >>makeOpt(g1) >>Graph g1; >>{ >> Junction *j1,*j2,*p; >> Graph g; >> require(g1.left != NULL && g1.right != NULL, "makeOpt: invalid graph"); >> >> j1 = newJunction(); >> j2 = newJunction(); >> ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */ >> g = emptyAlt(); >> if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1; >> ((Junction *)g.left)->altnum = ((Junction *)g1.left)->altnum + 1; >> for(p=(Junction *)g1.left; p->p2!=NULL; p=(Junction *)p->p2) >> {;} /* find last alt */ >> p->p2 = g.left; /* add optional alternative */ >> ((Junction *)g.right)->p1 = (Node *)j2; /* opt alt points to EndBlk */ >> g1.right = (Node *)j2; >> SetBlk(g1, aOptBlk); >> j1->p1 = g1.left; /* add generic node in front */ >> g.left = (Node *) j1; >> g.right = g1.right; >> >> return g; >>} >> >>/* >> * Make a graph into subblock >> * >> * makeBlk(G) ::= --o-->o-G-o-->o-- >> * >> * The node on the far right is added so that every block owns its own >> * EndBlk node. >> */ >>Graph >>makeBlk(g1) >>Graph g1; >>{ >> Junction *j,*j2; >> Graph g; >> require(g1.left != NULL && g1.right != NULL, "makeBlk: invalid graph"); >> >> j = newJunction(); >> j2 = newJunction(); >> ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */ >> g1.right = (Node *)j2; >> SetBlk(g1, aSubBlk); >> j->p1 = g1.left; /* add node in front */ >> g.left = (Node *) j; >> g.right = g1.right; >> >> return g; >>} >> >>/* >> * Make a subgraph into a loop (closure) block -- (...)* >> * >> * makeLoop(G) ::= |---| >> * v | >> * --o-->o-->o-G-o-->o-- >> * | ^ >> * v | >> * o-----------o >> * >> * After making loop, always place generic node out front. It becomes >> * the start of enclosing block. The aLoopBlk is the target of the loop. >> * >> * Loop blks have TWO EndBlk nodes--the far right and the node that loops back >> * to the aLoopBlk node. Node with which we can branch past loop == aLoopBegin and >> * one which is loop target == aLoopBlk. >> * The branch-past (initial) aLoopBegin node has end >> * pointing to the last EndBlk node. The loop-target node has end==NULL. >> * >> * Loop blocks have a set of locks (from 1..LL_k) on the aLoopBlk node. >> */ >>Graph >>makeLoop(g1) >>Graph g1; >>{ >> Junction *back, *front, *begin; >> Graph g; >> require(g1.left != NULL && g1.right != NULL, "makeLoop: invalid graph"); >> >> back = newJunction(); >> front = newJunction(); >> begin = newJunction(); >> g = emptyAlt(); >> ((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */ >> ((Junction *)g1.right)->p1 = (Node *) back; /* add node to G at end */ >> ((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */ >> ((Junction *)g1.left)->jtype = aLoopBlk; /* mark 2nd aLoopBlk node */ >> ((Junction *)g1.left)->end = (Junction *) g1.right; >> ((Junction *)g1.left)->lock = makelocks(); >> ((Junction *)g1.left)->pred_lock = makelocks(); >> g1.right = (Node *) back; >> begin->p1 = (Node *) g1.left; >> g1.left = (Node *) begin; >> begin->p2 = (Node *) g.left; /* make bypass arc */ >> ((Junction *)g.right)->p1 = (Node *) back; >> SetBlk(g1, aLoopBegin); >> front->p1 = g1.left; /* add node to front */ >> g1.left = (Node *) front; >> >> return g1; >>} >> >>/* >> * Make a subgraph into a plus block -- (...)+ -- 1 or more times >> * >> * makeLoop(G) ::= |---| >> * v | >> * --o-->o-G-o-->o-- >> * >> * After making loop, always place generic node out front. It becomes >> * the start of enclosing block. The aPlusBlk is the target of the loop. >> * >> * Plus blks have TWO EndBlk nodes--the far right and the node that loops back >> * to the aPlusBlk node. >> * >> * Plus blocks have a set of locks (from 1..LL_k) on the aPlusBlk node. >> */ >>Graph >>makePlus(g1) >>Graph g1; >>{ >> Junction *j2, *j3; >> require(g1.left != NULL && g1.right != NULL, "makePlus: invalid graph"); >> >> j2 = newJunction(); >> j3 = newJunction(); >> if ( ((Junction *)g1.left)->altnum == 0 ) ((Junction *)g1.left)->altnum = 1; >> ((Junction *)g1.right)->p2 = g1.left; /* add loop branch to G */ >> ((Junction *)g1.right)->p1 = (Node *) j2; /* add node to G at end */ >> ((Junction *)g1.right)->jtype = EndBlk; /* mark 1st EndBlk node */ >> g1.right = (Node *) j2; >> SetBlk(g1, aPlusBlk); >> ((Junction *)g1.left)->lock = makelocks(); >> ((Junction *)g1.left)->pred_lock = makelocks(); >> j3->p1 = g1.left; /* add node to front */ >> g1.left = (Node *) j3; >> >> return g1; >>} >> >>/* >> * Return an optional path: --o-->o-- >> */ >>Graph >>emptyAlt() >>{ >> Junction *j1, *j2; >> Graph g; >> >> j1 = newJunction(); >> j2 = newJunction(); >> j1->p1 = (Node *) j2; >> g.left = (Node *) j1; >> g.right = (Node *) j2; >> >> return g; >>} >> >>/* N o d e A l l o c a t i o n */ >> >>TokNode * >>newTokNode() >>{ >> static TokNode *FreeList = NULL; >> TokNode *p, *newblk; >> >> if ( FreeList == NULL ) >> { >> newblk = (TokNode *)calloc(TokenBlockAllocSize, sizeof(TokNode)); >> if ( newblk == NULL ) >> fatal(eMsg1("out of memory while building rule '%s'",CurRule)); >> for (p=newblk; p<&(newblk[TokenBlockAllocSize]); p++) >> { >> p->next = (Node *)FreeList; /* add all new token nodes to FreeList */ >> FreeList = p; >> } >> } >> p = FreeList; >> FreeList = (TokNode *)FreeList->next;/* remove a Junction node */ >> p->next = NULL; /* NULL the ptr we used */ >> >> p->ntype = nToken; >> p->rname = CurRule; >> p->file = CurFile; >> p->line = zzline; >> >> return p; >>} >> >>RuleRefNode * >>newRNode() >>{ >> static RuleRefNode *FreeList = NULL; >> RuleRefNode *p, *newblk; >> >> if ( FreeList == NULL ) >> { >> newblk = (RuleRefNode *)calloc(RRefBlockAllocSize, sizeof(RuleRefNode)); >> if ( newblk == NULL ) >> fatal(eMsg1("out of memory while building rule '%s'",CurRule)); >> for (p=newblk; p<&(newblk[RRefBlockAllocSize]); p++) >> { >> p->next = (Node *)FreeList; /* add all new rref nodes to FreeList */ >> FreeList = p; >> } >> } >> p = FreeList; >> FreeList = (RuleRefNode *)FreeList->next;/* remove a Junction node */ >> p->next = NULL; /* NULL the ptr we used */ >> >> p->ntype = nRuleRef; >> p->rname = CurRule; >> p->file = CurFile; >> p->line = zzline; >> p->astnode = ASTinclude; >> >> return p; >>} >> >>Junction * >>newJunction() >>{ >> static Junction *FreeList = NULL; >> Junction *p, *newblk; >> >> if ( FreeList == NULL ) >> { >> newblk = (Junction *)calloc(JunctionBlockAllocSize, sizeof(Junction)); >> if ( newblk == NULL ) >> fatal(eMsg1("out of memory while building rule '%s'",CurRule)); >> for (p=newblk; p<&(newblk[JunctionBlockAllocSize]); p++) >> { >> p->p1 = (Node *)FreeList; /* add all new Junction nodes to FreeList */ >> FreeList = p; >> } >> } >> p = FreeList; >> FreeList = (Junction *)FreeList->p1;/* remove a Junction node */ >> p->p1 = NULL; /* NULL the ptr we used */ >> >> p->ntype = nJunction; p->visited = 0; >> p->jtype = Generic; >> p->rname = CurRule; >> p->file = CurFile; >> p->line = zzline; >> p->fset = (set *) calloc(LL_k+1, sizeof(set)); >> require(p->fset!=NULL, "cannot allocate fset in newJunction"); >> >> return p; >>} >> >>ActionNode * >>newActionNode() >>{ >> static ActionNode *FreeList = NULL; >> ActionNode *p, *newblk; >> >> if ( FreeList == NULL ) >> { >> newblk = (ActionNode *)calloc(ActionBlockAllocSize, sizeof(ActionNode)); >> if ( newblk == NULL ) >> fatal(eMsg1("out of memory while building rule '%s'",CurRule)); >> for (p=newblk; p<&(newblk[ActionBlockAllocSize]); p++) >> { >> p->next = (Node *)FreeList; /* add all new Action nodes to FreeList */ >> FreeList = p; >> } >> } >> p = FreeList; >> FreeList = (ActionNode *)FreeList->next;/* remove a Junction node */ >> p->next = NULL; /* NULL the ptr we used */ >> >> p->ntype = nAction; >> return p; >>} >> >>/* >> * allocate the array of locks (1..LL_k) used to inhibit infinite recursion. >> * Infinite recursion can occur in (..)* blocks, FIRST calcs and FOLLOW calcs. >> * Therefore, we need locks on aLoopBlk, RuleBlk, EndRule nodes. >> * >> * if ( lock[k]==TRUE ) then we have been here before looking for k tokens >> * of lookahead. >> */ >>char * >>makelocks() >>{ >> char *p = (char *) calloc(LL_k+1, sizeof(char)); >> require(p!=NULL, "cannot allocate lock array"); >> >> return p; >>} >EOF_build.c >cat << \EOF_fset2.c | sed 's/^>//' > fset2.c >>/* >> * fset2.c >> * >> * Compute FIRST sets for full LL(k) >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#include >>#ifdef __STDC__ >>#include >>#else >>#include >>#endif >>#include "set.h" >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#include "dlgdef.h" >> >>extern char tokens[]; >> >>/* ick! globals. Used by permute() to track which elements of a set have been used */ >>static int *index; >>static set *fset; >>static unsigned **ftbl; >>static set *constrain; /* pts into fset. constrains tToken() to 'constrain' */ >>int ConstrainSearch; >>static int maxk; /* set to initial k upon tree construction request */ >>static Tree *FreeList = NULL; >> >>#ifdef __STDC__ >>Tree *tmake(Tree *root, ...); >>#else >>Tree *tmake(); >>#endif >> >>/* Do root >> * Then each sibling >> */ >>void >>preorder(tree) >>Tree *tree; >>{ >> if ( tree == NULL ) return; >> if ( tree->down != NULL ) fprintf(stderr, " ("); >> if ( tree->token == ALT ) fprintf(stderr, " J"); >> else fprintf(stderr, " %s", TerminalString(tree->token)); >> if ( tree->token==EpToken ) fprintf(stderr, "(%d)", tree->v.rk); >> preorder(tree->down); >> if ( tree->down != NULL ) fprintf(stderr, " )"); >> preorder(tree->right); >>} >> >>/* check the depth of each primary sibling to see that it is exactly >> * k deep. e.g.; >> * >> * ALT >> * | >> * A ------- B >> * | | >> * C -- D E >> * >> * Remove all branches <= k deep. >> * >> * Added by TJP 9-23-92 to correct the LL(k) constraint mechanism to work. >> */ >>Tree * >>prune(t, k) >>Tree *t; >>int k; >>{ >> if ( t == NULL ) return NULL; >> if ( t->token == ALT ) fatal("prune: ALT node in FIRST tree"); >> t->right = prune(t->right, k); >> t->down = prune(t->down, k-1); >> if ( t->down == NULL && k > 1 ) >> { >> Tree *r = t->right; >> t->right = NULL; >> Tfree(t); >> return r; >> } >> return t; >>} >> >>/* build a tree (root child1 child2 ... NULL) */ >>#ifdef __STDC__ >>Tree *tmake(Tree *root, ...) >>#else >>Tree *tmake(va_alist) >>va_dcl >>#endif >>{ >> va_list ap; >> Tree *child, *sibling=NULL, *tail; >>#ifndef __STDC__ >> Tree *root; >>#endif >>#ifdef __STDC__ >> require(root!=NULL, "tmake: NULL root impossible"); >>#endif >> >>#ifdef __STDC__ >> va_start(ap, root); >>#else >> va_start(ap); >> root = va_arg(ap, Tree *); >>#endif >> child = va_arg(ap, Tree *); >> while ( child != NULL ) >> { >> if ( sibling == NULL ) sibling = tail = child; >> else {tail->right = child; tail = child;} >> child = va_arg(ap, Tree *); >> } >> root->down = sibling; >> va_end(ap); >> return root; >>} >> >>Tree * >>tnode(tok) >>int tok; >>{ >> Tree *p, *newblk; >> static int n=0; >> >> if ( FreeList == NULL ) >> { >> /*fprintf(stderr, "tnode: %d more nodes\n", TreeBlockAllocSize);*/ >> if ( TreeResourceLimit > 0 ) >> { >> if ( (n+TreeBlockAllocSize) >= TreeResourceLimit ) >> { >> fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline); >> fprintf(stderr, " hit analysis resource limit while analyzing alts %d and %d %s\n", >> CurAmbigAlt1, >> CurAmbigAlt2, >> CurAmbigbtype); >> exit(-1); >> } >> } >> newblk = (Tree *)calloc(TreeBlockAllocSize, sizeof(Tree)); >> if ( newblk == NULL ) >> { >> fprintf(stderr, ErrHdr, FileStr[CurAmbigfile], CurAmbigline); >> fprintf(stderr, " out of memory while analyzing alts %d and %d %s\n", >> CurAmbigAlt1, >> CurAmbigAlt2, >> CurAmbigbtype); >> exit(-1); >> } >> n += TreeBlockAllocSize; >> for (p=newblk; p<&(newblk[TreeBlockAllocSize]); p++) >> { >> p->right = FreeList; /* add all new Tree nodes to Free List */ >> FreeList = p; >> } >> } >> p = FreeList; >> FreeList = FreeList->right; /* remove a tree node */ >> p->right = NULL; /* zero out ptrs */ >> p->down = NULL; >> p->token = tok; >> return p; >>} >> >>static Tree * >>eofnode(k) >>int k; >>{ >> Tree *t=NULL; >> int i; >> >> for (i=1; i<=k; i++) >> { >> t = tmake(tnode(EofToken), t, NULL); >> } >> return t; >>} >> >> >> >>void >>tfree(t) >>Tree *t; >>{ >> if ( t!=NULL ) >> { >> t->right = FreeList; >> FreeList = t; >> } >>} >> >>/* tree duplicate */ >>Tree * >>tdup(t) >>Tree *t; >>{ >> Tree *u; >> >> if ( t == NULL ) return NULL; >> u = tnode(t->token); >> u->v.rk = t->v.rk; >> u->right = tdup(t->right); >> u->down = tdup(t->down); >> return u; >>} >> >>Tree * >>tappend(t,u) >>Tree *t, *u; >>{ >> Tree *w; >> >> /*fprintf(stderr, "tappend("); >> preorder(t); fprintf(stderr, ","); >> preorder(u); fprintf(stderr, " )\n");*/ >> if ( t == NULL ) return u; >> if ( t->token == ALT && t->right == NULL ) return tappend(t->down, u); >> for (w=t; w->right!=NULL; w=w->right) {;} >> w->right = u; >> return t; >>} >> >>/* dealloc all nodes in a tree */ >>void >>Tfree(t) >>Tree *t; >>{ >> if ( t == NULL ) return; >> Tfree( t->down ); >> Tfree( t->right ); >> tfree( t ); >>} >> >>/* find all children (alts) of t that require remaining_k nodes to be LL_k >> * tokens long. >> * >> * t-->o >> * | >> * a1--a2--...--an <-- LL(1) tokens >> * | | | >> * b1 b2 ... bn <-- LL(2) tokens >> * | | | >> * . . . >> * . . . >> * z1 z2 ... zn <-- LL(LL_k) tokens >> * >> * We look for all [Ep] needing remaining_k nodes and replace with u. >> * u is not destroyed or actually used by the tree (a copy is made). >> */ >>Tree * >>tlink(t,u,remaining_k) >>Tree *t, *u; >>int remaining_k; >>{ >> Tree *p; >> require(remaining_k!=0, "tlink: bad tree"); >> >> if ( t==NULL ) return NULL; >> /*fprintf(stderr, "tlink: u is:"); preorder(u); fprintf(stderr, "\n");*/ >> if ( t->token == EpToken && t->v.rk == remaining_k ) >> { >> require(t->down==NULL, "tlink: invalid tree"); >> if ( u == NULL ) return t->right; >> p = tdup( u ); >> p->right = t->right; >> tfree( t ); >> return p; >> } >> t->down = tlink(t->down, u, remaining_k); >> t->right = tlink(t->right, u, remaining_k); >> return t; >>} >> >>/* remove as many ALT nodes as possible while still maintaining semantics */ >>Tree * >>tshrink(t) >>Tree *t; >>{ >> if ( t == NULL ) return NULL; >> t->down = tshrink( t->down ); >> t->right = tshrink( t->right ); >> if ( t->down == NULL ) >> { >> if ( t->token == ALT ) >> { >> Tree *u = t->right; >> tfree(t); >> return u; /* remove useless alts */ >> } >> return t; >> } >> >> /* (? (ALT (? ...)) s) ==> (? (? ...) s) where s = sibling, ? = match any */ >> if ( t->token == ALT && t->down->right == NULL) >> { >> Tree *u = t->down; >> u->right = t->right; >> tfree( t ); >> return u; >> } >> /* (? (A (ALT t)) s) ==> (? (A t) s) where A is a token; s,t siblings */ >> if ( t->token != ALT && t->down->token == ALT && t->down->right == NULL ) >> { >> Tree *u = t->down->down; >> tfree( t->down ); >> t->down = u; >> return t; >> } >> return t; >>} >> >>Tree * >>tflatten(t) >>Tree *t; >>{ >> if ( t == NULL ) return NULL; >> t->down = tflatten( t->down ); >> t->right = tflatten( t->right ); >> if ( t->down == NULL ) return t; >> >> if ( t->token == ALT ) >> { >> Tree *u; >> /* find tail of children */ >> for (u=t->down; u->right!=NULL; u=u->right) {;} >> u->right = t->right; >> u = t->down; >> tfree( t ); >> return u; >> } >> return t; >>} >> >>Tree * >>tJunc(p,k,rk) >>Junction *p; >>int k; >>set *rk; >>{ >> Tree *t=NULL, *u=NULL; >> Junction *alt; >> Tree *tail, *r; >> >>#ifdef DBG_TRAV >> fprintf(stderr, "tJunc(%d): %s in rule %s\n", k, >> decodeJType[p->jtype], ((Junction *)p)->rname); >>#endif >> if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || >> p->jtype==aPlusBlk || p->jtype==aSubBlk || p->jtype==aOptBlk ) >> { >> if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) { >> require(p->lock!=NULL, "rJunc: lock array is NULL"); >> if ( p->lock[k] ) return NULL; >> p->lock[k] = TRUE; >> } >> TRAV(p->p1, k, rk, tail); >> if ( p->jtype==RuleBlk ) {p->lock[k] = FALSE; return tail;} >> r = tmake(tnode(ALT), tail, NULL); >> for (alt=(Junction *)p->p2; alt!=NULL; alt = (Junction *)alt->p2) >> { >> if ( tail==NULL ) {TRAV(alt->p1, k, rk, tail); r->down = tail;} >> else >> { >> TRAV(alt->p1, k, rk, tail->right); >> /* TJP -- lost info when tail->right was NULL >> tail = tail->right;*/ >> if ( tail->right != NULL ) tail = tail->right; >> } >> } >> if ( p->jtype!=aSubBlk && p->jtype!=aOptBlk ) p->lock[k] = FALSE; >>#ifdef DBG_TREES >> fprintf(stderr, "blk(%s) returns:",((Junction *)p)->rname); preorder(r); fprintf(stderr, "\n"); >>#endif >> if ( r->down == NULL ) {tfree(r); return NULL;} >> return r; >> } >> >> if ( p->jtype==EndRule ) >> { >> if ( p->halt ) /* don't want FOLLOW here? */ >> { >> set_orel(k, rk); /* indicate this k value needed */ >> t = tnode(EpToken); >> t->v.rk = k; >> return t; >> } >> require(p->lock!=NULL, "rJunc: lock array is NULL"); >> if ( p->lock[k] ) return NULL; >> /* if no FOLLOW assume k EOF's */ >> if ( p->p1 == NULL ) return eofnode(k); >> p->lock[k] = TRUE; >> } >> >> if ( p->p2 == NULL ) >> { >> TRAV(p->p1, k, rk,t); >> if ( p->jtype==EndRule ) p->lock[k]=FALSE; >> return t; >> } >> TRAV(p->p1, k, rk, t); >> if ( p->jtype!=RuleBlk ) TRAV(p->p2, k, rk, u); >> if ( p->jtype==EndRule ) p->lock[k] = FALSE;/* unlock node */ >> >> if ( t==NULL ) return tmake(tnode(ALT), u, NULL); >> return tmake(tnode(ALT), t, u, NULL); >>} >> >>Tree * >>tRuleRef(p,k,rk_out) >>RuleRefNode *p; >>int k; >>set *rk_out; >>{ >> int k2; >> Tree *t, *u; >> Junction *r; >> set rk, rk2; >> char save_halt; >> RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text); >> >>#ifdef DBG_TRAV >> fprintf(stderr, "tRuleRef: %s\n", p->text); >>#endif >> if ( q == NULL ) >> { >> TRAV(p->next, k, rk_out, t);/* ignore undefined rules */ >> return t; >> } >> rk = rk2 = empty; >> r = RulePtr[q->rulenum]; >> if ( r->lock[k] ) return NULL; >> save_halt = r->end->halt; >> r->end->halt = TRUE; /* don't let reach fall off end of rule here */ >> TRAV(r, k, &rk, t); >> r->end->halt = save_halt; >>#ifdef DBG_TREES >> fprintf(stderr, "after ruleref, t is:"); preorder(t); fprintf(stderr, "\n"); >>#endif >> t = tshrink( t ); >> while ( !set_nil(rk) ) { /* any k left to do? if so, link onto tree */ >> k2 = set_int(rk); >> set_rm(k2, rk); >> TRAV(p->next, k2, &rk2, u); >> t = tlink(t, u, k2); /* any alts missing k2 toks, add u onto end */ >> } >> set_orin(rk_out, rk2); /* remember what we couldn't do */ >> set_free(rk2); >> return t; >>} >> >>Tree * >>tToken(p,k,rk) >>TokNode *p; >>int k; >>set *rk; >>{ >> Tree *t; >> require(constrain>=fset&&constrain<=&(fset[LL_k]),"tToken: constrain is not a valid set"); >> >> constrain = &fset[maxk-k+1]; >> >>#ifdef DBG_TRAV >> fprintf(stderr, "tToken(%d): %s\n", k, TerminalString(p->token)); >> if ( ConstrainSearch ) { >> fprintf(stderr, "constrain is:"); s_fprT(stderr, *constrain); fprintf(stderr, "\n"); >> } >>#endif >> if ( ConstrainSearch ) >> if ( !set_el(p->token, *constrain) ) >> { >>/* fprintf(stderr, "ignoring token %s(%d)\n", TerminalString(p->token), >> k);*/ >> return NULL; >> } >> if ( k == 1 ) return tnode(p->token); >> TRAV(p->next, k-1, rk, t); >> /* here, we are positive that, at least, this tree will not contribute >> * to the LL(2) tree since it will be too shallow, IF t==NULL >> */ >> if ( t == NULL ) /* tree will be too shallow */ >> { >> return NULL; >> } >>#ifdef DBG_TREES >> fprintf(stderr, "tToken(%d)->next:",k); preorder(t); fprintf(stderr, "\n"); >>#endif >> return tmake(tnode(p->token), t, NULL); >>} >> >>Tree * >>tAction(p,k,rk) >>ActionNode *p; >>int k; >>set *rk; >>{ >> Tree *t; >> >> /*fprintf(stderr, "tAction\n");*/ >> TRAV(p->next, k, rk, t); >> return t; >>} >> >>/* see if e exists in s as a possible input permutation (e is always a chain) */ >>int >>tmember(e,s) >>Tree *e, *s; >>{ >> if ( e==NULL||s==NULL ) return 0; >> /*fprintf(stderr, "tmember("); >> preorder(e); fprintf(stderr, ","); >> preorder(s); fprintf(stderr, " )\n");*/ >> if ( s->token == ALT && s->right == NULL ) return tmember(e, s->down); >> if ( e->token!=s->token ) >> { >> if ( s->right==NULL ) return 0; >> return tmember(e, s->right); >> } >> if ( e->down==NULL && s->down == NULL ) return 1; >> if ( tmember(e->down, s->down) ) return 1; >> if ( s->right==NULL ) return 0; >> return tmember(e, s->right); >>} >> >>/* combine (? (A t) ... (A u) ...) into (? (A t u)) */ >>Tree * >>tleft_factor(t) >>Tree *t; >>{ >> Tree *u, *v, *trail, *w; >> >> /* left-factor what is at this level */ >> if ( t == NULL ) return NULL; >> for (u=t; u!=NULL; u=u->right) >> { >> trail = u; >> v=u->right; >> while ( v!=NULL ) >> { >> if ( u->token == v->token ) >> { >> if ( u->down!=NULL ) >> { >> for (w=u->down; w->right!=NULL; w=w->right) {;} >> w->right = v->down; /* link children together */ >> } >> else u->down = v->down; >> trail->right = v->right; /* unlink factored node */ >> tfree( v ); >> v = trail->right; >> } >> else {trail = v; v=v->right;} >> } >> } >> /* left-factor what is below */ >> for (u=t; u!=NULL; u=u->right) u->down = tleft_factor( u->down ); >> return t; >>} >> >>/* remove the permutation p from t if present */ >>Tree * >>trm_perm(t,p) >>Tree *t, *p; >>{ >> /* >> fprintf(stderr, "trm_perm("); >> preorder(t); fprintf(stderr, ","); >> preorder(p); fprintf(stderr, " )\n"); >> */ >> if ( t == NULL || p == NULL ) return NULL; >> if ( t->token == ALT ) >> { >> t->down = trm_perm(t->down, p); >> if ( t->down == NULL ) /* nothing left below, rm cur node */ >> { >> Tree *u = t->right; >> tfree( t ); >> return trm_perm(u, p); >> } >> t->right = trm_perm(t->right, p); /* look for more instances of p */ >> return t; >> } >> if ( p->token != t->token ) /* not found, try a sibling */ >> { >> t->right = trm_perm(t->right, p); >> return t; >> } >> t->down = trm_perm(t->down, p->down); >> if ( t->down == NULL ) /* nothing left below, rm cur node */ >> { >> Tree *u = t->right; >> tfree( t ); >> return trm_perm(u, p); >> } >> t->right = trm_perm(t->right, p); /* look for more instances of p */ >> return t; >>} >> >>/* add the permutation 'perm' to the LL_k sets in 'fset' */ >>void >>tcvt(fset,perm) >>set *fset; >>Tree *perm; >>{ >> if ( perm==NULL ) return; >> set_orel(perm->token, fset); >> tcvt(fset+1, perm->down); >>} >> >>/* for each element of ftbl[k], make it the root of a tree with permute(ftbl[k+1]) >> * as a child. >> */ >>Tree * >>permute(k) >>int k; >>{ >> Tree *t, *u; >> >> if ( k>LL_k ) return NULL; >> if ( ftbl[k][index[k]] == nil ) return NULL; >> t = permute(k+1); >> if ( t==NULL&&k> { >> index[k+1] = 0; >> (index[k])++; /* try next token at this k */ >> return permute(k); >> } >> >> u = tmake(tnode(ftbl[k][index[k]]), t, NULL); >> if ( k == LL_k ) (index[k])++; >> return u; >>} >> >>/* Compute LL(k) trees for alts alt1 and alt2 of p. >> * function result is tree of ambiguous input permutations >> * >> * ALGORITHM may change to look for something other than LL_k size >> * trees ==> maxk will have to change. >> */ >>Tree * >>VerifyAmbig(alt1,alt2,ft,fs,t,u,numAmbig) >>Junction *alt1, *alt2; >>unsigned **ft; >>set *fs; /* set of possible ambiguities */ >>Tree **t, **u; /* return constrained perm sets */ >>int *numAmbig; /* how many ambigs were there */ >>{ >> set rk; >> Tree *perm, *ambig=NULL; >> int k; >> >> maxk = LL_k; /* NOTE: for now, we look for LL_k */ >> ftbl = ft; >> fset = fs; >> constrain = &(fset[1]); >> index = (int *) calloc(LL_k+1, sizeof(int)); >> if ( index == NULL ) >> { >> fprintf(stderr, ErrHdr, CurAmbigfile, CurAmbigline); >> fprintf(stderr, " out of memory while analyzing alts %d and %d of %s\n", >> CurAmbigAlt1, >> CurAmbigAlt2, >> CurAmbigbtype); >> exit(-1); >> } >> for (k=1; k<=LL_k; k++) index[k] = 0; >> >> rk = empty; >> ConstrainSearch = 1; /* consider only tokens in ambig sets */ >> >> TRAV(alt1->p1, LL_k, &rk, *t); >> *t = tshrink( *t ); >> *t = tflatten( *t ); >> *t = prune(*t, LL_k); >> *t = tleft_factor( *t ); >>/* fprintf(stderr, "after shrink&flatten&prune&left_factor:"); preorder(*t); fprintf(stderr, "\n");*/ >> if ( *t == NULL ) >> { >>/* fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/ >> Tfree( *t ); /* kill if impossible to have ambig */ >> *t = NULL; >> } >> >> TRAV(alt2->p1, LL_k, &rk, *u); >> *u = tshrink( *u ); >> *u = tflatten( *u ); >> *u = prune(*u, LL_k); >> *u = tleft_factor( *u ); >>/* fprintf(stderr, "after shrink&flatten&prune&lfactor:"); preorder(*u); fprintf(stderr, "\n");*/ >> if ( *u == NULL ) >> { >>/* fprintf(stderr, "TreeIncomplete --> no LL(%d) ambiguity\n", LL_k);*/ >> Tfree( *u ); >> *u = NULL; >> } >> >> for (k=1; k<=LL_k; k++) set_clr( fs[k] ); >> >> ambig = tnode(ALT); >> k = 0; >> if ( *t!=NULL && *u!=NULL ) >> { >> while ( (perm=permute(1))!=NULL ) >> { >>/* fprintf(stderr, "chk perm:"); preorder(perm); fprintf(stderr, "\n");*/ >> if ( tmember(perm, *t) && tmember(perm, *u) ) >> { >>/* fprintf(stderr, "ambig upon"); preorder(perm); fprintf(stderr, "\n");*/ >> k++; >> perm->right = ambig->down; >> ambig->down = perm; >> tcvt(&(fs[1]), perm); >> } >> else Tfree( perm ); >> } >> } >> >> *numAmbig = k; >> if ( ambig->down == NULL ) {tfree(ambig); ambig = NULL;} >> free( index ); >> /*fprintf(stderr, "final ambig:"); preorder(ambig); fprintf(stderr, "\n");*/ >> return ambig; >>} >EOF_fset2.c >cat << \EOF_fset.c | sed 's/^>//' > fset.c >>/* >> * fset.c >> * >> * Compute FIRST and FOLLOW sets. >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#include >>#include "set.h" >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#include "dlgdef.h" >> >>/* >> * What tokens are k tokens away from junction q? >> * >> * Follow both p1 and p2 paths (unless RuleBlk) to collect the tokens k away from this >> * node. >> * We lock the junction according to k--the lookahead. If we have been at this >> * junction before looking for the same, k, number of lookahead tokens, we will >> * do it again and again...until we blow up the stack. Locks are only used on aLoopBlk, >> * RuleBlk, aPlusBlk and EndRule junctions to remove/detect infinite recursion from >> * FIRST and FOLLOW calcs. >> * >> * If p->jtype == EndRule we are going to attempt a FOLLOW. (FOLLOWs are really defined >> * in terms of FIRST's, however). To proceed with the FOLLOW, p->halt cannot be >> * set. p->halt is set to indicate that a reference to the current rule is in progress >> * and the FOLLOW is not desirable. >> * >> * If we attempt a FOLLOW and find that there is no FOLLOW or REACHing beyond the EndRule >> * junction yields an empty set, replace the empty set with EOF. No FOLLOW means that >> * only EOF can follow the current rule. This normally occurs only on the start symbol >> * since all other rules are referenced by another rule somewhere. >> * >> * Normally, both p1 and p2 are followed. However, checking p2 on a RuleBlk node is >> * the same as checking the next rule which is clearly incorrect. >> * >> * Cycles in the FOLLOW sense are possible. e.g. Fo(c) requires Fo(b) which requires >> * Fo(c). Both Fo(b) and Fo(c) are defined to be Fo(b) union Fo(c). Let's say >> * Fo(c) is attempted first. It finds all of the FOLLOW symbols and then attempts >> * to do Fo(b) which finds of its FOLLOW symbols. So, we have: >> * >> * Fo(c) >> * / \ >> * a set Fo(b) >> * / \ >> * a set Fo(c) .....Hmmmm..... Infinite recursion! >> * >> * The 2nd Fo(c) is not attempted and Fo(b) is left deficient, but Fo(c) is now >> * correctly Fo(c) union Fo(b). We wish to pick up where we left off, so the fact >> * that Fo(b) terminated early means that we lack Fo(c) in the Fo(b) set already >> * laying around. SOOOOoooo, we track FOLLOW cycles. All FOLLOW computations are >> * cached in a hash table. After the sequence of FOLLOWs finish, we reconcile all >> * cycles --> correct all Fo(rule) sets in the cache. >> * >> * Confused? Good! Read my MS thesis [Purdue Technical Report TR90-30]. >> * >> * Also, FIRST sets are cached in the hash table. Keys are (rulename,Fi/Fo,k). >> * Only FIRST sets, for which the FOLLOW is not included, are stored. >> */ >>set >>rJunc(p,k,rk) >>Junction *p; >>int k; >>set *rk; >>{ >> set a, b; >> require(p!=NULL, "rJunc: NULL node"); >> require(p->ntype==nJunction, "rJunc: not junction"); >> >> /*if ( p->jtype == RuleBlk ) fprintf(stderr, "FIRST(%s,%d) \n",((Junction *)p)->rname,k); >> else fprintf(stderr, "rJunc: %s in rule %s\n", >> decodeJType[p->jtype], ((Junction *)p)->rname); >> */ >> /* locks are valid for aLoopBlk,aPlusBlk,RuleBlk,EndRule junctions only */ >> if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || >> p->jtype==aPlusBlk || p->jtype==EndRule ) >> { >> require(p->lock!=NULL, "rJunc: lock array is NULL"); >> if ( p->lock[k] ) >> { >> if ( p->jtype == EndRule ) /* FOLLOW cycle? */ >> { >> /*fprintf(stderr, "FOLLOW cycle to %s: panic!\n", p->rname);*/ >> RegisterCycle(p->rname, k); >> } >> return empty; >> } >> if ( p->jtype == RuleBlk && p->end->halt ) /* check for FIRST cache */ >> { >> CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'i',k)); >> if ( q != NULL ) >> { >> set_orin(rk, q->rk); >> return set_dup( q->fset ); >> } >> } >> if ( p->jtype == EndRule ) /* FOLLOW set cached already? */ >> { >> CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'o',k)); >> if ( q != NULL ) >> { >> /*fprintf(stderr, "<->FOLLOW(%s,%d):", p->rname,k); >> s_fprT(stderr, q->fset); >> if ( q->incomplete ) fprintf(stderr, " (incomplete)"); >> fprintf(stderr, "\n"); >> */ >> if ( !q->incomplete ) >> { >> return set_dup( q->fset ); >> } >> } >> } >> p->lock[k] = TRUE; /* This rule is busy */ >> } >> >> a = b = empty; >> >> if ( p->jtype == EndRule ) >> { >> if ( p->halt ) /* don't want FOLLOW here? */ >> { >> p->lock[k] = FALSE; >> set_orel(k, rk); /* indicate this k value needed */ >> return empty; >> } >> FoPush(p->rname, k); /* Attempting FOLLOW */ >> if ( p->p1 == NULL ) set_orel(EofToken, &a);/* if no FOLLOW assume EOF */ >> /*fprintf(stderr, "-->FOLLOW(%s,%d)\n", p->rname,k);*/ >> } >> >> if ( p->p1 != NULL ) REACH(p->p1, k, rk, a); >> >> /* C a c h e R e s u l t s */ >> if ( p->jtype == RuleBlk && p->end->halt ) /* can save FIRST set? */ >> { >> CacheEntry *q = newCacheEntry( Fkey(p->rname,'i',k) ); >> /*fprintf(stderr, "Caching %s FIRST %d\n", p->rname, k);*/ >> hash_add(Fcache, Fkey(p->rname,'i',k), (Entry *)q); >> q->fset = set_dup( a ); >> q->rk = set_dup( *rk ); >> } >> >> if ( p->jtype == EndRule ) /* just completed FOLLOW? */ >> { >> /* Cache Follow set */ >> CacheEntry *q = (CacheEntry *) hash_get(Fcache, Fkey(p->rname,'o',k)); >> if ( q==NULL ) >> { >> q = newCacheEntry( Fkey(p->rname,'o',k) ); >> hash_add(Fcache, Fkey(p->rname,'o',k), (Entry *)q); >> } >> /*fprintf(stderr, "Caching %s FOLLOW %d\n", p->rname, k);*/ >> set_orin(&(q->fset), a); >> FoPop( k ); >> if ( FoTOS[k] == NULL && Cycles[k] != NULL ) ResolveFoCycles(k); >> /* >> fprintf(stderr, "<--FOLLOW(%s,%d):", p->rname, k); >> s_fprT(stderr, q->fset); >> if ( q->incomplete ) fprintf(stderr, " (incomplete)"); >> fprintf(stderr, "\n"); >> */ >> } >> >> if ( p->jtype != RuleBlk && p->p2 != NULL ) REACH(p->p2, k, rk, b); >> if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || >> p->jtype==aPlusBlk || p->jtype==EndRule ) >> p->lock[k] = FALSE; /* unlock node */ >> >> set_orin(&a, b); >> set_free(b); >> return a; >>} >> >>set >>rRuleRef(p,k,rk_out) >>RuleRefNode *p; >>int k; >>set *rk_out; >>{ >> set rk; >> Junction *r; >> int k2; >> set a, rk2, b; >> int save_halt; >> RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text); >> require(p!=NULL, "rRuleRef: NULL node"); >> require(p->ntype==nRuleRef, "rRuleRef: not rule ref"); >> >> /*fprintf(stderr, "rRuleRef: %s\n", p->text);*/ >> if ( q == NULL ) >> { >> warnNoFL( eMsg1("rule %s not defined",p->text) ); >> REACH(p->next, k, rk_out, a); >> return a; >> } >> rk2 = empty; >> r = RulePtr[q->rulenum]; >> if ( r->lock[k] ) >> { >> warnNoFL( eMsg2("infinite left-recursion to rule %s from rule %s", >> r->rname, p->rname) ); >> return empty; >> } >> save_halt = r->end->halt; >> r->end->halt = TRUE; /* don't let reach fall off end of rule here */ >> rk = empty; >> REACH(r, k, &rk, a); >> r->end->halt = save_halt; >> while ( !set_nil(rk) ) { >> k2 = set_int(rk); >> set_rm(k2, rk); >> REACH(p->next, k2, &rk2, b); >> set_orin(&a, b); >> set_free(b); >> } >> set_orin(rk_out, rk2); /* remember what we couldn't do */ >> set_free(rk2); >> return a; >>} >> >>set >>rToken(p,k,rk) >>TokNode *p; >>int k; >>set *rk; >>{ >> set a; >> require(p!=NULL, "rToken: NULL node"); >> require(p->ntype==nToken, "rToken: not token node"); >> >> /*fprintf(stderr, "rToken: %s\n", (TokenStr[p->token]!=NULL)?TokenStr[p->token]: >> ExprStr[p->token]);*/ >> if ( k-1 == 0 ) return set_of( p->token ); >> REACH(p->next, k-1, rk, a); >> >> return a; >>} >> >>set >>rAction(p,k,rk) >>ActionNode *p; >>int k; >>set *rk; >>{ >> set a; >> require(p!=NULL, "rJunc: NULL node"); >> require(p->ntype==nAction, "rJunc: not action"); >> >> REACH(p->next, k, rk, a); /* ignore actions */ >> return a; >>} >> >> /* A m b i g u i t y R e s o l u t i o n */ >> >> >>static void >>dumpAmbigMsg(fset) >>set *fset; >>{ >> int i; >> >> fprintf(stderr, " "); >> for (i=1; i<=LL_k; i++) >> { >> if ( i>1 ) fprintf(stderr, ", "); >> if ( set_deg(fset[i]) > 3 && elevel == 1 ) >> { >> int e,m; >> fprintf(stderr, "{"); >> for (m=1; m<=3; m++) >> { >> e=set_int(fset[i]); >> fprintf(stderr, " %s", TerminalString(e)); >> set_rm(e, fset[i]); >> } >> fprintf(stderr, " ... }"); >> } >> else s_fprT(stderr, fset[i]); >> } >> fprintf(stderr, "\n"); >> for (i=1; i<=LL_k; i++) set_free( fset[i] ); >> free(fset); >>} >> >>void >>HandleAmbiguity(alt1,alt2,jtype) >>Junction *alt1, *alt2; >>int jtype; >>{ >> unsigned **ftbl; >> set *fset, b; >> int i, numAmbig, n, n2; >> Tree *ambig, *t, *u; >> char *sub = ""; >> >> fset = (set *) calloc(LL_k+1, sizeof(set)); >> require(fset!=NULL, "cannot allocate fset"); >> ftbl = (unsigned **) calloc(LL_k+1, sizeof(unsigned *)); >> require(ftbl!=NULL, "cannot allocate ftbl"); >> /* create constraint table and count number of possible ambiguities */ >> for (n=1,i=1; i<=LL_k; i++) >> { >> b = set_and(alt1->fset[i], alt2->fset[i]); >> n *= set_deg(b); >> fset[i] = set_dup(b); >> ftbl[i] = set_pdq(b); >> set_free(b); >> } >> >> switch ( jtype ) >> { >> case aSubBlk: sub = "of (..) "; break; >> case aOptBlk: sub = "of {..} "; break; >> case aLoopBegin: sub = "of (..)* "; break; >> case aLoopBlk: sub = "of (..)* "; break; >> case aPlusBlk: sub = "of (..)+ "; break; >> case RuleBlk: sub = "of rule "; break; >> default : sub = ""; break; >> } >> >> /* if all sets have degree 1 for k> n2 = 0; >> for (i=1; ifset[i])+set_deg(alt2->fset[i]); >> if ( n2==2*(LL_k-1) ) >> { >> /* C O D E F O R P R E D I C A T E S (ambiguous--check for predicates) */ >> if ( ParseWithPredicates ) >> { >> alt1->predicate = find_predicates((Node *)alt1->p1); >> alt2->predicate = find_predicates((Node *)alt2->p1); >> } >> >> fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); >> if ( jtype == aLoopBegin ) >> fprintf(stderr, " warning: optional path and alt(s) of (..)* ambiguous upon"); >> else >> fprintf(stderr, " warning: alts %d and %d %sambiguous upon", >> alt1->altnum, alt2->altnum, sub); >> dumpAmbigMsg(fset); >> for (i=1; i<=LL_k; i++) free( ftbl[i] ); >> free(ftbl); >> return; >> } >> >> /* in case tree construction runs out of memory, set info to make good err msg */ >> CurAmbigAlt1 = alt1->altnum; >> CurAmbigAlt2 = alt2->altnum; >> CurAmbigbtype = sub; >> CurAmbigfile = alt1->file; >> CurAmbigline = alt1->line; >> >> ambig = VerifyAmbig(alt1, alt2, ftbl, fset, &t, &u, &numAmbig); >> for (i=1; i<=LL_k; i++) free( ftbl[i] ); >> free(ftbl); >> >> /* are all things in intersection really ambigs? */ >> if ( numAmbig < n ) >> { >> Tree *v; >> >> /* remove ambig permutation from 2nd alternative to resolve ambig */ >> if ( ambig!=NULL ) >> { >> for (v=ambig->down; v!=NULL; v=v->right) >> { >> u = trm_perm(u, v); >> } >> /*fprintf(stderr, "after rm alt2:"); preorder(u); fprintf(stderr, "\n");*/ >> } >> Tfree( t ); >> alt1->ftree = tappend(alt1->ftree, u); >> alt1->ftree = tleft_factor(alt1->ftree); >> } >> >> if ( ambig==NULL ) >> { >> for (i=1; i<=LL_k; i++) set_free( fset[i] ); >> free(fset); >> return; >> } >> >> /* C O D E F O R P R E D I C A T E S (ambiguous k>1 --check for predicates) */ >> if ( ParseWithPredicates ) >> { >> alt1->predicate = find_predicates((Node *)alt1->p1); >> alt2->predicate = find_predicates((Node *)alt2->p1); >> } >> >> ambig = tleft_factor(ambig); >> >> fprintf(stderr, ErrHdr, FileStr[alt1->file], alt1->line); >> if ( jtype == aLoopBegin ) >> fprintf(stderr, " warning: optional path and alt(s) of (..)* ambiguous upon"); >> else >> fprintf(stderr, " warning: alts %d and %d %sambiguous upon", >> alt1->altnum, alt2->altnum, sub); >> if ( elevel == 3 ) >> { >> preorder(ambig->down); >> fprintf(stderr, "\n"); >> Tfree(ambig); >> return; >> } >> Tfree(ambig); >> dumpAmbigMsg(fset); >>} >> >>set >>First(j,k,jtype,max_k) >>Junction *j; >>int k, jtype; >>int *max_k; >>{ >> Junction *alt1, *alt2; >> set a, rk, fCurBlk; >> int savek; >> require(j->ntype==nJunction, "First: non junction passed"); >> >> /* C o m p u t e F I R S T s e t w i t h k l o o k a h e a d */ >> fCurBlk = rk = empty; >> for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2) >> { >> REACH(alt1->p1, k, &rk, alt1->fset[k]); >> require(set_nil(rk), "rk != nil"); >> set_orin(&fCurBlk, alt1->fset[k]); >> } >> >> /* D e t e c t A m b i g u i t i e s */ >> *max_k = 1; >> for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2) >> { >> for (alt2=(Junction *)alt1->p2; alt2!=NULL; alt2 = (Junction *)alt2->p2) >> { >> savek = k; >> a = set_and(alt1->fset[k], alt2->fset[k]); >> while ( !set_nil(a) ) >> { >> if ( k==LL_k ) >> { >> *max_k = LL_k; >> HandleAmbiguity(alt1, alt2, jtype); >> break; >> } >> else >> { >> k++; /* attempt ambig alts again with more lookahead */ >> REACH(alt1->p1, k, &rk, alt1->fset[k]); >> require(set_nil(rk), "rk != nil"); >> REACH(alt2->p1, k, &rk, alt2->fset[k]); >> require(set_nil(rk), "rk != nil"); >> set_free(a); >> a = set_and(alt1->fset[k], alt2->fset[k]); >> if ( k > *max_k ) *max_k = k; >> } >> } >> set_free(a); >> k = savek; >> } >> } >> >> return fCurBlk; >>} >EOF_fset.c >cat << \EOF_gen.c | sed 's/^>//' > gen.c >>/* >> * gen.c >> * >> * Generate C code (ANSI or K&R) >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#include >>#include >>#include "set.h" >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#include "dlgdef.h" >> >> /* T r a n s l a t i o n T a b l e s */ >> >>/* C_Trans[node type] == pointer to function that knows how to translate that node. */ >>void (*C_Trans[NumNodeTypes+1])() = { >> NULL, >> NULL, /* See next table. Junctions have many types */ >> genRuleRef, >> genToken, >> genAction >>}; >> >>/* C_JTrans[Junction type] == pointer to function that knows how to translate that >> * kind of junction node. >> */ >>void (*C_JTrans[NumJuncTypes+1])() = { >> NULL, >> genSubBlk, >> genOptBlk, >> genLoopBlk, >> genEndBlk, >> genRule, >> genJunction, >> genEndRule, >> genPlusBlk, >> genLoopBegin >>}; >> >>#define PastWhiteSpace(s) while (*(s) == ' ' || *(s) == '\t' || *(s) == '\n') {s++;} >> >>static int tabs = 0; >>#define TAB { int i; for (i=0; i>static void tab() TAB >> >>#ifdef __STDC__ >>static ActionNode *findImmedAction( Node * ); >>static void dumpRetValAssign(char *, char *); >>static dumpAfterActions(FILE *output); >>static set ComputeErrorSet(Junction *, int); >>static void makeErrorClause(Junction *, set, int); >>static void DumpFuncHeader( Junction *, RuleEntry * ); >>#else >>static ActionNode *findImmedAction(); >>static void dumpRetValAssign(); >>static dumpAfterActions(); >>static set ComputeErrorSet(); >>static void makeErrorClause(); >>static void DumpFuncHeader(); >>#endif >> >>#define gen(s) {tab(); fprintf(output, s);} >>#define gen1(s,a) {tab(); fprintf(output, s,a);} >>#define gen2(s,a,b) {tab(); fprintf(output, s,a,b);} >>#define gen3(s,a,b,c) {tab(); fprintf(output, s,a,b,c);} >>#define gen4(s,a,b,c,d) {tab(); fprintf(output, s,a,b,c,d);} >>#define gen5(s,a,b,c,d,e) {tab(); fprintf(output, s,a,b,c,d,e);} >>#define gen6(s,a,b,c,d,e,f) {tab(); fprintf(output, s,a,b,c,d,e,f);} >> >>#define _gen(s) {fprintf(output, s);} >>#define _gen1(s,a) {fprintf(output, s,a);} >>#define _gen2(s,a,b) {fprintf(output, s,a,b);} >>#define _gen3(s,a,b,c) {fprintf(output, s,a,b,c);} >>#define _gen4(s,a,b,c,d){fprintf(output, s,a,b,c,d);} >>#define _gen5(s,a,b,c,d,e){fprintf(output, s,a,b,c,d,e);} >> >>void >>freeBlkFsets(q) >>Junction *q; >>{ >> int i; >> Junction *alt; >> require(q!=NULL, "freeBlkFsets: invalid node"); >> >> for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) >> { >> for (i=1; i<=LL_k; i++) set_free(alt->fset[i]); >> } >>} >> >>static void >>BLOCK_Head() >>{ >> gen("{\n"); >> tabs++; >> gen1("zzBLOCK(zztasp%d);\n", BlkLevel); >>} >> >>static void >>BLOCK_Tail() >>{ >> gen1("zzEXIT(zztasp%d);\n", BlkLevel); >> gen("}\n"); >> tabs--; >> gen("}\n"); >>} >> >>static void >>BLOCK_Preamble(q) >>Junction *q; >>{ >> ActionNode *a; >> >> BLOCK_Head(); >> if ( q->jtype == aPlusBlk ) gen("int zzcnt=1;\n"); >> if ( q->parm != NULL ) gen1("zzaPush(%s);\n", q->parm) >> else gen("zzMake0;\n"); >> gen("{\n"); >> if ( q->jtype == aLoopBegin ) >> a = findImmedAction( ((Junction *)q->p1)->p1 ); /* look at aLoopBlk */ >> else >> a = findImmedAction( q->p1 ); >> if ( a!=NULL && !a->is_predicate ) { >> dumpAction(a->action, output, tabs, a->file, a->line, 1); >> a->done = 1; /* remove action. We have already handled it */ >> } >>} >> >>static void >>genExprTree(t,k) >>Tree *t; >>int k; >>{ >> require(t!=NULL, "genExprTree: NULL tree"); >> >> if ( t->token == ALT ) >> { >> _gen("("); genExprTree(t->down, k); _gen(")"); >> if ( t->right!=NULL ) >> { >> _gen("||"); >> _gen("("); genExprTree(t->right, k); _gen(")"); >> } >> return; >> } >> if ( t->down!=NULL ) _gen("("); >> _gen1("LA(%d)==",k); >> if ( TokenStr[t->token] == NULL ) _gen1("%d", t->token) >> else _gen1("%s", TokenStr[t->token]); >> if ( t->down!=NULL ) >> { >> _gen("&&"); >> _gen("("); genExprTree(t->down, k+1); _gen(")"); >> } >> if ( t->down!=NULL ) _gen(")"); >> if ( t->right!=NULL ) >> { >> _gen("||"); >> _gen("("); genExprTree(t->right, k); _gen(")"); >> } >>} >> >>/* >> * Generate LL(k) type expressions of the form: >> * >> * (LA(1) == T1 || LA(1) == T2 || ... || LA(1) == Tn) && >> * (LA(2) == T1 || LA(2) == T2 || ... || LA(2) == Tn) && >> * ..... >> * (LA(k) == T1 || LA(k) == T2 || ... || LA(k) == Tn) >> * >> * If GenExprSets generate: >> * >> * (setwdi[LA(1)]&(1<> * >> * where n is set_deg(expr) and Ti is some random token and k is the last nonempty >> * set in fset. >> * k=1..LL_k where LL_k >= 1. >> * This routine is visible only to this file and cannot answer a TRANS message. >> * >> * TJP Oct '92: If predicates are allowed in parsing expressions: >> * >> * ( <>? production 1 >> * | production 2 >> * ... >> * | production n >> * ) >> * >> * Generates: >> * >> * if ( pred && (production 1 prediction) ) { >> * ... >> * } >> * else if ( production 2 prediction ) { >> * ... >> * } >> * ... >> */ >>static int >>genExpr(j) >>Junction *j; >>{ >> int k = 1; >> int max_k = 0; >> unsigned *e, *g, firstTime=1; >> set *fset = j->fset; >> >> if ( ParseWithPredicates && j->predicate.expr!=NULL ) >> { >> _gen("(("); >> dumpAction(j->predicate.expr, output, 0, j->file, j->line, 0); >> _gen(") && ("); >>#ifdef COMPUTE_CONTEXT >> require(j->predicate.context!=NULL, "no context for predicate"); >> genExprTree(j->predicate.context, 1); >>#else >> _gen("1"); >>#endif >> _gen(")) && ("); >> } >> if ( GenExprSets ) >> { >> while ( !set_nil(fset[k]) ) >> { >> if ( set_deg(fset[k])==1 ) /* too simple for a set? */ >> { >> int e; >> _gen1("(LA(%d)==",k); >> e = set_int(fset[k]); >> if ( TokenStr[e] == NULL ) _gen1("%d)", e) >> else _gen1("%s)", TokenStr[e]); >> } >> else >> { >> NewSet(); >> FillSet( fset[k] ); >> _gen3("(setwd%d[LA(%d)]&0x%x)", wordnum, k, 1<> } >> if ( k>max_k ) max_k = k; >> if ( k == LL_k ) break; >> k++; >> if ( !set_nil(fset[k]) ) _gen(" && "); >> } >> if ( j->ftree != NULL ) >> { >> /*fprintf(stderr, "genExpr ftree:"); preorder(j->ftree); fprintf(stderr, "\n"); >> */ >> _gen(" && !("); genExprTree(j->ftree, 1); _gen(")"); >> } >> if ( ParseWithPredicates && j->predicate.expr!=NULL ) _gen(")"); >> return max_k; >> } >> >> while ( !set_nil(fset[k]) ) >> { >> if ( (e=g=set_pdq(fset[k])) == NULL ) fatal("genExpr: cannot allocate IF expr pdq set"); >> for (; *e!=nil; e++) >> { >> if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; } >> _gen1("LA(%d)==",k); >> if ( TokenStr[*e] == NULL ) _gen1("%d", *e) >> else _gen1("%s", TokenStr[*e]); >> } >> free( g ); >> _gen(")"); >> if ( k>max_k ) max_k = k; >> if ( k == LL_k ) break; >> k++; >> if ( !set_nil(fset[k]) ) { firstTime=1; _gen(" && "); } >> } >> if ( j->ftree != NULL ) >> { >>/* fprintf(stderr, "genExpr ftree:"); preorder(j->ftree); fprintf(stderr, "\n"); >> */ >> _gen(" && !("); genExprTree(j->ftree, 1); _gen(")"); >> } >> if ( ParseWithPredicates && j->predicate.expr!=NULL ) _gen(")"); >> return max_k; >>} >> >>/* >> * Generate code for any type of block. If the last alternative in the block is >> * empty (not even an action) don't bother doing it. This permits us to handle >> * optional and loop blocks as well. >> * >> * Only do this block, return after completing the block. >> * This routine is visible only to this file and cannot answer a TRANS message. >> */ >>static set >>genBlk(q,jtype,max_k) >>Junction *q; >>int jtype, *max_k; >>{ >> set f; >> Junction *alt; >> require(q!=NULL, "genBlk: invalid node"); >> require(q->ntype == nJunction, "genBlk: not junction"); >> >> if ( q->p2 == NULL ) /* only one alternative? Then don't need if */ >> { >> TRANS(q->p1); >> return empty; /* no decision to be made-->no error set */ >> } >> f = First(q, 1, jtype, max_k); >> for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) >> { >> if ( alt->p2 == NULL ) /* chk for empty alt */ >> { >> Node *p = alt->p1; >> if ( p->ntype == nJunction ) >> { >> /* we have empty alt */ >> if ( ((Junction *)p)->p1 == (Node *)q->end ) >> { >> break; /* don't do this one, quit */ >> } >> } >> } >> if ( alt != q ) gen("else ") >> else >> { >> if ( DemandLookahead ) gen1("LOOK(%d);\n", *max_k); >> tab(); >> } >> _gen("if ( "); >> genExpr(alt); >> _gen(" ) "); >> _gen("{\n"); >> tabs++; >> TRANS(alt->p1); >> --tabs; >> gen("}\n"); >> } >> return f; >>} >> >>/* Generate an action. Don't if action is NULL which means that it was already >> * handled as an init action. >> */ >>void >>genAction(p) >>ActionNode *p; >>{ >> require(p!=NULL, "genAction: invalid node and/or rule"); >> require(p->ntype==nAction, "genAction: not action"); >> >> if ( !p->done ) >> { >> if ( p->is_predicate ) >> { >> gen("if (!("); >> dumpAction(p->action, output, 0, p->file, p->line, 0); >> if ( p->pred_fail != NULL ) {_gen1(")) {{%s}; exit(-1);}\n", p->pred_fail);} >> else _gen1(")) {fprintf(stderr, \"semantic error; failed predicate: '%s'\\n\"); exit(-1);}\n",p->action); >> } >> else >> { >> dumpAction(p->action, output, tabs, p->file, p->line, 1); >> } >> p->done = 1; >> } >> TRANS(p->next) >>} >> >>/* >> * if invoking rule has !noAST pass zzSTR to rule ref and zzlink it in >> * else pass addr of temp root ptr (&_ast) (don't zzlink it in). >> * >> * if ! modifies rule-ref, then never link it in and never pass zzSTR. >> * Always pass address of temp root ptr. >> */ >>void >>genRuleRef(p) >>RuleRefNode *p; >>{ >> Junction *q; >> RuleEntry *r, *r2; >> char *parm = ""; >> require(p!=NULL, "genRuleRef: invalid node and/or rule"); >> require(p->ntype==nRuleRef, "genRuleRef: not rule reference"); >> >> r = (RuleEntry *) hash_get(Rname, p->text); >> if ( r == NULL ) {warnNoFL( eMsg1("rule %s not defined", p->text) ); return;} >> r2 = (RuleEntry *) hash_get(Rname, p->rname); >> if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;} >> >> tab(); >> if ( GenAST ) >> { >> if ( r2->noAST || p->astnode==ASTexclude ) >> { >> _gen("_ast = NULL; "); >> parm = "&_ast"; >> } >> else parm = "zzSTR"; >> if ( p->assign!=NULL ) >> { >> if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);} >> else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum); >> } >> _gen5("%s%s(%s%s%s);", RulePrefix, >> p->text, >> parm, >> (p->parms!=NULL)?",":"", >> (p->parms!=NULL)?p->parms:""); >> if ( !r2->noAST && p->astnode == ASTinclude ) >> { >> _gen(" zzlink(_root, &_sibling, &_tail);"); >> } >> } >> else >> { >> if ( p->assign!=NULL ) >> { >> if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);} >> else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum); >> } >> _gen2("%s(%s);", p->text, (p->parms!=NULL)?p->parms:""); >> } >> q = RulePtr[r->rulenum]; /* find definition of ref'd rule */ >> if ( p->assign!=NULL ) >> if ( HasComma(p->assign) ) >> { >> dumpRetValAssign(p->assign, q->ret); >> _gen("}"); >> } >> _gen("\n"); >> TRANS(p->next) >>} >> >>/* >> * Generate code to match a token. >> * >> * Getting the next token is tricky. We want to ensure that any action >> * following a token is executed before the next GetToken(); >> */ >>void >>genToken(p) >>TokNode *p; >>{ >> RuleEntry *r; >> ActionNode *a; >> require(p!=NULL, "genToken: invalid node and/or rule"); >> require(p->ntype==nToken, "genToken: not token"); >> >> r = (RuleEntry *) hash_get(Rname, p->rname); >> if ( r == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;} >> if ( TokenStr[p->token]!=NULL ) gen1("zzmatch(%s);", TokenStr[p->token]) >> else gen1("zzmatch(%d);", p->token); >> a = findImmedAction( p->next ); >> if ( GenAST ) >> { >> if ( !r->noAST ) >> { >> if ( p->astnode==ASTchild ) >> {_gen(" zzsubchild(_root, &_sibling, &_tail);");} >> else if ( p->astnode==ASTroot ) >> {_gen(" zzsubroot(_root, &_sibling, &_tail);");} >> else >> {_gen(" zzastDPush;");} >> } >> else _gen(" zzastDPush;"); >> } >> if ( a != NULL ) >> { >> /* delay next token fetch until after action */ >> _gen("\n"); >> if ( a->is_predicate ) >> { >> gen("if (!("); >> dumpAction(a->action, output, 0, a->file, a->line, 0); >> _gen1(")) {fprintf(stderr, \"failed predicate: '%s'\n\"); exit(-1);}\n",a->action); >> } >> else >> { >> dumpAction(a->action, output, tabs, a->file, a->line, 1); >> } >> a->done = 1; >> if ( !DemandLookahead ) {gen(" zzCONSUME;\n");} >> else gen("\n"); >> TRANS( a->next ); >> } >> else >> { >> if ( !DemandLookahead ) {_gen(" zzCONSUME;\n");} >> else gen("\n"); >> TRANS(p->next); >> } >>} >> >>void >>genOptBlk(q) >>Junction *q; >>{ >> int max_k; >> set f; >> require(q!=NULL, "genOptBlk: invalid node and/or rule"); >> require(q->ntype == nJunction, "genOptBlk: not junction"); >> require(q->jtype == aOptBlk, "genOptBlk: not optional block"); >> >> BLOCK_Preamble(q); >> BlkLevel++; >> f = genBlk(q, aOptBlk, &max_k); >> set_free(f); >> freeBlkFsets(q); >> BlkLevel--; >> BLOCK_Tail(); >> if (q->end->p1 != NULL) TRANS(q->end->p1); >>} >> >>/* >> * Generate code for a loop blk of form: >> * >> * |---| >> * v | >> * --o-G-o-->o-- >> */ >>void >>genLoopBlk(q,begin,max_k) >>Junction *q, *begin; >>int max_k; >>{ >> int dum_k; >> set f; >> require(q->ntype == nJunction, "genLoopBlk: not junction"); >> require(q->jtype == aLoopBlk, "genLoopBlk: not loop block"); >> >> if ( q->visited ) return; >> q->visited = TRUE; >> if ( q->p2 == NULL ) /* only one alternative? */ >> { >> f = First(q, 1, aLoopBlk, &dum_k); >> if ( DemandLookahead ) gen1("LOOK(%d);\n", max_k); >> gen("while ( "); >> if ( begin!=NULL ) >> { >> genExpr(begin); >> } >> else genExpr(q); >> _gen(" ) {\n"); >> tabs++; >> TRANS(q->p1); >> gen1("zzLOOP(zztasp%d);\n", BlkLevel-1); >> if ( DemandLookahead ) gen1("LOOK(%d);\n", max_k); >> --tabs; >> gen("}\n"); >> freeBlkFsets(q); >> set_free(f); >> q->visited = FALSE; >> return; >> } >> gen("while ( 1 ) {\n"); >> tabs++; >> if ( begin!=NULL ) >> { >> if ( DemandLookahead ) gen1("LOOK(%d);\n",max_k); >> gen("if ( "); >> genExpr((Junction *)begin->p2); >> _gen(" ) break;\n"); >> } >> f = genBlk(q, aLoopBlk, &max_k); >> set_free(f); >> freeBlkFsets(q); >> if ( begin==NULL ) gen("else break;\n"); /* code for exiting loop */ >> gen1("zzLOOP(zztasp%d);\n", BlkLevel-1); >> --tabs; >> gen("}\n"); >> q->visited = FALSE; >>} >> >>/* >> * Generate code for a loop blk of form: >> * >> * |---| >> * v | >> * --o-->o-->o-G-o-->o-- >> * | ^ >> * v | >> * o-----------o >> * >> * q->end points to the last node (far right) in the blk. Note that q->end->jtype >> * must be 'EndBlk'. >> * >> * Generate code roughly of the following form: >> * >> * do { >> * ... code for alternatives ... >> * } while ( First Set of aLoopBlk ); >> * >> * OR if > 1 alternative >> * >> * do { >> * ... code for alternatives ... >> * else break; >> * } while ( 1 ); >> */ >>void >>genLoopBegin(q) >>Junction *q; >>{ >> set f; >> int i; >> int max_k; >> require(q!=NULL, "genLoopBegin: invalid node and/or rule"); >> require(q->ntype == nJunction, "genLoopBegin: not junction"); >> require(q->jtype == aLoopBegin, "genLoopBegin: not loop block"); >> require(q->p2!=NULL, "genLoopBegin: invalid Loop Graph"); >> >> BLOCK_Preamble(q); >> BlkLevel++; >> f = First(q, 1, aLoopBegin, &max_k); >> if ( LL_k>1 ) >> { >> if ( !set_nil(q->fset[2]) ) genLoopBlk( (Junction *)q->p1, q, max_k ); >> else genLoopBlk( (Junction *)q->p1, NULL, max_k ); >> } >> else genLoopBlk( (Junction *)q->p1, NULL, max_k ); >> for (i=1; i<=LL_k; i++) set_free(q->fset[i]); >> for (i=1; i<=LL_k; i++) set_free(((Junction *)q->p2)->fset[i]); >> --BlkLevel; >> BLOCK_Tail(); >> set_free(f); >> if (q->end->p1 != NULL) TRANS(q->end->p1); >>} >> >>/* >> * Generate code for a loop blk of form: >> * >> * |---| >> * v | >> * --o-G-o-->o-- >> * >> * q->end points to the last node (far right) in the blk. Note that q->end->jtype >> * must be 'EndBlk'. >> * >> * Generate code roughly of the following form: >> * >> * do { >> * ... code for alternatives ... >> * } while ( First Set of aPlusBlk ); >> * >> * OR if > 1 alternative >> * >> * do { >> * ... code for alternatives ... >> * else if not 1st time through, break; >> * } while ( 1 ); >> */ >>void >>genPlusBlk(q) >>Junction *q; >>{ >> int max_k; >> set f; >> require(q!=NULL, "genPlusBlk: invalid node and/or rule"); >> require(q->ntype == nJunction, "genPlusBlk: not junction"); >> require(q->jtype == aPlusBlk, "genPlusBlk: not Plus block"); >> >> if ( q->visited ) return; >> q->visited = TRUE; >> BLOCK_Preamble(q); >> BlkLevel++; >> if ( q->p2 == NULL ) /* only one alternative? */ >> { >> gen("do {\n"); >> tabs++; >> TRANS(q->p1); >> gen1("zzLOOP(zztasp%d);\n", BlkLevel-1); >> f = First(q, 1, aPlusBlk, &max_k); >> if ( DemandLookahead ) gen1("LOOK(%d);\n", max_k); >> --tabs; >> gen("} while ( "); >> genExpr(q); >> _gen(" );\n"); >> --BlkLevel; >> BLOCK_Tail(); >> q->visited = FALSE; >> freeBlkFsets(q); >> set_free(f); >> if (q->end->p1 != NULL) TRANS(q->end->p1); >> return; >> } >> gen("do {\n"); >> tabs++; >> f = genBlk(q, aPlusBlk, &max_k); >> gen("else if ( zzcnt>1 ) break; ");/* code for exiting loop */ >> makeErrorClause(q,f,max_k); >> freeBlkFsets(q); >> gen1("zzcnt++; zzLOOP(zztasp%d);\n", BlkLevel-1); >> if ( DemandLookahead ) gen1("LOOK(%d);\n", max_k); >> --tabs; >> gen("} while ( 1 );\n"); >> --BlkLevel; >> BLOCK_Tail(); >> q->visited = FALSE; >> if (q->end->p1 != NULL) TRANS(q->end->p1); >>} >> >>/* >> * Generate code for a sub blk of alternatives of form: >> * >> * --o-G1--o-- >> * | ^ >> * v /| >> * o-G2-o| >> * | ^ >> * v | >> * .......... >> * | ^ >> * v / >> * o-Gn-o >> * >> * q points to the 1st junction of blk (upper-left). >> * q->end points to the last node (far right) in the blk. Note that q->end->jtype >> * must be 'EndBlk'. >> * The last node in every alt points to q->end. >> * >> * Generate code of the following form: >> * if ( First(G1) ) { >> * ...code for G1... >> * } >> * else if ( First(G2) ) { >> * ...code for G2... >> * } >> * ... >> * else { >> * ...code for Gn... >> * } >> */ >>void >>genSubBlk(q) >>Junction *q; >>{ >> int max_k; >> set f; >> require(q->ntype == nJunction, "genSubBlk: not junction"); >> require(q->jtype == aSubBlk, "genSubBlk: not subblock"); >> >> BLOCK_Preamble(q); >> BlkLevel++; >> f = genBlk(q, aSubBlk, &max_k); >> if ( q->p2 != NULL ) {tab(); makeErrorClause(q,f,max_k);} >> freeBlkFsets(q); >> --BlkLevel; >> BLOCK_Tail(); >> if (q->end->p1 != NULL) TRANS(q->end->p1); >>} >> >>/* >> * Generate code for a rule. >> * >> * rule--> o-->o-Alternatives-o-->o >> * Or, >> * rule--> o-->o-Alternative-o-->o >> * >> * The 1st junction is a RuleBlk. The second can be a SubBlk or just a junction >> * (one alternative--no block), the last is EndRule. >> * The second to last is EndBlk if more than one alternative exists in the rule. >> * >> * To get to the init-action for a rule, we must bypass the RuleBlk, >> * and possible SubBlk. >> * Mark any init-action as generated so genBlk() does not regenerate it. >> */ >>void >>genRule(q) >>Junction *q; >>{ >> int max_k; >> set follow, rk, f; >> ActionNode *a; >> RuleEntry *r; >> static int file = -1; >> require(q->ntype == nJunction, "genRule: not junction"); >> require(q->jtype == RuleBlk, "genRule: not rule"); >> >> r = (RuleEntry *) hash_get(Rname, q->rname); >> if ( r == NULL ) warnNoFL("Rule hash table is screwed up beyond belief"); >> if ( q->file != file ) /* open new output file if need to */ >> { >> if ( output != NULL ) fclose( output ); >> output = fopen(outname(FileStr[q->file]), "w"); >> require(output != NULL, "genRule: can't open output file"); >> if ( file == -1 ) genHdr1(q->file); >> else genHdr(q->file); >> file = q->file; >> } >> DumpFuncHeader(q,r); >> tabs++; >> if ( q->ret!=NULL ) >> { >> if ( HasComma(q->ret) ) {gen1("struct _rv%d _retv;\n",r->rulenum);} >> else >> { >> tab(); >> DumpType(q->ret, output); >> gen(" _retv;\n"); >> } >> } >> gen("zzRULE;\n"); >> gen1("zzBLOCK(zztasp%d);\n", BlkLevel); >> gen("zzMake0;\n"); >> gen("{\n"); >> >> /* L o o k F o r I n i t A c t i o n */ >> if ( ((Junction *)q->p1)->jtype == aSubBlk ) >> a = findImmedAction( ((Junction *)q->p1)->p1 ); >> else >> a = findImmedAction( q->p1 ); /* only one alternative in rule */ >> if ( a!=NULL && !a->is_predicate ) >> { >> dumpAction(a->action, output, tabs, a->file, a->line, 1); >> a->done = 1; /* ignore action. We have already handled it */ >> } >> if ( TraceGen ) gen1("zzTRACEIN(\"%s\");\n", q->rname); >> >> BlkLevel++; >> q->visited = TRUE; /* mark RULE as visited for FIRST/FOLLOW */ >> f = genBlk((Junction *)q->p1, RuleBlk, &max_k); >> if ( q->p1 != NULL ) >> if ( ((Junction *)q->p1)->p2 != NULL ) >> {tab(); makeErrorClause((Junction *)q->p1,f,max_k);} >> freeBlkFsets((Junction *)q->p1); >> q->visited = FALSE; >> --BlkLevel; >> gen1("zzEXIT(zztasp%d);\n", BlkLevel); >> >> if ( TraceGen ) gen1("zzTRACEOUT(\"%s\");\n", q->rname); >> >> if ( q->ret!=NULL ) gen("return _retv;\n") else gen("return;\n"); >> /* E r r o r R e c o v e r y */ >> NewSet(); >> rk = empty; >> REACH(q->end, 1, &rk, follow); >> FillSet( follow ); >> set_free( follow ); >> _gen("fail:\n"); >> gen("zzEXIT(zztasp1);\n"); >> if ( q->erraction!=NULL ) >> dumpAction(q->erraction, output, tabs, q->file, q->line, 1); >> gen1("zzsyn(zzMissText, zzBadTok, %s, zzMissSet, zzMissTok, zzErrk, zzBadText);\n", r->egroup==NULL?"\"\"":r->egroup); >> gen2("zzresynch(setwd%d, 0x%x);\n", wordnum, 1<> >> if ( TraceGen ) gen1("zzTRACEOUT(\"%s\");\n", q->rname); >> >> if ( q->ret!=NULL ) gen("return _retv;\n"); >> gen("}\n"); >> tabs--; >> gen("}\n"); >> if ( q->p2 != NULL ) {TRANS(q->p2);} /* generate code for next rule too */ >> else dumpAfterActions( output ); >>} >> >>static void >>DumpFuncHeader(q, r) >>Junction *q; >>RuleEntry *r; >>{ >> /* A N S I */ >> _gen("\n#ifdef __STDC__\n"); >> if ( q->ret!=NULL ) >> { >> if ( HasComma(q->ret) ) {gen1("struct _rv%d\n",r->rulenum);} >> else >> { >> DumpType(q->ret, output); >> gen("\n"); >> } >> } >> else >> { >> _gen("void\n"); >> } >> gen2("%s%s(", RulePrefix, q->rname); >> if ( GenAST ) >> { >> _gen("AST **_root"); >> if ( q->pdecl!=NULL ) _gen(","); >> } >> _gen1("%s)\n", (q->pdecl!=NULL)?q->pdecl:""); >> >> /* K & R */ >> gen("#else\n"); >> if ( q->ret!=NULL ) >> { >> if ( HasComma(q->ret) ) {gen1("struct _rv%d\n",r->rulenum);} >> else >> { >> DumpType(q->ret, output); >> gen("\n"); >> } >> } >> gen2("%s%s(", RulePrefix, q->rname); >> if ( GenAST ) >> { >> _gen("_root"); >> if ( q->pdecl!=NULL ) _gen(","); >> } >> >> DumpListOfParmNames( q->pdecl, output ); >> gen(")\n"); >> if ( GenAST ) gen("AST **_root;\n"); >> DumpOldStyleParms( q->pdecl, output ); >> gen("#endif\n"); >> gen("{\n"); >>} >> >>void >>genJunction(q) >>Junction *q; >>{ >> require(q->ntype == nJunction, "genJunction: not junction"); >> require(q->jtype == Generic, "genJunction: not generic junction"); >> >> if ( q->p1 != NULL ) TRANS(q->p1); >> if ( q->p2 != NULL ) TRANS(q->p2); >>} >> >>void >>genEndBlk(q) >>Junction *q; >>{ >>} >> >>void >>genEndRule(q) >>Junction *q; >>{ >>} >> >>void >>genHdr(file) >>int file; >>{ >> _gen("/*\n"); >> _gen(" * A n t l r T r a n s l a t i o n H e a d e r\n"); >> _gen(" *\n"); >> _gen(" * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n"); >> _gen(" * Purdue University Electrical Engineering\n"); >> _gen1(" * ANTLR Version %s\n", Version); >> _gen(" */\n"); >> _gen("#include \n"); >> if ( GenLineInfo ) _gen2(LineInfoFormatStr, 1, FileStr[file]); >> if ( HdrAction != NULL ) dumpAction( HdrAction, output, 0, -1, 0, 1); >> if ( LL_k > 1 ) _gen1("#define LL_K %d\n", OutputLL_k); >> if ( GenAST ) _gen("#define GENAST\n\n"); >> if ( DemandLookahead ) _gen("#define DEMAND_LOOK\n\n"); >> _gen("#include \"antlr.h\"\n"); >> if ( GenAST ) _gen("#include \"ast.h\"\n\n"); >> _gen1("#include \"%s\"\n", DefFileName); >> _gen("#include \"dlgdef.h\"\n"); >> _gen("#include \"mode.h\"\n"); >>} >> >>void >>genHdr1(file) >>int file; >>{ >> ListNode *p; >> >> genHdr(file); >> if ( GenAST ) >> { >> _gen("#include \"ast.c\"\n"); >> _gen("zzASTgvars\n\n"); >> } >> _gen("ANTLR_INFO\n"); >> if ( BeforeActions != NULL ) >> { >> for (p = BeforeActions->next; p!=NULL; p=p->next) >> dumpAction( p->elem, output, 0, -1, 0, 1); >> } >>} >> >>void >>genStdPCCTSIncludeFile(f) >>FILE *f; >>{ >> fprintf(f,"/*\n"); >> fprintf(f," * %s -- P C C T S I n c l u d e\n", stdpccts); >> fprintf(f," *\n"); >> fprintf(f," * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n"); >> fprintf(f," * Purdue University Electrical Engineering\n"); >> fprintf(f," * ANTLR Version %s\n", Version); >> fprintf(f," */\n"); >> fprintf(f,"#include \n"); >> if ( HdrAction != NULL ) dumpAction( HdrAction, f, 0, -1, 0, 1); >> if ( LL_k > 1 ) fprintf(f,"#define LL_K %d\n", OutputLL_k); >> if ( GenAST ) fprintf(f,"#define GENAST\n"); >> if ( DemandLookahead ) fprintf(f,"#define DEMAND_LOOK\n"); >> fprintf(f,"#include \"antlr.h\"\n"); >> if ( GenAST ) fprintf(f,"#include \"ast.h\"\n"); >> fprintf(f,"#include \"%s\"\n", DefFileName); >> fprintf(f,"#include \"dlgdef.h\"\n"); >> fprintf(f,"#include \"mode.h\"\n"); >>} >> >>/* dump action 's' to file 'output' starting at "local" tab 'tabs' >> Dump line information in front of action if GenLineInfo is set >> If file == -1 then GenLineInfo is ignored. >> The user may redefine the LineInfoFormatStr to his/her liking >> most compilers will like the default, however. >>*/ >>void >>dumpAction(s,output,tabs,file,line,final_newline) >>char *s; >>FILE *output; >>int tabs, file, line; >>int final_newline; >>{ >> int inDQuote, inSQuote; >> require(s!=NULL, "dumpAction: NULL action"); >> require(output!=NULL, eMsg1("dumpAction: output FILE is NULL for %s",s)); >> >> if ( GenLineInfo && file != -1 ) >> { >> fprintf(output, LineInfoFormatStr, line, FileStr[file]); >> } >> TAB; >> PastWhiteSpace( s ); >> inDQuote = inSQuote = FALSE; >> while ( *s != '\0' ) >> { >> if ( *s == '\\' ) >> { >> putc( *s++, output ); /* Avoid '"' Case */ >> if ( *s == '\0' ) return; >> if ( *s == '\'' ) putc( *s++, output ); >> if ( *s == '\"' ) putc( *s++, output ); >> } >> if ( *s == '\'' ) >> { >> if ( !inDQuote ) inSQuote = !inSQuote; >> } >> if ( *s == '"' ) >> { >> if ( !inSQuote ) inDQuote = !inDQuote; >> } >> if ( *s == '\n' ) >> { >> putc('\n', output); >> PastWhiteSpace( s ); >> if ( *s == '}' ) >> { >> --tabs; >> TAB; >> putc( *s++, output ); >> continue; >> } >> if ( *s == '\0' ) return; >> if ( *s != '#' ) /* #define, #endif etc.. start at col 1 */ >> { >> TAB; >> } >> } >> if ( *s == '}' && !(inSQuote || inDQuote) ) >> { >> --tabs; /* Indent one fewer */ >> } >> if ( *s == '{' && !(inSQuote || inDQuote) ) >> { >> tabs++; /* Indent one more */ >> } >> putc( *s, output ); >> s++; >> } >> if ( final_newline ) putc('\n', output); >>} >> >>static >>dumpAfterActions(output) >>FILE *output; >>{ >> ListNode *p; >> require(output!=NULL, "dumpAfterActions: output file was NULL for some reason"); >> if ( AfterActions != NULL ) >> { >> for (p = AfterActions->next; p!=NULL; p=p->next) >> dumpAction( p->elem, output, 0, -1, 0, 1 ); >> } >> fclose( output ); >>} >> >>/* >> * Find the next action in the stream of execution. Do not pass >> * junctions with more than one path leaving them. >> * Only pass generic junctions. >> * >> * Scan forward while (generic junction with p2==NULL) >> * If we stop on an action, return ptr to the action >> * else return NULL; >> */ >>static ActionNode * >>findImmedAction(q) >>Node *q; >>{ >> Junction *j; >> require(q!=NULL, "findImmedAction: NULL node"); >> require(q->ntype>=1 && q->ntype<=NumNodeTypes, "findImmedAction: invalid node"); >> >> while ( q->ntype == nJunction ) >> { >> j = (Junction *)q; >> if ( j->jtype != Generic || j->p2 != NULL ) return NULL; >> q = j->p1; >> if ( q == NULL ) return NULL; >> } >> if ( q->ntype == nAction ) return (ActionNode *)q; >> return NULL; >>} >> >>static void >>dumpRetValAssign(retval, ret_def) >>char *retval, *ret_def; >>{ >> char *q = ret_def; >> >> tab(); >> while ( *retval != '\0' ) >> { >> while ( isspace((*retval)) ) retval++; >> while ( *retval!=',' && *retval!='\0' ) putc(*retval++, output); >> fprintf(output, " = _trv."); >> >> DumpNextNameInDef(&q, output); >> putc(';', output); putc(' ', output); >> if ( *retval == ',' ) retval++; >> } >>} >> >>/* This function computes the set of tokens that can possibly be seen k >> * tokens in the future from point j >> */ >>static set >>ComputeErrorSet(j,k) >>Junction *j; >>int k; >>{ >> Junction *alt1; >> set a, rk, f; >> require(j->ntype==nJunction, "ComputeErrorSet: non junction passed"); >> >> f = rk = empty; >> for (alt1=j; alt1!=NULL; alt1 = (Junction *)alt1->p2) >> { >> REACH(alt1->p1, k, &rk, a); >> require(set_nil(rk), "ComputeErrorSet: rk != nil"); >> set_orin(&f, a); >> } >> return f; >>} >> >>static void >>makeErrorClause(q, f, max_k) >>Junction *q; >>set f; >>int max_k; >>{ >> if ( max_k == 1 ) >> { >> _gen1("else {zzFAIL(1,zzerr%d", DefErrSet(&f)) >> set_free(f); >> } >> else >> { >> int i; >> set_free(f); >> _gen1("else {zzFAIL(%d", max_k); >> for (i=1; i<=max_k; i++) >> { >> f = ComputeErrorSet(q, i); >> _gen1(",zzerr%d", DefErrSet( &f )); >> set_free(f); >> } >> } >> _gen(",&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;}\n"); >>} >EOF_gen.c >cat << \EOF_globals.c | sed 's/^>//' > globals.c >>/* >> * globals.c -- File containing all variables/tables visible to all files. >> * >> * 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. >> * >> * Terence Parr >> * Purdue University >> * August 1990 >> */ >>#include >>#include "set.h" >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >> >>char Version[] = "1.06"; /* PCCTS version number */ >>char LexStartSymbol[] = "START";/* Name of starting lexical class/automaton */ >> >>char *DlgFileName = "parser.dlg"; >>char *DefFileName = "tokens.h"; >>char *ErrFileName = "err.c"; >> >> >>/* Current ambiguity examination information */ >>int CurAmbigAlt1, CurAmbigAlt2, CurAmbigline, CurAmbigfile; >>char *CurAmbigbtype; >> >> >> /* M e t h o d T a b l e s */ >>/* >> * The following tables are used to fill syntax diagram nodes with the correct >> * function pointers for computing FIRST sets and printing themselves. >> */ >> >>/* fpTraverse[node type] == pointer to function that calculates trees >> * representing the FIRST sets for that node (maintains spatial info). >> */ >>Tree *(*fpTraverse[NumNodeTypes+1])() = { >> NULL, >> tJunc, >> tRuleRef, >> tToken, >> tAction >>}; >> >>/* fpReach[node type] == pointer to function that calculates FIRST set for >> * that node. (r stands for reach) >> */ >>set (*fpReach[NumNodeTypes+1])() = { >> NULL, >> rJunc, >> rRuleRef, >> rToken, >> rAction >>}; >> >>/* fpPrint[node type] == pointer to function that knows how to print that node. */ >>void (*fpPrint[NumNodeTypes+1])() = { >> NULL, >> pJunc, >> pRuleRef, >> pToken, >> pAction >>}; >> >>char *decodeJType[] = { >> "invalid", >> "aSubBlk", >> "aOptBlk", >> "aLoopBlk", >> "EndBlk", >> "RuleBlk", >> "Generic", >> "EndRule", >> "aPlusBlk", >> "aLoopBegin" >>}; >> >> >> /* H a s h T a b l e s */ >> >>Entry **Tname, /* Table of all token names (maps name to tok num)*/ >> **Texpr, /* Table of all token expressions >> (maps expr to tok num) */ >> **Rname, /* Table of all Rules (has ptr to start of rule) */ >> **Fcache, /* Cache of First/Follow Computations */ >> **Tcache; /* Tree cache; First/Follow for permute trees */ >> >> >> /* V a r i a b l e s */ >> >>int EpToken=0; /* Imaginary Epsilon token number */ >>int CurFile= -1; /* Index into FileStr table */ >>char *CurRule=NULL; /* Pointer to current rule name */ >>RuleEntry *CurRuleNode=NULL;/* Pointer to current rule node in syntax tree */ >>char *CurRetDef=NULL; /* Pointer to current return type definition */ >>char *CurParmDef=NULL; /* Pointer to current parameter definition */ >>int NumRules=0; /* Rules are from 1 to n */ >>FILE *output=NULL; /* current parser output file */ >>FILE *input=NULL; /* current grammar input file */ >>char *FileStr[MaxNumFiles];/* Ptr to array of file names on command-line */ >>int NumFiles=0; /* current grammar file number */ >>void (**fpTrans)(), /* array of ptrs to funcs that translate nodes */ >> (**fpJTrans)(); /* ... that translate junctions */ >>int **FoStack; /* Array of LL_k ptrs to stacks of rule numbers */ >>int **FoTOS; /* FOLLOW stack top-of-stack pointers */ >>Junction *SynDiag = NULL; /* Pointer to start of syntax diagram */ >>int BlkLevel=1; /* Current block level. Set by antlr.g, used by >> * scanner to translate $i.j attributes */ >>int TokenNum=TokenStart; >>char **TokenStr=NULL; /* map token # to token name */ >>char **ExprStr=NULL; /* map token # to expr */ >>Junction **RulePtr=NULL; /* map rule # to RuleBlk node of rule */ >>ListNode *ExprOrder=NULL; /* list of exprs as they are found in grammar */ >>ListNode *BeforeActions=NULL;/* list of grammar actions before rules */ >>ListNode *AfterActions=NULL;/* list of grammar actions after rules */ >>ListNode *LexActions=NULL; /* list of lexical actions */ >>ListNode **Cycles=NULL; /* list of cycles (for each k) found when >> doing FOLLOWs */ >>ListNode *eclasses=NULL; /* list of error classes */ >>LClass lclass[MaxLexClasses]; /* array of lex class definitions */ >>int CurrentLexClass; /* index into lclass */ >>int NumLexClasses=0; /* in range 1..MaxLexClasses (init 0) */ >> >>char *HdrAction=NULL; /* action defined with #header */ >>FILE *ErrFile; /* sets and error recovery stuff */ >>FILE *DefFile=NULL; /* list of tokens, return value structs, setwd defs */ >>int CannotContinue=FALSE; >>int OutputLL_k = 1; /* LL_k for parsing must be power of 2 */ >>int action_file; /* used to track start of action */ >>int action_line; >> >> /* C m d - L i n e O p t i o n s */ >> >>int LL_k=1; /* how many tokens of lookahead */ >>int PrintOut = FALSE; /* print out the grammar */ >>int PrintAnnotate = FALSE;/* annotate printout with FIRST sets */ >>int CodeGen=TRUE; /* Generate output code? */ >>int LexGen=TRUE; /* Generate lexical files? (tokens.h, parser.dlg) */ >>int GenAST=FALSE; /* Generate AST's? */ >>int GenANSI=FALSE; /* Generate ANSI code where necessary */ >>int GenExprSets=TRUE; /* use sets not (LA(1)==tok) expression lists */ >>int GenCR=FALSE; /* Generate cross reference? */ >>int GenLineInfo=FALSE; /* Generate # line "file" stuff? */ >>int TraceGen=FALSE; /* Generate code to trace rule invocation */ >>int elevel=1; /* error level for ambiguity messages */ >>int GenEClasseForRules=0;/* don't generate eclass for each rule */ >>int TreeResourceLimit= -1;/* don't limit tree resource */ >>int DemandLookahead = 0;/* demand/delayed lookahead or not */ >>char *RulePrefix = ""; /* prefix each generated rule with this */ >>char *stdpccts = "stdpccts.h";/* where to generate std pccts include file */ >>int GenStdPccts = 0; /* don't gen stdpccts.h? */ >>int ParseWithPredicates = 0; /* don't use for version 1.06 */ >EOF_globals.c >cat << \EOF_hash.c | sed 's/^>//' > hash.c >>/* >> * hash.c >> * >> * Manage hash tables. >> * >> * The following functions are visible: >> * >> * char *strdup(char *); Make space and copy string >> * Entry **newHashTable(); Create and return initialized hash table >> * Entry *hash_add(Entry **, char *, Entry *) >> * Entry *hash_get(Entry **, char *) >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >>#include >>#include "hash.h" >>#ifdef MEMCHK >>#include "trax.h" >>#else >>#ifdef __STDC__ >>void *malloc(unsigned int), *calloc(unsigned int, unsigned int); >>#else >>char *malloc(), *calloc(); >>#endif >>#endif >> >>#define StrSame 0 >>#define fatal(err) \ >> {fprintf(stderr, "%s(%d):", __FILE__, __LINE__); \ >> fprintf(stderr, " %s\n", err); exit(-1);} >>#define require(expr, err) {if ( !(expr) ) fatal(err);} >> >>static unsigned size = HashTableSize; >>static char *strings = NULL; >>static char *strp; >>static unsigned strsize = StrTableSize; >> >>/* create the hash table and string table for terminals (string table only once) */ >>Entry ** >>newHashTable() >>{ >> Entry **table; >> >> table = (Entry **) calloc(size, sizeof(Entry *)); >> require( table != NULL, "cannot allocate hash table"); >> if ( strings == NULL ) >> { >> strings = (char *) calloc(strsize, sizeof(char)); >> require( strings != NULL, "cannot allocate string table"); >> strp = strings; >> } >> return table; >>} >> >>/* Given a table, add 'rec' with key 'key' (add to front of list). return ptr to entry */ >>Entry * >>hash_add(table,key,rec) >>Entry **table; >>char *key; >>Entry *rec; >>{ >> unsigned h=0; >> char *p=key; >> extern Entry *Globals; >> require(table!=NULL && key!=NULL && rec!=NULL, "add: invalid addition"); >> >> Hash(p,h,size); >> rec->next = table[h]; /* Add to singly-linked list */ >> table[h] = rec; >> return rec; >>} >> >>/* Return ptr to 1st entry found in table under key (return NULL if none found) */ >>Entry * >>hash_get(table,key) >>Entry **table; >>char *key; >>{ >> unsigned h=0; >> char *p=key; >> Entry *q; >> require(table!=NULL && key!=NULL, "get: invalid table and/or key"); >> >> Hash(p,h,size); >> for (q = table[h]; q != NULL; q = q->next) >> { >> if ( strcmp(key, q->str) == StrSame ) return( q ); >> } >> return( NULL ); >>} >> >>void >>hashStat(table) >>Entry **table; >>{ >> static unsigned short count[20]; >> int i,n=0,low=0, hi=0; >> Entry **p; >> float avg=0.0; >> >> for (i=0; i<20; i++) count[i] = 0; >> for (p=table; p<&(table[size]); p++) >> { >> Entry *q = *p; >> int len; >> >> if ( q != NULL && low==0 ) low = p-table; >> len = 0; >> if ( q != NULL ) fprintf(stderr, "[%d]", p-table); >> while ( q != NULL ) >> { >> len++; >> n++; >> fprintf(stderr, " %s", q->str); >> q = q->next; >> if ( q == NULL ) fprintf(stderr, "\n"); >> } >> count[len]++; >> if ( *p != NULL ) hi = p-table; >> } >> >> fprintf(stderr, "Storing %d recs used %d hash positions out of %d\n", >> n, size-count[0], size); >> fprintf(stderr, "%f %% utilization\n", >> ((float)(size-count[0]))/((float)size)); >> for (i=0; i<20; i++) >> { >> if ( count[i] != 0 ) >> { >> avg += (((float)(i*count[i]))/((float)n)) * i; >> fprintf(stderr, "Bucket len %d == %d (%f %% of recs)\n", >> i, count[i], ((float)(i*count[i]))/((float)n)); >> } >> } >> fprintf(stderr, "Avg bucket length %f\n", avg); >> fprintf(stderr, "Range of hash function: %d..%d\n", low, hi); >>} >> >>/* Add a string to the string table and return a pointer to it. >> * Bump the pointer into the string table to next avail position. >> */ >>char * >>strdup(s) >>char *s; >>{ >> char *start=strp; >> require(s!=NULL, "strdup: NULL string"); >> >> while ( *s != '\0' ) >> { >> require( strp <= &(strings[strsize-2]), >> "string table overflow\nIncrease StrTableSize in hash.h and recompile hash.c\n"); >> *strp++ = *s++; >> } >> *strp++ = '\0'; >> >> return( start ); >>} >EOF_hash.c >cat << \EOF_lex.c | sed 's/^>//' > lex.c >>/* >> * lex.c -- Generate all of the lexical type files: parser.dlg tokens.h >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#include >>#include >>#include "set.h" >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >> >>#define DLGErrorString "invalid token" >> >>/* Generate a complete lexical description of the lexemes found in the grammar */ >>void >>genLexDescr() >>{ >> ListNode *p; >> FILE *dlgFile = fopen(DlgFileName, "w"); >> require(dlgFile!=NULL, eMsg1("genLexFile: cannot open %s", DlgFileName) ); >> >> fprintf(dlgFile, "<<\n"); >> fprintf(dlgFile, "/* %s -- DLG Description of scanner\n", DlgFileName); >> fprintf(dlgFile, " *\n"); >> fprintf(dlgFile, " * Generated from:"); >> {int i; for (i=0; i> fprintf(dlgFile, "\n"); >> fprintf(dlgFile, " *\n"); >> fprintf(dlgFile, " * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n"); >> fprintf(dlgFile, " * Purdue University Electrical Engineering\n"); >> fprintf(dlgFile, " * ANTLR Version %s\n", Version); >> fprintf(dlgFile, " */\n"); >> fprintf(dlgFile, "#include \n"); >> if ( HdrAction != NULL ) dumpAction( HdrAction, dlgFile, 0, -1, 0, 1 ); >> if ( LL_k > 1 ) fprintf(dlgFile, "#define LL_K %d\n", OutputLL_k); >> if ( DemandLookahead ) fprintf(dlgFile, "#define DEMAND_LOOK\n"); >> fprintf(dlgFile, "#include \"antlr.h\"\n"); >> if ( GenAST ) fprintf(dlgFile, "#include \"ast.h\"\n"); >> fprintf(dlgFile, "#include \"%s\"\n", DefFileName); >> fprintf(dlgFile, "#include \"dlgdef.h\"\n"); >> fprintf(dlgFile, "LOOKAHEAD\n"); >> fprintf(dlgFile, "void zzerraction()\n"); >> fprintf(dlgFile, "{\n"); >> fprintf(dlgFile, "\t(*zzerr)(\"%s\");\n", DLGErrorString); >> fprintf(dlgFile, "\tzzadvance();\n"); >> fprintf(dlgFile, "\tzzskip();\n"); >> fprintf(dlgFile, "}\n>>\n\n"); >> /* dump all actions */ >> if (LexActions != NULL) >> { >> for (p = LexActions->next; p!=NULL; p=p->next) >> { >> fprintf(dlgFile, "<<\n"); >> dumpAction( p->elem, dlgFile, 0, -1, 0, 1 ); >> fprintf(dlgFile, ">>\n"); >> } >> } >> /* dump all regular expression rules/actions (skip sentinel node) */ >> if ( ExprOrder == NULL ) { >> warnNoFL("no regular expressions found in grammar"); >> } >> else dumpLexClasses(dlgFile); >> fprintf(dlgFile, "%%%%\n"); >> fclose( dlgFile ); >>} >> >>/* For each lexical class, scan ExprOrder looking for expressions >> * in that lexical class. Print out only those that match. >> * Each element of the ExprOrder list has both an expr and an lclass >> * field. >> */ >>dumpLexClasses(dlgFile) >>FILE *dlgFile; >>{ >> int i; >> TermEntry *t; >> ListNode *p; >> Expr *q; >> >> for (i=0; i> { >> fprintf(dlgFile, "\n%%%%%s\n\n", lclass[i].class); >> for (p=ExprOrder->next; p!=NULL; p=p->next) >> { >> q = (Expr *) p->elem; >> if ( q->lclass != i ) continue; >> lexmode(i); >> t = (TermEntry *) hash_get(Texpr, q->expr); >> require(t!=NULL, eMsg1("genLexDescr: rexpr %s not in hash table",q->expr) ); >> if ( t->token == EpToken ) continue; >> fprintf(dlgFile, "%s\n\t<<\n", StripQuotes(q->expr)); >> /* replace " killed by StripQuotes() */ >> q->expr[ strlen(q->expr) ] = '"'; >> if ( TokenStr[t->token] != NULL ) >> fprintf(dlgFile, "\t\tNLA = %s;\n", TokenStr[t->token]); >> else fprintf(dlgFile, "\t\tNLA = %d;\n", t->token); >>/* >> if ( TokenStr[t->token] != NULL ) >> fprintf(dlgFile, "\t\tLA(1) = %s;\n", TokenStr[t->token]); >> else fprintf(dlgFile, "\t\tLA(1) = %d;\n", t->token); >>*/ >> if ( t->action != NULL ) dumpAction( t->action, dlgFile, 2,-1,0,1 ); >> fprintf(dlgFile, "\t>>\n\n"); >> } >> } >>} >> >>/* Generate a list of #defines && list of struct definitions for >> * aggregate retv's */ >>void >>genDefFile() >>{ >> Junction *p = SynDiag; >> int i; >> >> DefFile = fopen(DefFileName, "w"); >> require(DefFile!=NULL, eMsg1("genDefFile: cannot open %s", DefFileName) ); >> fprintf(DefFile, "/* %s -- List of labelled tokens\n", DefFileName); >> fprintf(DefFile, " *\n"); >> fprintf(DefFile, " * Generated from:"); >> for (i=0; i> fprintf(DefFile, "\n"); >> fprintf(DefFile, " *\n"); >> fprintf(DefFile, " * Terence Parr, Hank Dietz and Will Cohen: 1989-1992\n"); >> fprintf(DefFile, " * Purdue University Electrical Engineering\n"); >> fprintf(DefFile, " * ANTLR Version %s\n", Version); >> fprintf(DefFile, " */\n"); >> if ( TokenStr[EofToken]!=NULL ) >> fprintf(DefFile, "#define %s %d\n", TokenStr[EofToken], EofToken); >> for (i=TokenStart; i> { >> if ( TokenStr[i]!=NULL && i != EpToken ) >> { >> TermEntry *p; >> >> require((p=(TermEntry *)hash_get(Tname, TokenStr[i])) != NULL, >> "token not in sym tab when it should be"); >> if ( !p->errclassname ) >> { >> fprintf(DefFile, "#define %s %d\n", TokenStr[i], i); >> } >> } >> } >> >> GenRulePrototypes(DefFile, p); >>} >> >>/* Find all return types/parameters that require structs and def >> * all rules with ret types. >> */ >>void >>GenRulePrototypes(f, p) >>FILE *f; >>Junction *p; >>{ >> int i; >> >> i = 1; >> while ( p!=NULL ) >> { >> if ( p->ret != NULL ) >> { >> if ( HasComma(p->ret) ) >> { >> DumpRetValStruct(f, p->ret, i); >> } >> fprintf(f, "\n#ifdef __STDC__\n"); >> if ( HasComma(p->ret) ) >> { >> fprintf(f, "extern struct _rv%d", i); >> } >> else >> { >> fprintf(f, "extern "); >> DumpType(p->ret, f); >> } >> fprintf(f, " %s%s(", RulePrefix, p->rname); >> if ( p->pdecl != NULL || GenAST ) >> { >> if ( GenAST ) fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":""); >> if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl); >> } >> fprintf(f, ");\n"); >> fprintf(f, "#else\n"); >> if ( HasComma(p->ret) ) >> { >> fprintf(f, "extern struct _rv%d", i); >> } >> else >> { >> fprintf(f, "extern "); >> DumpType(p->ret, f); >> } >> fprintf(f, " %s%s();\n", RulePrefix, p->rname); >> fprintf(f, "#endif\n"); >> } >> else >> { >> fprintf(f, "\n#ifdef __STDC__\n"); >> fprintf(f, "void %s%s(", RulePrefix, p->rname); >> if ( p->pdecl != NULL || GenAST ) >> { >> if ( GenAST ) fprintf(f, "AST **%s",(p->pdecl!=NULL)?",":""); >> if ( p->pdecl!=NULL ) fprintf(f, "%s", p->pdecl); >> } >> fprintf(f, ");\n"); >> fprintf(f, "#else\n"); >> fprintf(f, "extern %s%s();\n", RulePrefix, p->rname); >> fprintf(f, "#endif\n"); >> } >> i++; >> p = (Junction *)p->p2; >> } >>} >> >>/* Given a list of ANSI-style parameter declarations, print out a >> * comma-separated list of the symbols (w/o types). >> * Basically, we look for a comma, then work backwards until start of >> * the symbol name. Then print it out until 1st non-alnum char. Now, >> * move on to next parameter. >> */ >>void >>DumpListOfParmNames( pdecl, output ) >>char *pdecl; >>FILE *output; >>{ >> char *end; >> int firstTime = 1, done = 0; >> require(output!=NULL, "DumpListOfParmNames: NULL parm"); >> >> if ( pdecl == NULL ) return; >> while ( !done ) >> { >> if ( !firstTime ) putc(',', output); >> done = DumpNextNameInDef(&pdecl, output); >> firstTime = 0; >> } >>} >> >>/* given a list of parameters or return values, dump the next >> * name to output. Return 1 if last one just printed, 0 if more to go. >> */ >>DumpNextNameInDef(q, output) >>char **q; /* pointer to ptr into definition string */ >>FILE *output; >>{ >> char *p = *q; /* where did we leave off? */ >> int done=0; >> >> while ( *p!='\0' && *p!=',' ) p++; /* find end of decl */ >> if ( *p == '\0' ) done = 1; >> while ( !isalnum(*p) && *p!='_' ) --p; /* scan back until valid var character */ >> while ( isalnum(*p) || *p=='_' ) --p; /* scan back until beginning of variable */ >> p++; /* move to start of variable */ >> while ( isalnum(*p) || *p=='_' ) {putc(*p, output); p++;} >> while ( *p!='\0' && *p!=',' ) p++; /* find end of decl */ >> p++; /* move past this parameter */ >> >> *q = p; /* record where we left off */ >> return done; >>} >> >>/* Given a list of ANSI-style parameter declarations, dump K&R-style >> * declarations, one per line for each parameter. Basically, convert >> * comma to semi-colon, newline. >> */ >>void >>DumpOldStyleParms( pdecl, output ) >>char *pdecl; >>FILE *output; >>{ >> require(output!=NULL, "DumpOldStyleParms: NULL parm"); >> >> if ( pdecl == NULL ) return; >> while ( *pdecl != '\0' ) >> { >> if ( *pdecl == ',' ) >> { >> pdecl++; >> putc(';', output); putc('\n', output); >> while ( *pdecl==' ' || *pdecl=='\t' || *pdecl=='\n' ) pdecl++; >> } >> else {putc(*pdecl, output); pdecl++;} >> } >> putc(';', output); >> putc('\n', output); >>} >> >>/* Take in a type definition (type + symbol) and print out type only */ >>void >>DumpType(s, f) >>char *s; >>FILE *f; >>{ >> char *p, *end; >> require(s!=NULL, "DumpType: invalid type string"); >> >> p = &s[strlen(s)-1]; /* start at end of string and work back */ >> /* scan back until valid variable character */ >> while ( !isalnum(*p) && *p!='_' ) --p; >> /* scan back until beginning of variable */ >> while ( isalnum(*p) || *p=='_' ) --p; >> if ( p<=s ) >> { >> warnNoFL(eMsg1("invalid parameter/return value: '%s'",s)); >> return; >> } >> end = p; /* here is where we stop printing alnum */ >> p = s; >> while ( p!=end ) {putc(*p, f); p++;} /* dump until just before variable */ >> while ( *p!='\0' ) /* dump rest w/o variable */ >> { >> if ( !isalnum(*p) && *p!='_' ) putc(*p, f); >> p++; >> } >>} >> >>/* check to see if string e is a word in string s */ >>int >>strmember(s, e) >> char *s, *e; >>{ >> register char *p; >> require(s!=NULL&&e!=NULL, "strmember: NULL string"); >> >> if ( *e=='\0' ) return 1; /* empty string is always member */ >> do { >> while ( *s!='\0' && !isalnum(*s) && *s!='_' ) >> ++s; >> p = e; >> while ( *p!='\0' && *p==*s ) {p++; s++;} >> if ( *p=='\0' ) { >> if ( *s=='\0' ) return 1; >> if ( !isalnum (*s) && *s != '_' ) return 1; >> } >> while ( isalnum(*s) || *s == '_' ) >> ++s; >> } while ( *s!='\0' ); >> return 0; >>} >> >>int >>HasComma(s) >>char *s; >>{ >> while (*s!='\0') >> if ( *s++ == ',' ) return 1; >> return 0; >>} >> >>void >>DumpRetValStruct(f,ret,i) >>FILE *f; >>char *ret; >>int i; >>{ >> fprintf(f, "\nstruct _rv%d {\n", i); >> while ( *ret != '\0' ) >> { >> while ( *ret==' ' || *ret=='\t' ) ret++; /* ignore white */ >> putc('\t', f); >> while ( *ret!=',' && *ret!='\0' ) putc(*ret++, f); >> if ( *ret == ',' ) {putc(';', f); putc('\n', f); ret++;} >> } >> fprintf(f, ";\n};\n"); >>} >> >>/* given "s" yield s -- DESTRUCTIVE (we modify s if starts with " else return s) */ >>char * >>StripQuotes(s) >>char *s; >>{ >> if ( *s == '"' ) >> { >> s[ strlen(s)-1 ] = '\0'; /* remove last quote */ >> return( s+1 ); /* return address past initial quote */ >> } >> return( s ); >>} >> >EOF_lex.c >cat << \EOF_main.c | sed 's/^>//' > main.c >>/* >> * main.c -- main program for PCCTS ANTLR. >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >>#include >>#include "set.h" >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#include "antlr.h" >>#include "tokens.h" >>#include "dlgdef.h" >> >> >>#define MAX_INT_STACK 50 >>static int istack[MAX_INT_STACK]; /* Int stack */ >>static int isp = MAX_INT_STACK; >> >> /* C m d - L i n e O p t i o n S t r u c t & F u n c s */ >> >>typedef struct _Opt { >> char *option; >> int arg; >> void (*process)(); >> char *descr; >> } Opt; >> >>extern int ProcessArgs(); >> >>static void >>pFile(s) >>char *s; >>{ >> if ( *s=='-' ) { warnNoFL( eMsg1("invalid option: '%s'",s) ); return; } >> require(NumFiles> FileStr[NumFiles++] = s; >>} >> >>static void >>pLLK(s,t) >>char *s,*t; >>{ >> OutputLL_k = LL_k = atoi(t); >> if ( LL_k <= 0 ) { >> warnNoFL("must have at least one token of look-ahead (setting to 1)"); >> LL_k = 1; >> } >> if ( ((LL_k-1)&LL_k)!=0 ) { /* output ll(k) must be power of 2 */ >> int n; >> for(n=1; n> OutputLL_k = n; >> } >>} >> >>static void pCGen() { CodeGen = FALSE; LexGen = FALSE; } >>static void pLGen() { LexGen = FALSE; } >>static void pTGen() { TraceGen = TRUE; } >>static void pSGen() { GenExprSets = FALSE; } >>static void pPrt() { PrintOut = TRUE; pCGen(); pLGen(); } >>static void pPrtA() { PrintOut = TRUE; PrintAnnotate = TRUE; pCGen(); pLGen(); } >>static void pAst() { GenAST = TRUE; } >>static void pANSI() { GenANSI = TRUE; } >>static void pCr() { GenCR = TRUE; } >>static void pLI() { GenLineInfo = TRUE; } >>static void pFe(s,t) char *s, *t; {ErrFileName = t;} >>static void pFl(s,t) char *s, *t; {DlgFileName = t;} >>static void pFt(s,t) char *s, *t; {DefFileName = t;} >>static void pE1() { elevel = 1; } >>static void pE2() { elevel = 2; } >>static void pE3() { elevel = 3; } >>static void pEGen() { GenEClasseForRules = 1; } >>static void pDL() { DemandLookahead = 1; } >>static void pGHdr() { GenStdPccts = 1; } >>static void pPre(s,t) char *s, *t; { RulePrefix = t; } >>static void pFHdr(s,t) char *s, *t; { stdpccts = t; pGHdr(); } >> >>static void >>pPred() >>{ >> ParseWithPredicates = 1; >> if ( DemandLookahead ) >> warnNoFL("-gk conflicts with -pr; -gk turned off"); >> DemandLookahead = 0; >>} >> >>static void pTRes(s,t) >>char *s, *t; >>{ >> TreeResourceLimit = atoi(t); >> if ( TreeResourceLimit <= 0 ) >> { >> warnNoFL("analysis resource limit (# of tree nodes) must be greater than 0"); >> TreeResourceLimit = -1; /* set to no limit */ >> } >>} >> >>Opt options[] = { >> { "-cr", 0, pCr, "Generate cross reference (default=FALSE)"}, >> { "-e1", 0, pE1, "Ambiguities/errors shown in low detail (default)"}, >> { "-e2", 0, pE2, "Ambiguities/errors shown in more detail"}, >> { "-e3", 0, pE3, "Ambiguities/errors shown in excrutiating detail"}, >> { "-fe", 1, pFe, "Rename err.c"}, >> { "-fh", 1, pFHdr, "Rename stdpccts.h header (turns on -gh)"}, >> { "-fl", 1, pFl, "Rename lexical output--parser.dlg"}, >> { "-ft", 1, pFt, "Rename tokens.h"}, >> { "-ga", 0, pANSI, "Generate ANSI-compatible code (default=FALSE)"}, >> { "-gc", 0, pCGen, "Do not generate output parser code (default=FALSE)"}, >> { "-gd", 0, pTGen, "Generate code to trace rule invocation (default=FALSE)"}, >> { "-ge", 0, pEGen, "Generate an error class for each non-terminal (default=FALSE)"}, >> { "-gh", 0, pGHdr, "Generate stdpccts.h for non-ANTLR-generated-files to include"}, >> { "-gk", 0, pDL, "Generate parsers that delay lookahead fetches 'til needed"}, >> { "-gl", 0, pLI, "Generate line info about grammar actions in C parser"}, >> { "-gp", 1, pPre, "Prefix all generated rule functions with a string"}, >> { "-gs", 0, pSGen, "Do not generate sets for token expression lists (default=FALSE)"}, >> { "-gt", 0, pAst, "Generate code for Abstract-Syntax-Trees (default=FALSE)"}, >> { "-gx", 0, pLGen, "Do not generate lexical (dlg-related) files (default=FALSE)"}, >> { "-k", 1, pLLK, "Set k of LL(k) -- tokens of look-ahead (default==1)"}, >> { "-p", 0, pPrt, "Print out the grammar w/o actions (default=no)"}, >> { "-pa", 0, pPrtA, "Print out the grammar w/o actions & w/FIRST sets (default=no)"}, >> { "-pr", 0, pPred, "Turn on use of predicates in parsing decisions (alpha version)"}, >> { "-rl", 1, pTRes, "Limit max # of tree nodes used by grammar analysis"}, >> { "*", 0, pFile, "" }, /* anything else is a file */ >> { NULL, 0, NULL } >>}; >> >>void readDescr(); >>void cleanUp(); >>static void help(), init(), buildRulePtr(); >> >> /* M a i n */ >> >>main(argc,argv) >>int argc; >>char *argv[]; >>{ >> static char EPSTR[] = "[Ep]"; >> >> fprintf(stderr, "Antlr parser generator Version %s 1989-1992\n", Version); >> if ( argc == 1 ) { help(); return 1; } >> ProcessArgs(argc-1, &(argv[1]), options); >> >> fpTrans = &(C_Trans[0]); /* Translate to C Language */ >> fpJTrans = &(C_JTrans[0]); >> init(); >> lexclass(LexStartSymbol); >> >> readDescr(); >> if ( CannotContinue ) {cleanUp(); return 1;} >> if ( HdrAction == NULL ) warnNoFL("no #header action was found"); >> >> EpToken = addTname(EPSTR); /* add imaginary token epsilon */ >> set_size(NumWords(TokenNum-1)); >> >> if ( CodeGen ) genDefFile(); /* create tokens.h */ >> if ( LexGen ) genLexDescr(); /* create parser.dlg */ >> if ( GenStdPccts ) >> { >> FILE *f = fopen(stdpccts, "w"); >> if ( f==NULL ) {warnNoFL( eMsg1("can't create %s",stdpccts) );} >> else >> { >> genStdPCCTSIncludeFile(f); >> fclose(f); >> } >> } >> >> buildRulePtr(); /* create mapping from rule # to RuleBlk junction */ >> ComputeErrorSets(); >> FoLink( (Node *)SynDiag ); /* add follow links to end of all rules */ >> if ( GenCR ) GenCrossRef( SynDiag ); >> >> if ( CodeGen ) >> { >> if ( SynDiag == NULL ) >> { >> warnNoFL("no grammar description recognized"); >> cleanUp(); >> return 1; >> } >> else >> { >> ErrFile = fopen(ErrFileName, "w"); >> require(ErrFile != NULL, "main: can't open err file"); >> NewSetWd(); >> GenErrHdr(); >> TRANS(SynDiag); /* Translate to the target language */ >> DumpSetWd(); >> fclose( ErrFile ); >> } >> } >> >> if ( PrintOut ) >> { >> if ( SynDiag == NULL ) {warnNoFL("no grammar description recognized");} >> else PRINT(SynDiag); >> } >> >> cleanUp(); >> return 0; /* report all is well for make etc... */ >>} >> >>static void >>init() >>{ >> Tname = newHashTable(); >> Rname = newHashTable(); >> Fcache = newHashTable(); >> Tcache = newHashTable(); >> TokenStr = (char **) calloc(TSChunk, sizeof(char *)); >> require(TokenStr!=NULL, "main: cannot allocate TokenStr"); >> FoStack = (int **) calloc(LL_k+1, sizeof(int *)); >> require(FoStack!=NULL, "main: cannot allocate FoStack"); >> FoTOS = (int **) calloc(LL_k+1, sizeof(int *)); >> require(FoTOS!=NULL, "main: cannot allocate FoTOS"); >> Cycles = (ListNode **) calloc(LL_k+1, sizeof(ListNode *)); >> require(Cycles!=NULL, "main: cannot allocate Cycles List"); >>} >> >>static >>void >>help() >>{ >> Opt *p = options; >> fprintf(stderr, "antlr [options] f1 f2 ... fn\n"); >> while ( *(p->option) != '*' ) >> { >> fprintf(stderr, "\t%s %s\t%s\n", >> p->option, >> (p->arg)?"___":" ", >> p->descr); >> p++; >> } >>} >> >>/* The RulePtr array is filled in here. RulePtr exists primarily >> * so that sets of rules can be maintained for the FOLLOW caching >> * mechanism found in rJunc(). RulePtr maps a rule num from 1 to n >> * to a pointer to its RuleBlk junction where n is the number of rules. >> */ >>static void >>buildRulePtr() >>{ >> int r=1; >> Junction *p = SynDiag; >> RulePtr = (Junction **) calloc(NumRules+1, sizeof(Junction *)); >> require(RulePtr!=NULL, "cannot allocate RulePtr array"); >> >> while ( p!=NULL ) >> { >> require(r<=NumRules, "too many rules???"); >> RulePtr[r++] = p; >> p = (Junction *)p->p2; >> } >>} >> >>void >>readDescr() >>{ >> input = NextFile(); >> require(input!=NULL, "No grammar description found (exiting...)"); >> ANTLR(grammar(), input); >>} >> >>FILE * >>NextFile() >>{ >> FILE *f; >> >> for (;;) >> { >> CurFile++; >> if ( CurFile >= NumFiles ) return(NULL); >> f = fopen(FileStr[CurFile], "r"); >> if ( f == NULL ) >> { >> warnNoFL( eMsg1("file %s doesn't exist; ignored", FileStr[CurFile]) ); >> } >> else >> { >>/* aSourceFile = FileStr[CurFile]; >> * Doesn't seem to be used >> */ >> return(f); >> } >> } >>} >> >>/* >> * Return a string corresponding to the output file name associated >> * with the input file name passed in. >> * >> * Observe the following rules: >> * >> * f.e --> f".c" >> * f --> f".c" >> * f. --> f".c" >> * f.e.g --> f.e".c" >> * >> * Where f,e,g are arbitrarily long sequences of characters in a file >> * name. >> * >> * In other words, if a ".x" appears on the end of a file name, make it >> * ".c". If no ".x" appears, append ".c" to the end of the file name. >> * >> * Use malloc() for new string. >> */ >>char * >>outname(fs) >>char *fs; >>{ >> static char buf[MaxFileName+1]; >> char *p; >> >> p = buf; >> strcpy(buf, fs); >> while ( *p != '\0' ) {p++;} /* Stop on '\0' */ >> while ( *p != '.' && p != buf ) {--p;} /* Find '.' */ >> if ( p != buf ) *p = '\0'; /* Found '.' */ >> require(strlen(buf) + 2 < MaxFileName, "outname: filename too big"); >> strcat(buf, ".c"); >> return( buf ); >>} >> >>void >>fatalFL(err,f,l) >>char *err, *f; >>int l; >>{ >> fprintf(stderr, ErrHdr, f, l); >> fprintf(stderr, " %s\n", err); >> cleanUp(); >> exit(-1); >>} >> >>void >>cleanUp() >>{ >> if ( DefFile != NULL) fclose( DefFile ); >>} >> >>/* sprintf up to 3 strings */ >>char * >>eMsg3(s,a1,a2,a3) >>char *s, *a1, *a2, *a3; >>{ >> static char buf[250]; /* DANGEROUS as hell !!!!!! */ >> >> sprintf(buf, s, a1, a2, a3); >> return( buf ); >>} >> >>/* sprintf a decimal */ >>char * >>eMsgd(s,d) >>char *s; >>int d; >>{ >> static char buf[250]; /* DANGEROUS as hell !!!!!! */ >> >> sprintf(buf, s, d); >> return( buf ); >>} >> >>void >>s_fprT(f, e) >>FILE *f; >>set e; >>{ >> register unsigned *p; >> unsigned *q; >> >> if ( set_nil(e) ) return; >> if ( (q=p=set_pdq(e)) == NULL ) fatal("Can't alloc space for set_pdq"); >> fprintf(f, "{"); >> while ( *p != nil ) >> { >> fprintf(f, " %s", TerminalString(*p)); >> p++; >> } >> fprintf(f, " }"); >> free(q); >>} >> >>/* Return the token name or regular expression for a token number. */ >>char * >>TerminalString(token) >>int token; >>{ >> int j; >> >> /* look in all lexclasses for the token */ >> if ( TokenStr[token] != NULL ) return TokenStr[token]; >> for (j=0; j> { >> lexmode(j); >> if ( ExprStr[token] != NULL ) return ExprStr[token]; >> } >> require(j> return "invalid"; >>} >> >> /* S i m p l e I n t S t a c k */ >> >>void >>pushint(i) >>int i; >>{ >> require(isp>0, "pushint: stack overflow"); >> istack[--isp] = i; >>} >> >>int >>popint() >>{ >> require(isp> return istack[isp++]; >>} >> >>int >>istacksize() >>{ >> return MAX_INT_STACK-isp; >>} >> >>void >>istackreset() >>{ >> isp = MAX_INT_STACK; >>} >> >>int >>istackempty() >>{ >> return isp==MAX_INT_STACK; >>} >> >>int >>topint() >>{ >> require(isp> return istack[isp]; >>} >> >>ProcessArgs(argc, argv, options) >>int argc; >>char **argv; >>Opt *options; >>{ >> Opt *p; >> require(argv!=NULL, "ProcessArgs: command line NULL"); >> >> while ( argc-- > 0 ) >> { >> p = options; >> while ( p->option != NULL ) >> { >> if ( strcmp(p->option, "*") == 0 || >> strcmp(p->option, *argv) == 0 ) >> { >> if ( p->arg ) >> { >> (*p->process)( *argv, *(argv+1) ); >> argv++; >> argc--; >> } >> else >> (*p->process)( *argv ); >> break; >> } >> p++; >> } >> argv++; >> } >>} >EOF_main.c >cat << \EOF_misc.c | sed 's/^>//' > misc.c >>/* >> * misc.c >> * >> * Manage tokens, regular expressions. >> * Print methods for debugging >> * Compute follow lists onto tail ends of rules. >> * >> * The following functions are visible: >> * >> * int addTname(char *); Add token name >> * int addTexpr(char *); Add token expression >> * int Tnum(char *); Get number of expr/token >> * void Tlink(char *, char *); Link a name with an expression >> * int hasAction(expr); Does expr already have action assigned? >> * void setHasAction(expr); Indicate that expr now has an action >> * Entry *newEntry(char *,int); Create new table entry with certain size >> * void list_add(ListNode **list, char *e) >> * void list_apply(ListNode *list, void (*f)()) >> * void lexclass(char *m); switch to new/old lexical class >> * void lexmode(int i); switch to old lexical class i >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#include >>#include "set.h" >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#include "dlgdef.h" >> >>static int tsize=TSChunk; /* size of token str arrays */ >> >> /* T o k e n M a n i p u l a t i o n */ >> >>/* >> * add token 't' to the TokenStr/Expr array. Make more room if necessary. >> * 't' is either an expression or a token name. >> * >> * There is only one TokenStr array, but multiple ExprStr's. Therefore, >> * for each lex class (element of lclass) we must extend the ExprStr array. >> * ExprStr's and TokenStr are always all the same size. >> * >> * Also, there is a Texpr hash table for each automaton. >> */ >>static void >>Ttrack(t) >>char *t; >>{ >> if ( TokenNum >= tsize ) /* terminal table overflow? */ >> { >> char **p; >> int i, more, j; >> >> more = TSChunk * (1 + ((TokenNum-tsize) / TSChunk)); >> tsize += more; >> TokenStr = (char **) realloc(TokenStr, tsize*sizeof(char *)); >> require(TokenStr != NULL, "Ttrack: can't extend TokenStr"); >> for (i=0; i> { >> lclass[i].exprs = (char **) >> realloc(lclass[i].exprs, tsize*sizeof(char *)); >> require(lclass[i].exprs != NULL, "Ttrack: can't extend ExprStr"); >> for (p= &lclass[i].exprs[tsize-more],j=1; j<=more; j++) *p++ = NULL; >> } >> for (p= &TokenStr[tsize-more],i=1; i<=more; i++) *p++ = NULL; >> lexmode( CurrentLexClass ); /* reset ExprStr in case table moved */ >> } >> if ( *t == '"' ) ExprStr[TokenNum] = t; >> else TokenStr[TokenNum] = t; >>} >> >>static Expr * >>newExpr(e) >>char *e; >>{ >> Expr *p = (Expr *) calloc(1, sizeof(Expr)); >> require(p!=NULL, "newExpr: cannot alloc Expr node"); >> >> p->expr = e; >> p->lclass = CurrentLexClass; >> return p; >>} >> >>/* switch to lexical class/mode m. This amounts to creating a new >> * lex mode if one does not already exist and making ExprStr point >> * to the correct char string array. We must also switch Texpr tables. >> * >> * BTW, we need multiple ExprStr arrays because more than one automaton >> * may have the same label for a token, but with different expressions. >> * We need to track an expr for each automaton. If we disallowed this >> * feature, only one ExprStr would be required. >> */ >>void >>lexclass(m) >>char *m; >>{ >> int i; >> TermEntry *p; >> static char EOFSTR[] = "\"@\""; >> >> if ( hash_get(Tname, m) != NULL ) >> { >> warn(eMsg1("lexclass name conflicts with token/errclass label '%s'",m)); >> } >> /* does m already exist? */ >> i = LexClassIndex(m); >> if ( i != -1 ) {lexmode(i); return;} >> /* must make new one */ >> NumLexClasses++; >> CurrentLexClass = NumLexClasses-1; >> require(NumLexClasses<=MaxLexClasses, "number of allowable lexclasses exceeded\nIncrease MaxLexClasses in generic.h and recompile all C files"); >> lclass[CurrentLexClass].class = m; >> lclass[CurrentLexClass].exprs = (char **) calloc(tsize, sizeof(char *)); >> require(lclass[CurrentLexClass].exprs!=NULL, >> "lexclass: cannot allocate ExprStr"); >> lclass[CurrentLexClass].htable = newHashTable(); >> ExprStr = lclass[CurrentLexClass].exprs; >> Texpr = lclass[CurrentLexClass].htable; >> /* define EOF for each automaton */ >> p = newTermEntry( EOFSTR ); >> p->token = EofToken; >> hash_add(Texpr, EOFSTR, (Entry *)p); >> list_add(&ExprOrder, (void *)newExpr(EOFSTR)); >> ExprStr[EofToken] = EOFSTR; >>} >> >>void >>lexmode(i) >>int i; >>{ >> require(i> ExprStr = lclass[i].exprs; >> Texpr = lclass[i].htable; >> CurrentLexClass = i; >>} >> >>/* return index into lclass array of lexical class. return -1 if nonexistent */ >>int >>LexClassIndex(class) >>char *class; >>{ >> int i; >> >> for (i=0; i> { >> if ( strcmp(lclass[i].class, class) == 0 ) return i; >> } >> return -1; >>} >> >>int >>hasAction(expr) >>char *expr; >>{ >> TermEntry *p; >> require(expr!=NULL, "hasAction: invalid expr"); >> >> p = (TermEntry *) hash_get(Texpr, expr); >> require(p!=NULL, eMsg1("hasAction: expr '%s' doesn't exist",expr)); >> return (p->action!=NULL); >>} >> >>void >>setHasAction(expr,action) >>char *expr, *action; >>{ >> TermEntry *p; >> require(expr!=NULL, "setHasAction: invalid expr"); >> >> p = (TermEntry *) hash_get(Texpr, expr); >> require(p!=NULL, eMsg1("setHasAction: expr '%s' doesn't exist",expr)); >> p->action = action; >>} >> >>/* >> * Add a token name. Return the token number associated with it. If it already >> * exists, then return the token number assigned to it. >> * >> * Track the order in which tokens are found so that the DLG output maintains >> * that order. It also lets us map token numbers to strings. >> */ >>int >>addTname(token) >>char *token; >>{ >> TermEntry *p; >> require(token!=NULL, "addTname: invalid token name"); >> >> if ( (p=(TermEntry *)hash_get(Tname, token)) != NULL ) return p->token; >> p = newTermEntry( token ); >> Ttrack( p->str ); >> p->token = TokenNum++; >> hash_add(Tname, token, (Entry *)p); >> return p->token; >>} >> >>/* >> * Add a token expr. Return the token number associated with it. If it already >> * exists, then return the token number assigned to it. >> */ >>int >>addTexpr(expr) >>char *expr; >>{ >> TermEntry *p; >> require(expr!=NULL, "addTexpr: invalid regular expression"); >> >> if ( (p=(TermEntry *)hash_get(Texpr, expr)) != NULL ) return p->token; >> p = newTermEntry( expr ); >> Ttrack( p->str ); >> /* track the order in which they occur */ >> list_add(&ExprOrder, (void *)newExpr(p->str)); >> p->token = TokenNum++; >> hash_add(Texpr, expr, (Entry *)p); >> return p->token; >>} >> >>/* return the token number of 'term'. Return 0 if no 'term' exists */ >>int >>Tnum(term) >>char *term; >>{ >> TermEntry *p; >> require(term!=NULL, "Tnum: invalid terminal"); >> >> if ( *term=='"' ) p = (TermEntry *) hash_get(Texpr, term); >> else p = (TermEntry *) hash_get(Tname, term); >> if ( p == NULL ) return 0; >> else return p->token; >>} >> >>/* associate a Name with an expr. If both have been already assigned >> * token numbers, then an error is reported. Add the token or expr >> * that has not been added if no error. This 'represents' the #token >> * ANTLR pseudo-op. If both have not been defined, define them both >> * linked to same token number. >> */ >>void >>Tlink(token,expr) >>char *token, *expr; >>{ >> TermEntry *p, *q; >> require(token!=NULL && expr!=NULL, "Tlink: invalid token name and/or expr"); >> >> p = (TermEntry *) hash_get(Tname, token); >> q = (TermEntry *) hash_get(Texpr, expr); >> if ( p != NULL && q != NULL ) /* both defined */ >> { >> warn( eMsg2("token name %s and rexpr %s already defined; ignored", >> token, expr) ); >> return; >> } >> if ( p==NULL && q==NULL ) /* both not defined */ >> { >> int t = addTname( token ); >> q = newTermEntry( expr ); >> hash_add(Texpr, expr, (Entry *)q); >> q->token = t; >> ExprStr[t] = q->str; >> /* track the order in which they occur */ >> list_add(&ExprOrder, (void *)newExpr(q->str)); >> return; >> } >> if ( p != NULL ) /* one is defined, one is not */ >> { >> q = newTermEntry( expr ); >> hash_add(Texpr, expr, (Entry *)q); >> q->token = p->token; >> ExprStr[p->token] = q->str; /* both expr and token str defined now */ >> list_add(&ExprOrder, (void *)newExpr(q->str)); >> } >> else /* trying to associate name with expr here*/ >> { >> p = newTermEntry( token ); >> hash_add(Tname, token, (Entry *)p); >> p->token = q->token; >> TokenStr[p->token] = p->str;/* both expr and token str defined now */ >> } >>} >> >>/* >> * Given a string, this function allocates and returns a pointer to a >> * hash table record of size 'sz' whose "str" pointer is reset to a position >> * in the string table. >> */ >>Entry * >>newEntry(text,sz) >>char *text; >>int sz; >>{ >> Entry *p; >> require(text!=NULL, "new: NULL terminal"); >> >> if ( (p = (Entry *) calloc(1,sz)) == 0 ) >> { >> fatal("newEntry: out of memory for terminals\n"); >> exit(1); >> } >> p->str = strdup(text); >> >> return(p); >>} >> >>/* >> * add an element to a list. >> * >> * Any non-empty list has a sentinel node whose 'elem' pointer is really >> * a pointer to the last element. (i.e. length(list) = #elemIn(list)+1). >> * Elements are appended to the list. >> */ >>void >>list_add(list,e) >>ListNode **list; >>void *e; >>{ >> ListNode *p, *tail; >> require(e!=NULL, "list_add: attempting to add NULL list element"); >> >> p = newListNode; >> require(p!=NULL, "list_add: cannot alloc new list node"); >> p->elem = e; >> if ( *list == NULL ) >> { >> ListNode *sentinel = newListNode; >> require(sentinel!=NULL, "list_add: cannot alloc sentinel node"); >> *list=sentinel; >> sentinel->next = p; >> sentinel->elem = (char *)p; /* set tail pointer */ >> } >> else /* find end of list */ >> { >> tail = (ListNode *) (*list)->elem; /* get tail pointer */ >> tail->next = p; >> (*list)->elem = (char *) p; /* reset tail */ >> } >>} >> >>void >>list_apply(list,f) >>ListNode *list; >>void (*f)(); >>{ >> ListNode *p; >> require(f!=NULL, "list_apply: NULL function to apply"); >> >> if ( list == NULL ) return; >> for (p = list->next; p!=NULL; p=p->next) (*f)( p->elem ); >>} >> >> /* F O L L O W C y c l e S t u f f */ >> >>/* make a key based upon (rulename, computation, k value). >> * Computation values are 'i'==FIRST, 'o'==FOLLOW. >> */ >>char * >>Fkey(rule,computation,k) >>char *rule; >>int computation; >>int k; >>{ >> static char key[MaxRuleName+2+1]; >> int i; >> >> if ( k > 255 ) >> fatal("k>255 is too big for this implementation of ANTLR!\n"); >> if ( (i=strlen(rule)) > MaxRuleName ) >> fatal( eMsgd("rule name > max of %d\n", MaxRuleName) ); >> strcpy(key,rule); >> key[i] = computation; >> key[i+1] = (char) ((unsigned int) k); >> key[i+2] = '\0'; >> return key; >>} >> >>/* Push a rule onto the kth FOLLOW stack */ >>void >>FoPush(rule,k) >>char *rule; >>int k; >>{ >> RuleEntry *r; >> require(rule!=NULL, "FoPush: tried to push NULL rule"); >> require(k<=LL_k, "FoPush: tried to access non-existent stack"); >> >> /*fprintf(stderr, "FoPush(%s)\n", rule);*/ >> r = (RuleEntry *) hash_get(Rname, rule); >> if ( r == NULL ) {fatal( eMsg1("rule %s must be defined but isn't", rule) );} >> if ( FoStack[k] == NULL ) /* Does the kth stack exist yet? */ >> { >> /*fprintf(stderr, "allocating FoStack\n");*/ >> FoStack[k] = (int *) calloc(FoStackSize, sizeof(int)); >> require(FoStack[k]!=NULL, "FoPush: cannot allocate FOLLOW stack\n"); >> } >> if ( FoTOS[k] == NULL ) >> { >> FoTOS[k]=FoStack[k]; >> *(FoTOS[k]) = r->rulenum; >> } >> else >> { >>#ifdef MEMCHK >> require(valid(FoStack[k]), "FoPush: invalid FoStack"); >>#endif >> if ( FoTOS[k] >= &(FoStack[k][FoStackSize-1]) ) >> fatal( eMsgd("exceeded max depth of FOLLOW recursion (%d)\n", >> FoStackSize) ); >> require(FoTOS[k]>=FoStack[k], >> eMsg1("FoPush: FoStack stack-ptr is playing out of its sandbox", >> rule)); >> ++(FoTOS[k]); >> *(FoTOS[k]) = r->rulenum; >> } >> { >> /* >> int *p; >> fprintf(stderr, "FoStack[k=%d]:\n", k); >> for (p=FoStack[k]; p<=FoTOS[k]; p++) >> { >> fprintf(stderr, "\t%s\n", RulePtr[*p]->rname); >> } >> */ >> } >>} >> >>/* Pop one rule off of the FOLLOW stack. TOS ptr is NULL if empty. */ >>void >>FoPop(k) >>int k; >>{ >> require(k<=LL_k, "FoPop: tried to access non-existent stack"); >> /*fprintf(stderr, "FoPop\n");*/ >> require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]), >> "FoPop: FoStack stack-ptr is playing out of its sandbox"); >> if ( FoTOS[k] == FoStack[k] ) FoTOS[k] = NULL; >> else (FoTOS[k])--; >>} >> >>/* Compute FOLLOW cycle. >> * Mark all FOLLOW sets for rules in cycle as incomplete. >> * Then, save cycle on the cycle list (Cycles) for later resolution. >> * The Cycle is stored in the form: >> * (head of cycle==croot, rest of rules in cycle==cyclicDep) >> * >> * e.g. (Fo means "FOLLOW of", "-->" means requires or depends on) >> * >> * Fo(x)-->Fo(a)-->Fo(b)-->Fo(c)-->Fo(x) >> * ^----Infinite recursion (cycle) >> * >> * the cycle would be: x -> {a,b,c} or stored as (x,{a,b,c}). Fo(x) depends >> * on the FOLLOW of a,b, and c. The root of a cycle is always complete after >> * Fo(x) finishes. Fo(a,b,c) however are not. It turns out that all rules >> * in a FOLLOW cycle have the same FOLLOW set. >> */ >>void >>RegisterCycle(rule,k) >>char *rule; >>int k; >>{ >> CacheEntry *f; >> Cycle *c; >> int *p; >> RuleEntry *r; >> require(rule!=NULL, "RegisterCycle: tried to register NULL rule"); >> require(k<=LL_k, "RegisterCycle: tried to access non-existent stack"); >> >> /*fprintf(stderr, "RegisterCycle(%s)\n", rule);*/ >> /* Find cycle start */ >> r = (RuleEntry *) hash_get(Rname, rule); >> require(r!=NULL,eMsg1("rule %s must be defined but isn't", rule)); >> require(FoTOS[k]>=FoStack[k]&&FoTOS[k]<=&(FoStack[k][FoStackSize-1]), >> eMsg1("RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox", >> rule)); >>/* if ( FoTOS[k]&(FoStack[k][FoStackSize-1]) ) >> { >> fprintf(stderr, "RegisterCycle(%s): FoStack stack-ptr is playing out of its sandbox\n", >> rule); >> fprintf(stderr, "RegisterCycle: sp==0x%x out of bounds 0x%x...0x%x\n", >> FoTOS[k], FoStack[k], &(FoStack[k][FoStackSize-1])); >> exit(-1); >> } >>*/ >>#ifdef MEMCHK >> require(valid(FoStack[k]), "RegisterCycle: invalid FoStack"); >>#endif >> for (p=FoTOS[k]; *p != r->rulenum && p >= FoStack[k]; --p) {;} >> require(p>=FoStack[k], "RegisterCycle: FoStack is screwed up beyond belief"); >> if ( p == FoTOS[k] ) return; /* don't worry about cycles to oneself */ >> >> /* compute cyclic dependents (rules in cycle except head) */ >> c = newCycle; >> require(c!=NULL, "RegisterCycle: couldn't alloc new cycle"); >> c->cyclicDep = empty; >> c->croot = *p++; /* record root of cycle */ >> for (; p<=FoTOS[k]; p++) >> { >> /* Mark all dependent rules as incomplete */ >> f = (CacheEntry *) hash_get(Fcache, Fkey(RulePtr[*p]->rname,'o',k)); >> if ( f==NULL ) >> { >> f = newCacheEntry( Fkey(RulePtr[*p]->rname,'o',k) ); >> hash_add(Fcache, Fkey(RulePtr[*p]->rname,'o',k), (Entry *)f); >> } >> f->incomplete = TRUE; >> >> set_orel(*p, &(c->cyclicDep)); /* mark rule as dependent of croot */ >> } >> list_add(&(Cycles[k]), (void *)c); >>} >> >>/* make all rules in cycle complete >> * >> * while ( some set has changed ) do >> * for each cycle do >> * if degree of FOLLOW set for croot > old degree then >> * update all FOLLOW sets for rules in cyclic dependency >> * change = TRUE >> * endif >> * endfor >> * endwhile >> */ >>void >>ResolveFoCycles(k) >>int k; >>{ >> ListNode *p, *q; >> Cycle *c; >> int changed = 1; >> CacheEntry *f,*g; >> int r,d,i; >> >> /*fprintf(stderr, "Resolving following cycles for %d\n", k);*/ >> while ( changed ) >> { >> changed = 0; >> i = 0; >> for (p = Cycles[k]->next; p!=NULL; p=p->next) >> { >> c = (Cycle *) p->elem; >> /*fprintf(stderr, "cycle %d: %s -->", i++, RulePtr[c->croot]->rname);*/ >> /*s_fprT(stderr, c->cyclicDep);*/ >> /*fprintf(stderr, "\n");*/ >> f = (CacheEntry *) >> hash_get(Fcache, Fkey(RulePtr[c->croot]->rname,'o',k)); >> require(f!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[c->croot]->rname) ); >> if ( (d=set_deg(f->fset)) > c->deg ) >> { >> /*fprintf(stderr, "Fo(%s) has changed\n", RulePtr[c->croot]->rname);*/ >> changed = 1; >> c->deg = d; /* update cycle FOLLOW set degree */ >> while ( !set_nil(c->cyclicDep) ) >> { >> r = set_int(c->cyclicDep); >> set_rm(r, c->cyclicDep); >> /*fprintf(stderr, "updating Fo(%s)\n", RulePtr[r]->rname);*/ >> g = (CacheEntry *) >> hash_get(Fcache, Fkey(RulePtr[r]->rname,'o',k)); >> require(g!=NULL, eMsg1("FOLLOW(%s) must be in cache but isn't", RulePtr[r]->rname) ); >> set_orin(&(g->fset), f->fset); >> g->incomplete = FALSE; >> } >> } >> } >> if ( i == 1 ) changed = 0; /* if only 1 cycle, no need to repeat */ >> } >> /* kill Cycle list */ >> for (q = Cycles[k]->next; q != NULL; q=p) >> { >> p = q->next; >> set_free( ((Cycle *)q->elem)->cyclicDep ); >> free(q); >> } >> free( Cycles[k] ); >> Cycles[k] = NULL; >>} >> >> >> /* P r i n t i n g S y n t a x D i a g r a m s */ >> >>static void >>pBlk(q,btype) >>Junction *q; >>int btype; >>{ >> int k; >> Junction *alt; >> >> q->end->visited = TRUE; >> if ( btype == aLoopBegin ) >> { >> require(q->p2!=NULL, "pBlk: invalid ()* block"); >> PRINT(q->p1); >> alt = (Junction *)q->p2; >> PRINT(alt->p1); >> if ( PrintAnnotate ) >> { >> printf(" /* Opt "); >> k = 1; >> while ( !set_nil(alt->fset[k]) ) >> { >> s_fprT(stdout, alt->fset[k]); >> if ( k++ == LL_k ) break; >> if ( !set_nil(alt->fset[k]) ) printf(", "); >> } >> printf(" */\n"); >> } >> return; >> } >> for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) >> { >> if ( alt->p1 != NULL ) PRINT(alt->p1); >> if ( PrintAnnotate ) >> { >> printf( " /* [%d] ", alt->altnum); >> k = 1; >> while ( !set_nil(alt->fset[k]) ) >> { >> s_fprT(stdout, alt->fset[k]); >> if ( k++ == LL_k ) break; >> if ( !set_nil(alt->fset[k]) ) printf(", "); >> } >> if ( alt->p2 == NULL && btype == aOptBlk ) >> printf( " (optional branch) */\n"); >> else printf( " */\n"); >> } >> if ( alt->p2 != NULL && !(((Junction *)alt->p2)->p2==NULL && btype == aOptBlk) ) >> { >> printf(" |"); >> } >> } >> q->end->visited = FALSE; >>} >> >>/* How to print out a junction */ >>void >>pJunc(q) >>Junction *q; >>{ >> int dum_k; >> int doing_rule; >> require(q!=NULL, "pJunc: NULL node"); >> require(q->ntype==nJunction, "pJunc: not junction"); >> >> if ( q->visited == TRUE ) return; >> q->visited = TRUE; >> switch ( q->jtype ) >> { >> case aSubBlk : >> if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); >> if ( q->end->p1 != NULL && ((Junction *)q->end->p1)->ntype==nJunction && >> ((Junction *)q->end->p1)->jtype == EndRule ) doing_rule = 1; >> else doing_rule = 0; >> if ( doing_rule ) pBlk(q,q->jtype); >> else { printf(" ("); pBlk(q,q->jtype); printf(" )\n"); } >> if ( PrintAnnotate ) freeBlkFsets(q); >> if ( q->end->p1 != NULL ) PRINT(q->end->p1); >> break; >> case aOptBlk : >> if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); >> printf(" {"); pBlk(q,q->jtype); printf(" }"); >> if ( PrintAnnotate ) freeBlkFsets(q); >> if ( q->end->p1 != NULL ) PRINT(q->end->p1); >> break; >> case aLoopBegin : >> if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); >> printf(" ("); pBlk(q,q->jtype); printf(" )*"); >> if ( PrintAnnotate ) freeBlkFsets(q); >> if ( q->end->p1 != NULL ) PRINT(q->end->p1); >> break; >> case aLoopBlk : >> if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); >> pBlk(q,q->jtype); >> if ( PrintAnnotate ) freeBlkFsets(q); >> break; >> case aPlusBlk : >> if ( PrintAnnotate ) First(q, 1, q->jtype, &dum_k); >> printf(" ("); pBlk(q,q->jtype); printf(" )+"); >> if ( PrintAnnotate ) freeBlkFsets(q); >> if ( q->end->p1 != NULL ) PRINT(q->end->p1); >> break; >> case EndBlk : >> break; >> case RuleBlk : >> printf( "\n%s :", q->rname); >> PRINT(q->p1); >> if ( q->p2 != NULL ) PRINT(q->p2); >> break; >> case Generic : >> if ( q->p1 != NULL ) PRINT(q->p1); >> q->visited = FALSE; >> if ( q->p2 != NULL ) PRINT(q->p2); >> break; >> case EndRule : >> printf( " ;\n"); >> break; >> } >> q->visited = FALSE; >>} >> >>/* How to print out a rule reference node */ >>void >>pRuleRef(p) >>RuleRefNode *p; >>{ >> require(p!=NULL, "pRuleRef: NULL node"); >> require(p->ntype==nRuleRef, "pRuleRef: not rule ref node"); >> >> printf( " %s", p->text); >> PRINT(p->next); >>} >> >>/* How to print out a terminal node */ >>void >>pToken(p) >>TokNode *p; >>{ >> require(p!=NULL, "pToken: NULL node"); >> require(p->ntype==nToken, "pToken: not token node"); >> >> printf( " %s", TerminalString(p->token)); >> PRINT(p->next); >>} >> >>/* How to print out a terminal node */ >>void >>pAction(p) >>ActionNode *p; >>{ >> require(p!=NULL, "pAction: NULL node"); >> require(p->ntype==nAction, "pAction: not action node"); >> >> PRINT(p->next); >>} >> >> /* F i l l F o l l o w L i s t s */ >> >>/* >> * Search all rules for all rule reference nodes, q to rule, r. >> * Add q->next to follow list dangling off of rule r. >> * i.e. >> * >> * r: -o-R-o-->o--> Ptr to node following rule r in another rule >> * | >> * o--> Ptr to node following another reference to r. >> * >> * This is the data structure employed to avoid FOLLOW set computation. We >> * simply compute the FIRST (reach) of the EndRule Node which follows the >> * list found at the end of all rules which are referenced elsewhere. Rules >> * not invoked by other rules have no follow list (r->end->p1==NULL). >> * Generally, only start symbols are not invoked by another rule. >> * >> * Note that this mechanism also gives a free cross-reference mechanism. >> * >> * The entire syntax diagram is layed out like this: >> * >> * SynDiag >> * | >> * v >> * o-->R1--o >> * | >> * o-->R2--o >> * | >> * ... >> * | >> * o-->Rn--o >> * >> */ >>void >>FoLink(p) >>Node *p; >>{ >> RuleEntry *q; >> Junction *j = (Junction *) p; >> RuleRefNode *r = (RuleRefNode *) p; >> >> if ( p==NULL ) return; >> require(p->ntype>=1 && p->ntype<=NumNodeTypes, "FoLink: invalid diagram node"); >> switch ( p->ntype ) >> { >> case nJunction : >> if ( j->visited ) return; >> if ( j->jtype == EndRule ) return; >> j->visited = TRUE; >> FoLink( j->p1 ); >> FoLink( j->p2 ); >> j->visited = FALSE; >> return; >> case nRuleRef : >> q = (RuleEntry *) hash_get(Rname, r->text); >> if ( q == NULL ) >> { >> warnNoFL( eMsg1("rule %s not defined",r->text) ); >> } >> else >> { >> if ( r->parms!=NULL && RulePtr[q->rulenum]->pdecl==NULL ) >> { >> warnFL( eMsg1("rule %s accepts no parameter(s)", r->text), >> FileStr[r->file], r->line ); >> } >> if ( r->parms==NULL && RulePtr[q->rulenum]->pdecl!=NULL ) >> { >> warnFL( eMsg1("rule %s requires parameter(s)", r->text), >> FileStr[r->file], r->line ); >> } >> if ( r->assign!=NULL && RulePtr[q->rulenum]->ret==NULL ) >> { >> warnFL( eMsg1("rule %s yields no return value(s)", r->text), >> FileStr[r->file], r->line ); >> } >> if ( r->assign==NULL && RulePtr[q->rulenum]->ret!=NULL ) >> { >> warnFL( eMsg1("rule %s returns a value(s)", r->text), >> FileStr[r->file], r->line ); >> } >> if ( !r->linked ) >> { >> addFoLink( r->next, r->rname, RulePtr[q->rulenum] ); >> r->linked = TRUE; >> } >> } >> FoLink( r->next ); >> return; >> case nToken : >> FoLink( ((TokNode *)p)->next ); >> return; >> case nAction : >> FoLink( ((ActionNode *)p)->next ); >> return; >> default : >> fatal("invalid node type"); >> } >>} >> >>/* >> * Add a reference to the end of a rule. >> * >> * 'r' points to the RuleBlk node in a rule. r->end points to the last node >> * (EndRule jtype) in a rule. >> * >> * Initial: >> * r->end --> o >> * >> * After: >> * r->end --> o-->o--> Ptr to node following rule r in another rule >> * | >> * o--> Ptr to node following another reference to r. >> * >> * Note that the links are added to the head of the list so that r->end->p1 >> * always points to the most recently added follow-link. At the end, it should >> * point to the last reference found in the grammar (starting from the 1st rule). >> */ >>addFoLink(p,rname,r) >>Node *p; >>char *rname; >>Junction *r; >>{ >> Junction *j; >> require(r!=NULL, "addFoLink: incorrect rule graph"); >> require(r->end!=NULL, "addFoLink: incorrect rule graph"); >> require(r->end->jtype==EndRule, "addFoLink: incorrect rule graph"); >> require(p!=NULL, "addFoLink: NULL FOLLOW link"); >> >> j = newJunction(); >> j->rname = rname; /* rname on follow links point to target rule */ >> j->p1 = p; /* link to other rule */ >> j->p2 = (Node *) r->end->p1;/* point to head of list */ >> r->end->p1 = (Node *) j; /* reset head to point to new node */ >>} >> >>void >>GenCrossRef(p) >>Junction *p; >>{ >> set a; >> Junction *j; >> RuleEntry *q; >> unsigned e; >> require(p!=NULL, "GenCrossRef: why are you passing me a null grammar?"); >> >> printf("Cross Reference:\n\n"); >> a = empty; >> for (; p!=NULL; p = (Junction *)p->p2) >> { >> printf("Rule %11s referenced by {", p->rname); >> /* make a set of rules for uniqueness */ >> for (j = (Junction *)(p->end)->p1; j!=NULL; j = (Junction *)j->p2) >> { >> q = (RuleEntry *) hash_get(Rname, j->rname); >> require(q!=NULL, "GenCrossRef: FoLinks are screwed up"); >> set_orel(q->rulenum, &a); >> } >> for (; !set_nil(a); set_rm(e, a)) >> { >> e = set_int(a); >> printf(" %s", RulePtr[e]->rname); >> } >> printf(" }\n"); >> } >> set_free( a ); >>} >EOF_misc.c >cat << \EOF_pred.c | sed 's/^>//' > pred.c >>/* >> * pred.c -- source for predicate detection, manipulation >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#include >>#include "set.h" >>#include "syn.h" >>#include "hash.h" >>#include "generic.h" >>#include "dlgdef.h" >> >>/* Look for a predicate; >> * >> * Do not pass anything but Junction nodes; no Actions, Tokens, RuleRefs. >> * Return the predicate found if any. ONLY FINDS ONE FOR NOW. >> */ >>Predicate >>find_predicates(alt) >>Node *alt; >>{ >>#ifdef DBG_PRED >> Junction *j; >> RuleRefNode *r; >> TokNode *t; >>#endif >> Junction *pr; >> Predicate pred; >> static Predicate pred_empty = {NULL,NULL}; >> int max_k=0; >> >> if ( alt==NULL ) return pred_empty; >> >>#ifdef DBG_PRED >> switch ( alt->ntype ) >> { >> case nJunction : >> j = (Junction *) alt; >> fprintf(stderr, "Junction(in %s)", j->rname); >> switch ( j->jtype ) >> { >> case aSubBlk : >> fprintf(stderr,"aSubBlk\n"); >> break; >> case aOptBlk : >> fprintf(stderr,"aOptBlk\n"); >> break; >> case aLoopBegin : >> fprintf(stderr,"aLoopBeginBlk\n"); >> break; >> case aLoopBlk : >> fprintf(stderr,"aLoopBlk\n"); >> break; >> case aPlusBlk : >> fprintf(stderr,"aPlusBlk\n"); >> break; >> case EndBlk : >> fprintf(stderr,"EndBlk\n"); >> break; >> case RuleBlk : >> fprintf(stderr,"RuleBlk\n"); >> break; >> case Generic : >> fprintf(stderr,"Generic\n"); >> break; >> case EndRule : >> fprintf(stderr,"EndRule\n"); >> break; >> } >> break; >> case nRuleRef : >> r = (RuleRefNode *) alt; >> fprintf(stderr, "RuleRef(in %s)\n", r->rname); >> break; >> case nToken : >> t = (TokNode *) alt; >> fprintf(stderr, "TokenNode(in %s)%s\n", t->rname, TokenStr[t->token]); >> break; >> case nAction : >> fprintf(stderr, "Action\n"); >> break; >> } >>#endif >> >> switch ( alt->ntype ) >> { >> case nJunction : >> { >> Predicate a; >> Junction *p = (Junction *) alt; >> if ( p->jtype == EndRule ) >> { >> return pred_empty; >> } >> if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || >> p->jtype==aPlusBlk || p->jtype==EndRule ) >> { >> require(p->pred_lock!=NULL, "rJunc: lock array is NULL"); >> if ( p->pred_lock[1] ) >> { >> return pred_empty; >> } >> p->pred_lock[1] = TRUE; >> } >> a = find_predicates(p->p1); >> if ( a.expr!=NULL ) >> { >> if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || >> p->jtype==aPlusBlk || p->jtype==EndRule ) >> { >> p->pred_lock[1] = FALSE; >> } >> return a; >> } >> a = find_predicates(p->p2); >> if ( p->jtype==aLoopBlk || p->jtype==RuleBlk || >> p->jtype==aPlusBlk || p->jtype==EndRule ) >> { >> p->pred_lock[1] = FALSE; >> } >> return a; >> } >> case nAction : >> { >> set f; >> ActionNode *p = (ActionNode *) alt; >> if ( p->init_action ) return find_predicates(p->next); >> if ( p->is_predicate ) >> { >> set rk; >> Tree *t; >>#ifdef DBG_PRED >> fprintf(stderr, "action: <<%s>>?\n", p->action); >>#endif >> >>#ifdef COMPUTE_CONTEXT >> ConstrainSearch = 0; >> TRAV(p->next, LL_k, &rk, t); >> t = tshrink( t ); >> t = tflatten( t ); >> t = tleft_factor( t ); >>#ifdef DBG_PRED >> fprintf(stderr, "after shrink&flatten&left_factor:"); preorder(t); fprintf(stderr, "\n"); >>#endif >>#endif >> >> pred.expr = p->action; >> >>#ifdef COMPUTE_CONTEXT >> pred.context = t; >>#else >> pred.context = NULL; >>#endif >> return pred; >> } >> return pred_empty; >> } >> case nRuleRef : >> { >> Predicate a; >> RuleRefNode *p = (RuleRefNode *) alt; >> Junction *r; >> int save_halt; >> RuleEntry *q = (RuleEntry *) hash_get(Rname, p->text); >> r = RulePtr[q->rulenum]; >> save_halt = r->end->halt; >> r->end->halt = TRUE; >> a = find_predicates((Node *)r->p1); >> r->end->halt = save_halt; >> return a; >> } >> case nToken : >> break; >> } >> >> return pred_empty; >>} >EOF_pred.c >cat << \EOF_generic.h | sed 's/^>//' > generic.h >>/* >> * generic.h -- generic include stuff for new PCCTS ANTLR. >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >>#define StrSame 0 >> >>/* User may redefine how line information looks */ >>#define LineInfoFormatStr "# %d \"%s\"\n" >> >>#define ZZLEXBUFSIZE 4000 >> >>/* Tree/FIRST/FOLLOW defines -- valid only after all grammar has been read */ >>#define ALT TokenNum+1 >>#define SET TokenNum+2 >>#define TREE_REF TokenNum+3 >> >> /* E r r o r M a c r o s */ >> >>#ifdef MPW /* Macintosh Programmer's Workshop */ >>#define ErrHdr "File \"%s\"; Line %d #" >>#else >>#define ErrHdr "%s, line %d:" >>#endif >> >>#define fatal(err) fatalFL(err, __FILE__, __LINE__) >>#define warnNoFL(err) fprintf(stderr, "warning: %s\n", err); >>#define warnFL(err,f,l) \ >> {fprintf(stderr, ErrHdr, f, l); \ >> fprintf(stderr, " warning: %s\n", err);} >>#define warn(err) \ >> {fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); \ >> fprintf(stderr, " warning: %s\n", err);} >>#define warnNoCR( err ) \ >> {fprintf(stderr, ErrHdr, FileStr[CurFile], zzline); \ >> fprintf(stderr, " warning: %s", err);} >>#define eMsg1(s,a) eMsg3(s,a,NULL,NULL) >>#define eMsg2(s,a,b) eMsg3(s,a,b,NULL) >> >> /* S a n i t y C h e c k i n g */ >> >>#ifndef require >>#define require(expr, err) {if ( !(expr) ) fatal(err);} >>#endif >> >> /* L i s t N o d e s */ >> >>typedef struct _l { >> char *elem; /* pointer to any kind of element */ >> struct _l *next; >> } ListNode; >> >>/* Define a Cycle node which is used to track lists of cycles for later >> * reconciliation by ResolveFoCycles(). >> */ >>typedef struct _c { >> int croot; /* cycle root */ >> set cyclicDep; /* cyclic dependents */ >> unsigned deg; /* degree of FOLLOW set of croot */ >> } Cycle; >> >>typedef struct _e { >> int tok; /* error class name == TokenStr[tok] */ >> ListNode *elist; /* linked list of elements in error set */ >> set eset; >> int setdeg; /* how big is the set */ >> int lexclass; /* which lex class is it in? */ >> } ECnode; >> >>#define newListNode (ListNode *) calloc(1, sizeof(ListNode)); >>#define newCycle (Cycle *) calloc(1, sizeof(Cycle)); >>#define newECnode (ECnode *) calloc(1, sizeof(ECnode)); >> >> >> /* H a s h T a b l e E n t r i e s */ >> >>typedef struct _t { /* Token name or expression */ >> char *str; >> struct _t *next; >> int token; /* token number */ >> int errclassname; /* is it a errclass name or token */ >> char *action; >> } TermEntry; >> >>typedef struct _r { /* Rule name and ptr to start of rule */ >> char *str; >> struct _t *next; >>/* int passedSomething;/* is this rule passed something? */ >>/* int returnsSomething;/* does this rule return something? */ >> int rulenum; /* RulePtr[rulenum]== ptr to RuleBlk junction */ >> int noAST; /* gen AST construction code? (def==gen code) */ >> char *egroup; /* which error group (err reporting stuff) */ >> } RuleEntry; >> >>typedef struct _f { /* cache Fi/Fo set */ >> char *str; /* key == (rulename, computation, k) */ >> struct _f *next; >> set fset; /* First/Follow of rule */ >> set rk; /* set of k's remaining to be done after ruleref */ >> int incomplete; /* only w/FOLLOW sets. Use only if complete */ >> } CacheEntry; >> >>#define newTermEntry(s) (TermEntry *) newEntry(s, sizeof(TermEntry)) >>#define newRuleEntry(s) (RuleEntry *) newEntry(s, sizeof(RuleEntry)) >>#define newCacheEntry(s) (CacheEntry *) newEntry(s, sizeof(CacheEntry)) >> >> /* L e x i c a l C l a s s */ >> >>/* to switch lex classes, switch ExprStr and Texpr (hash table) */ >>typedef struct _lc { >> char *class, **exprs; >> Entry **htable; >> } LClass; >> >>typedef struct _exprOrder { >> char *expr; >> int lclass; >> } Expr; >> >> >>typedef Graph Attrib; >> >> /* M a x i m u m s */ >> >>#ifndef HashTableSize >>#define HashTableSize 253 >>#endif >>#ifndef StrTableSize >>#define StrTableSize 15000 /* all tokens, nonterminals, rexprs stored here */ >>#endif >>#define MaxLexClasses 50 /* how many automatons */ >>#define TokenStart 2 /* MUST be in 1 + EofToken */ >>#define EofToken 1 /* Always predefined to be 1 */ >>#define MaxNumFiles 20 >>#define MaxFileName 300 /* largest file name size */ >>#define MaxRuleName 100 /* largest rule name size */ >>#define TSChunk 100 /* how much to expand TokenStr/ExprStr each time */ >>#define FoStackSize 100 /* deepest FOLLOW recursion possible */ >> >>/* AST token types */ >>#define ASTexclude 0 >>#define ASTchild 1 >>#define ASTroot 2 >>#define ASTinclude 3 /* include subtree made by rule ref */ >> >> /* V a r i a b l e s */ >> >>extern int tp; >>extern Junction *SynDiag; >>extern char Version[]; >>extern void (*fpPrint[])(); >>extern set (*fpReach[])(); >>extern Tree *(*fpTraverse[])(); >>extern void (**fpTrans)(); >>extern void (**fpJTrans)(); >>extern void (*C_Trans[])(); >>extern void (*C_JTrans[])(); >>extern int BlkLevel; >>extern int CurFile; >>extern char *CurRule; >>extern RuleEntry *CurRuleNode; >>extern char *FileStr[]; >>extern int NumFiles; >>extern int EpToken; >>extern Entry **Tname, >> **Texpr, >> **Rname, >> **Fcache, >> **Tcache; >>extern ListNode *ExprOrder; >>extern ListNode **Cycles; >>extern int TokenNum; >>extern ListNode *BeforeActions, *AfterActions, *LexActions; >>extern ListNode *eclasses; >>extern char *HdrAction; >>extern FILE *ErrFile; >>extern char *ErrFileName; >>extern char *DlgFileName; >>extern char *DefFileName; >>extern int NumRules; >>extern Junction **RulePtr; >>extern int LL_k; >>extern char *decodeJType[]; >>extern int PrintOut; >>extern int PrintAnnotate; >>extern int CodeGen; >>extern int LexGen; >>extern int setnum; >>extern int wordnum; >>extern int GenAST; >>extern int GenANSI; >>extern int **FoStack; >>extern int **FoTOS; >>extern int GenExprSets; >>extern FILE *DefFile; >>extern int CannotContinue; >>extern int GenCR; >>extern int GenLineInfo; >>extern int action_file, action_line; >>extern int TraceGen; >>extern int CurAmbigAlt1, CurAmbigAlt2, CurAmbigline, CurAmbigfile; >>extern char *CurAmbigbtype; >>extern int elevel; >>extern int GenEClasseForRules; >>extern FILE *input, *output; >>extern char **TokenStr, **ExprStr; >>extern int CurrentLexClass, NumLexClasses; >>extern LClass lclass[]; >>extern char LexStartSymbol[]; >>extern char *CurRetDef; >>extern char *CurParmDef; >>extern int OutputLL_k; >>extern int TreeResourceLimit; >>extern int DemandLookahead; >>extern char *RulePrefix; >>extern int GenStdPccts; >>extern char *stdpccts; >>extern int ParseWithPredicates; >>extern int ConstrainSearch; >> >>#ifdef MEMCHK >>#include "trax.h" >>#else >>#ifdef __STDC__ >>void *malloc(unsigned int), *calloc(unsigned int, unsigned int); >>void *realloc(void *, unsigned int); >>void free(void *); /* TJP added for ANSI compilation */ >>#else >>char *malloc(), *calloc(), *realloc(); >>#endif >>#endif >> >>#ifndef TRUE >>#define TRUE 1 >>#endif >>#ifndef FALSE >>#define FALSE 0 >>#endif >> >>#include "proto.h" >EOF_generic.h >cat << \EOF_hash.h | sed 's/^>//' > hash.h >>/* >> * hash.h -- define hash table entries, sizes, hash function... >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >> /* H a s h T a b l e S t u f f */ >> >>#ifndef HashTableSize >>#define HashTableSize 353 >>#endif >>#ifndef StrTableSize >>#define StrTableSize 5000 >>#endif >> >>typedef struct _entry { /* Minimum hash table entry -- superclass */ >> char *str; >> struct _entry *next; >> } Entry; >> >>/* Hash 's' using 'size', place into h (s is modified) */ >>#define Hash(s,h,size) \ >> {while ( *s != '\0' ) h = (h<<1) + *s++; \ >> h %= size;} >> >>#ifdef __STDC__ >>Entry *hash_get(Entry **, char *), >> **newHashTable(void), >> *hash_add(Entry **, char *, Entry *); >>#else >>Entry *hash_get(), **newHashTable(), *hash_add(); >>#endif >EOF_hash.h >cat << \EOF_mode.h | sed 's/^>//' > mode.h >>#define START 0 >>#define STRINGS 1 >>#define COMMENTS 2 >>#define ACTIONS 3 >EOF_mode.h >cat << \EOF_proto.h | sed 's/^>//' > proto.h >>/* >> * proto.h -- function prototypes >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >>#ifdef __STDC__ >>extern void istackreset(void); >>extern int istacksize(void); >>extern void pushint(int); >>extern int popint( void ); >>extern int istackempty( void ); >>extern int topint( void ); >>extern void NewSetWd( void ); >>extern void DumpSetWd( void ); >>extern void NewSet( void ); >>extern void FillSet( set ); >>extern void ComputeErrorSets( void ); >>extern void SubstErrorClass( set * ); >>extern int DefErrSet( set * ); >>extern void GenErrHdr( void ); >>extern void dumpExpr( char * ); >>extern void addParm( Node *, char * ); >>extern Graph buildAction( char *, int, int, int ); >>extern Graph buildToken( char * ); >>extern Graph buildRuleRef( char * ); >>extern Graph Or( Graph, Graph ); >>extern Graph Cat( Graph, Graph ); >>extern Graph makeOpt( Graph ); >>extern Graph makeBlk( Graph ); >>extern Graph makeLoop( Graph ); >>extern Graph makePlus( Graph ); >>extern Graph emptyAlt( void ); >>extern TokNode * newTokNode( void ); >>extern RuleRefNode * newRNode( void ); >>extern Junction * newJunction( void ); >>extern ActionNode * newActionNode( void ); >>extern char * makelocks( void ); >>extern void preorder( Tree * ); >>extern Tree * tnode( int ); >>extern void tfree( Tree * ); >>extern Tree * tdup( Tree * ); >>extern Tree * tappend( Tree *, Tree * ); >>extern void Tfree( Tree * ); >>extern Tree * tlink( Tree *, Tree *, int ); >>extern Tree * tshrink( Tree * ); >>extern Tree * tflatten( Tree * ); >>extern Tree * tJunc( Junction *, int, set * ); >>extern Tree * tRuleRef( RuleRefNode *, int, set * ); >>extern Tree * tToken( TokNode *, int, set * ); >>extern Tree * tAction( ActionNode *, int, set * ); >>extern int tmember( Tree *, Tree * ); >>extern Tree * tleft_factor( Tree * ); >>extern Tree * trm_perm( Tree *, Tree * ); >>extern void tcvt( set *, Tree * ); >>extern Tree * permute( int ); >>extern Tree * VerifyAmbig( Junction *, Junction *, unsigned **, set *, Tree **, Tree **, int * ); >>extern set rJunc( Junction *, int, set * ); >>extern set rRuleRef( RuleRefNode *, int, set * ); >>extern set rToken( TokNode *, int, set * ); >>extern set rAction( ActionNode *, int, set * ); >>extern void HandleAmbiguity( Junction *, Junction *, int ); >>extern set First( Junction *, int, int, int * ); >>extern void freeBlkFsets( Junction * ); >>extern void genAction( ActionNode * ); >>extern void genRuleRef( RuleRefNode * ); >>extern void genToken( TokNode * ); >>extern void genOptBlk( Junction * ); >>extern void genLoopBlk( Junction *, Junction *, int ); >>extern void genLoopBegin( Junction * ); >>extern void genPlusBlk( Junction * ); >>extern void genSubBlk( Junction * ); >>extern void genRule( Junction * ); >>extern void genJunction( Junction * ); >>extern void genEndBlk( Junction * ); >>extern void genEndRule( Junction * ); >>extern void genHdr( int ); >>extern void genHdr1( int ); >>extern void dumpAction( char *, FILE *, int, int, int, int ); >>extern Entry ** newHashTable( void ); >>extern Entry * hash_add( Entry **, char *, Entry * ); >>extern Entry * hash_get( Entry **, char * ); >>extern void hashStat( Entry ** ); >>extern char * strdup( char * ); >>extern void genLexDescr( void ); >>extern int dumpLexClasses( FILE * ); >>extern void genDefFile( void ); >>extern void DumpListOfParmNames( char *, FILE * ); >>extern int DumpNextNameInDef( char **, FILE * ); >>extern void DumpOldStyleParms( char *, FILE * ); >>extern void DumpType( char *, FILE * ); >>extern int strmember( char *, char * ); >>extern int HasComma( char * ); >>extern void DumpRetValStruct( FILE *, char *, int ); >>extern char * StripQuotes( char * ); >>extern int main( int, char *[] ); >>extern void readDescr( void ); >>extern FILE * NextFile( void ); >>extern char * outname( char * ); >>extern void fatalFL( char *, char *, int ); >>extern void cleanUp( void ); >>extern char * eMsg3( char *, char *, char *, char * ); >>extern char * eMsgd( char *, int ); >>extern void s_fprT( FILE *, set ); >>extern char * TerminalString( int ); >>extern void lexclass( char * ); >>extern void lexmode( int ); >>extern int LexClassIndex( char * ); >>extern int hasAction( char * ); >>extern void setHasAction( char *, char * ); >>extern int addTname( char * ); >>extern int addTexpr( char * ); >>extern int Tnum( char * ); >>extern void Tlink( char *, char * ); >>extern Entry * newEntry( char *, int ); >>extern void list_add( ListNode **, void * ); >>extern void list_apply( ListNode *, void (*)() ); >>extern char * Fkey( char *, int, int ); >>extern void FoPush( char *, int ); >>extern void FoPop( int ); >>extern void RegisterCycle( char *, int ); >>extern void ResolveFoCycles( int ); >>extern void pJunc( Junction * ); >>extern void pRuleRef( RuleRefNode * ); >>extern void pToken( TokNode * ); >>extern void pAction( ActionNode * ); >>extern void FoLink( Node * ); >>extern int addFoLink( Node *, char *, Junction * ); >>extern void GenCrossRef( Junction * ); >>extern void defErr( char *, long, long, long, long, long, long ); >>extern void genStdPCCTSIncludeFile(FILE *); >>extern Predicate find_predicates(Node *); >>extern void GenRulePrototypes(FILE *, Junction *); >>#else >>extern void istackreset(); >>extern int istacksize(); >>extern void pushint(); >>extern int popint(); >>extern int istackempty(); >>extern int topint(); >>extern void NewSetWd(); >>extern void DumpSetWd(); >>extern void NewSet(); >>extern void FillSet(); >>extern void ComputeErrorSets(); >>extern void SubstErrorClass(); >>extern int DefErrSet(); >>extern void GenErrHdr(); >>extern void dumpExpr(); >>extern void addParm(); >>extern Graph buildAction(); >>extern Graph buildToken(); >>extern Graph buildRuleRef(); >>extern Graph Or(); >>extern Graph Cat(); >>extern Graph makeOpt(); >>extern Graph makeBlk(); >>extern Graph makeLoop(); >>extern Graph makePlus(); >>extern Graph emptyAlt(); >>extern TokNode * newTokNode(); >>extern RuleRefNode * newRNode(); >>extern Junction * newJunction(); >>extern ActionNode * newActionNode(); >>extern char * makelocks(); >>extern void preorder(); >>extern Tree * tnode(); >>extern void tfree(); >>extern Tree * tdup(); >>extern Tree * tappend(); >>extern void Tfree(); >>extern Tree * tlink(); >>extern Tree * tshrink(); >>extern Tree * tflatten(); >>extern Tree * tJunc(); >>extern Tree * tRuleRef(); >>extern Tree * tToken(); >>extern Tree * tAction(); >>extern int tmember(); >>extern Tree * tleft_factor(); >>extern Tree * trm_perm(); >>extern void tcvt(); >>extern Tree * permute(); >>extern Tree * VerifyAmbig(); >>extern set rJunc(); >>extern set rRuleRef(); >>extern set rToken(); >>extern set rAction(); >>extern void HandleAmbiguity(); >>extern set First(); >>extern void freeBlkFsets(); >>extern void genAction(); >>extern void genRuleRef(); >>extern void genToken(); >>extern void genOptBlk(); >>extern void genLoopBlk(); >>extern void genLoopBegin(); >>extern void genPlusBlk(); >>extern void genSubBlk(); >>extern void genRule(); >>extern void genJunction(); >>extern void genEndBlk(); >>extern void genEndRule(); >>extern void genHdr(); >>extern void genHdr1(); >>extern void dumpAction(); >>extern Entry ** newHashTable(); >>extern Entry * hash_add(); >>extern Entry * hash_get(); >>extern void hashStat(); >>extern char * strdup(); >>extern void genLexDescr(); >>extern int dumpLexClasses(); >>extern void genDefFile(); >>extern void DumpListOfParmNames(); >>extern int DumpNextNameInDef(); >>extern void DumpOldStyleParms(); >>extern void DumpType(); >>extern int strmember(); >>extern int HasComma(); >>extern void DumpRetValStruct(); >>extern char * StripQuotes(); >>extern int main(); >>extern void readDescr(); >>extern FILE * NextFile(); >>extern char * outname(); >>extern void fatalFL(); >>extern void cleanUp(); >>extern char * eMsg3(); >>extern char * eMsgd(); >>extern void s_fprT(); >>extern char * TerminalString(); >>extern void lexclass(); >>extern void lexmode(); >>extern int LexClassIndex(); >>extern int hasAction(); >>extern void setHasAction(); >>extern int addTname(); >>extern int addTexpr(); >>extern int Tnum(); >>extern void Tlink(); >>extern Entry * newEntry(); >>extern void list_add(); >>extern void list_apply(); >>extern char * Fkey(); >>extern void FoPush(); >>extern void FoPop(); >>extern void RegisterCycle(); >>extern void ResolveFoCycles(); >>extern void pJunc(); >>extern void pRuleRef(); >>extern void pToken(); >>extern void pAction(); >>extern void FoLink(); >>extern int addFoLink(); >>extern void GenCrossRef(); >>extern void defErr(); >>extern void genStdPCCTSIncludeFile(); >>extern Predicate find_predicates(); >>extern void GenRulePrototypes(); >>#endif >EOF_proto.h >cat << \EOF_syn.h | sed 's/^>//' > syn.h >>/* >> * syn.h >> * >> * This file includes definitions and macros associated with syntax diagrams >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >>#define NumNodeTypes 4 >>#define NumJuncTypes 9 >> >>/* List the different node types */ >>#define nJunction 1 >>#define nRuleRef 2 >>#define nToken 3 >>#define nAction 4 >> >>/* Different types of junctions */ >>#define aSubBlk 1 >>#define aOptBlk 2 >>#define aLoopBlk 3 >>#define EndBlk 4 >>#define RuleBlk 5 >>#define Generic 6 /* just a junction--no unusual characteristics */ >>#define EndRule 7 >>#define aPlusBlk 8 >>#define aLoopBegin 9 >> >>typedef int NodeType; >> >>#define TreeBlockAllocSize 500 >>#define JunctionBlockAllocSize 200 >>#define ActionBlockAllocSize 50 >>#define RRefBlockAllocSize 100 >>#define TokenBlockAllocSize 100 >> >>/* note that 'right' is used by the tree node allocator as a ptr for linked list */ >>typedef struct _tree { >> struct _tree *down, *right; >> int token; >> union { >> int rk; /* if token==EpToken, => how many more tokens req'd */ >> struct _tree *tref; /* if token==TREE_REF */ >> set sref; /* if token==SET */ >> } v; >> } Tree; >> >>/* a predicate is defined to be a predicate action and a token tree with context info */ >>typedef struct { >> char *expr; >> Tree *context; >>} Predicate; >> >> /* M e s s a g e P a s s i n g T o N o d e s */ >> >>/* >> * assumes a 'Junction *r' exists. This macro calls a function with >> * the pointer to the node to operate on and a pointer to the rule >> * in which it is enclosed. >> */ >>#define TRANS(p) {if ( (p)==NULL ) fatal("TRANS: NULL object"); \ >> if ( (p)->ntype == nJunction ) (*(fpJTrans[((Junction *)(p))->jtype]))( p );\ >> else (*(fpTrans[(p)->ntype]))( p );} >> >>#define PRINT(p) {if ( (p)==NULL ) fatal("PRINT: NULL object");\ >> (*(fpPrint[(p)->ntype]))( p );} >> >>#define REACH(p,k,rk,a){if ( (p)==NULL ) fatal("REACH: NULL object");\ >> (a) = (*(fpReach[(p)->ntype]))( p, k, rk );} >> >>#define TRAV(p,k,rk,a){if ( (p)==NULL ) fatal("TRAV: NULL object");\ >> (a) = (*(fpTraverse[(p)->ntype]))( p, k, rk );} >> >>/* All syntax diagram nodes derive from Node -- superclass >> */ >>typedef struct _node { >> NodeType ntype; >> } Node; >> >>typedef struct _anode { >> NodeType ntype; >> Node *next; >> char *action; >> int file; /* index in FileStr (name of file with action) */ >> int line; /* line number that action occurs on */ >> int is_predicate; /* true if action is a <<...>>? predicate action */ >> int done; /* don't dump if action dumped (used for predicates) */ >> int init_action; /* is this the 1st action of 1st prod of block? */ >> char *pred_fail; /* what to do/print when predicate fails */ >> } ActionNode; >> >>typedef struct _toknode { >> NodeType ntype; >> Node *next; >> char *rname; /* name of rule it's in */ >> int file; /* index in FileStr (name of file with rule) */ >> int line; /* line number that token occurs on */ >> int token; >> int label; /* token label or expression ? */ >> int astnode; /* leaf/root/excluded (used to build AST's) */ >> } TokNode; >> >>typedef struct _rrnode { >> NodeType ntype; >> Node *next; >> char *rname; /* name of rule it's in */ >> int file; /* index in FileStr (name of file with rule) >> it's in */ >> int line; /* line number that rule ref occurs on */ >> char *text; /* reference to which rule */ >> char *parms; /* point to parameters of rule invocation >> (if present) */ >> char *assign; /* point to left-hand-side of assignment >> (if any) */ >> int linked; /* Has a FoLink already been established? */ >> int astnode; /* excluded? (used to build AST's) */ >> } RuleRefNode; >> >>typedef struct _junct { >> NodeType ntype; >> int visited; /* used by recursive routines to avoid >> infinite recursion */ >> char *lock; /* used by REACH to track infinite recursion */ >> char *pred_lock; /* used by find_predicates to track infinite recursion */ >> int altnum; /* used in subblocks. altnum==0 means not an >> alt of subrule */ >> int jtype; /* annotation for code-gen/FIRST/FOLLOW. >> Junction type */ >> struct _junct *end; /* pointer to node with EndBlk in it >> if blk == a block type */ >> Node *p1, *p2; >> char *rname; /* name of rule junction is in */ >> int file; /* index in FileStr (name of file with rule) >> if blk == RuleBlk */ >> int line; /* line number that rule occurs on */ >> int halt; /* never move past a junction with halt==TRUE */ >> char *pdecl; /* point to declaration of parameters on rule >> (if present) */ >> char *parm; /* point to parameter of block invocation >> (if present) */ >> char *ret; /* point to return type of rule (if present) */ >> char *erraction; /* point to error action (if present) */ >> set *fset; /* used for code generation */ >> Tree *ftree; /* used for code generation */ >> Predicate predicate;/* predicate that can be used to disambiguate */ >>} Junction; >> >>typedef struct { Node *left, *right; } Graph; >EOF_syn.h >cat << \EOF_tokens.h | sed 's/^>//' > tokens.h >>/* tokens.h -- List of labelled tokens >> * >> * Generated from: antlr.g >> * >> * Terence Parr, Hank Dietz and Will Cohen: 1989-1992 >> * Purdue University Electrical Engineering >> * ANTLR Version 1.06 >> */ >>#define Eof 1 >>#define QuotedTerm 2 >>#define Action 11 >>#define Pred 12 >>#define PassAction 13 >>#define NonTerminal 51 >>#define TokenTerm 59 >> >>#ifdef __STDC__ >>void grammar(); >>#else >>extern grammar(); >>#endif >> >>#ifdef __STDC__ >>void rule(); >>#else >>extern rule(); >>#endif >> >>#ifdef __STDC__ >>void laction(); >>#else >>extern laction(); >>#endif >> >>#ifdef __STDC__ >>void aLexclass(); >>#else >>extern aLexclass(); >>#endif >> >>#ifdef __STDC__ >>void error(); >>#else >>extern error(); >>#endif >> >>#ifdef __STDC__ >>void token(); >>#else >>extern token(); >>#endif >> >>#ifdef __STDC__ >>void block(); >>#else >>extern block(); >>#endif >> >>#ifdef __STDC__ >>void alt(); >>#else >>extern alt(); >>#endif >> >>#ifdef __STDC__ >>void element(); >>#else >>extern element(); >>#endif >>extern unsigned zzerr1[]; >>extern unsigned zzerr2[]; >>extern unsigned zzerr3[]; >>extern unsigned zzerr4[]; >>extern unsigned zzerr5[]; >>extern unsigned zzerr6[]; >>extern unsigned zzerr7[]; >>extern unsigned setwd1[]; >EOF_tokens.h >cat << \EOF_makefile.user | sed 's/^>//' > makefile.user >># >># Makefile for ANTLR 1.06 >># Terence Parr >># Purdue University >># November 1992 >># >>SET=../support/set >>PCCTS_H=../h >>SYSTEM=UNIX >>CC=cc >>CFLAGS= -I. -I$(SET) -D$(SYSTEM) -I$(PCCTS_H) >>ANTLR=../bin/antlr >>DLG=../bin/dlg >> >>SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \ >> hash.c lex.c main.c misc.c $(SET)/set.c pred.c >>OBJ=antlr.o scan.o err.o bits.o build.o fset2.o fset.o gen.o globals.o \ >> hash.o lex.o main.o misc.o set.o pred.o >> >>antlr : $(OBJ) $(SRC) >> $(CC) $(CFLAGS) -o antlr $(OBJ) >> mv antlr ../bin >> >>antlr.c parser.dlg tokens.h err.c : antlr.g >> $(ANTLR) antlr.g >> >>scan.c mode.h : parser.dlg >> $(DLG) -C2 parser.dlg scan.c >> >>set.o : $(SET)/set.c >> $(CC) -c -o set.o $(CFLAGS) $(SET)/set.c >> >>#clean up all the intermediate files >>clean: >> rm -f *.o core >> >>#remove everything in clean plus the PCCTS files generated >>scrub: >> rm -f $(PCCTS_GEN) *.o core >EOF_makefile.user >cat << \EOF_makefile.os2 | sed 's/^>//' > makefile.os2 >># >># Makefile for ANTLR 1.06 >># Terence Parr >># Purdue University >># November 1992 >># >># Ported to Microsoft 6.0 by >># Ed Harfmann >># Micro Data Base Systems >># Lafayette, Indiana >># >>SET=../support/set >>PCCTS_H=../h >>SYSTEM=PC >>CC=cl >>ANTLR=..\bin\antlr >>DLG=..\bin\dlg >> >>CFLAGS= -I. -I$(SET) -D$(SYSTEM) -I$(PCCTS_H) /AL /Za >> >>LIBS=/NOD:LLIBCE LLIBCEP >> >>SRC=antlr.c scan.c err.c bits.c build.c fset2.c fset.c gen.c globals.c \ >> hash.c lex.c main.c misc.c $(SET)/set.c pred.c >>OBJ=antlr.obj scan.obj err.obj bits.obj build.obj fset2.obj fset.obj gen.obj globals.obj \ >> hash.obj lex.obj main.obj misc.obj set.obj pred.obj >> >>antlr.exe: $(OBJ) $(SRC) >> link @<< >>$(OBJ: = +^ >>) /NOI >>$@ /STACK:16384 >> >>$(LIBS: = +^ >>) >>$(DEF_FILE) $(LFLAGS) ; >><< >> bind $@ c:\os2\doscalls.lib >> copy *.exe ..\bin >> >>antlr.c parser.dlg tokens.h err.c : antlr.g >> $(ANTLR) antlr.g >> >>scan.c mode.h : parser.dlg >> $(DLG) -C2 parser.dlg scan.c >> >>set.obj: $(SET)/set.c >> $(CC) -c $(CFLAGS) $(SET)/set.c >EOF_makefile.os2 >cat << \EOF_antlr.1 | sed 's/^>//' > antlr.1 >>.TH ANTLR 1 "December 1992" "ANTLR" "PCCTS Manual Pages" >>.SH NAME >>antlr \- ANother Tool for Language Recognition >>.SH SYNTAX >>.LP >>\fBantlr\fR [\fIoptions\fR] \fIgrammar_files\fR >>.SH DESCRIPTION >>.PP >>\fIAntlr\fP converts an extended form of context-free grammar into a >>set of C functions which directly implement an efficient form of >>deterministic recursive-descent LL(k) parser. Context-free grammars >>may be augmented with predicates to allow semantics to influence >>parsing; this allows a form of context-sensitive parsing. \fIAntlr\fP >>also produces a definition of a lexer which can be automatically >>converted into C code for a DFA-based lexer by \fIdlg\fR. Hence, >>\fIantlr\fR serves a function much like that of \fIyacc\fR, however, >>it is notably more flexible and is more integrated with a lexer >>generator (\fIantlr\fR directly generates \fIdlg\fR code, whereas >>\fIyacc\fR and \fIlex\fR are given independent descriptions). >>Unlike \fIyacc\fR which accepts LALR(1) grammars, \fIantlr\fR accepts >>LL(k) grammars in an extended BNF notation \(em which eliminates the >>need for precedence rules. >>.PP >>Like \fIyacc\fR grammars, \fIantlr\fR grammars can use >>automatically-maintained symbol attribute values referenced as dollar >>variables. Further, because \fIantlr\fR generates top-down parsers, >>arbitrary values may be inherited from parent rules (passed like >>function parameters). \fIAntlr\fP also has a mechanism for creating >>and manipulating abstract-syntax-trees. >>.PP >>There are various other niceties in \fIantlr\fR, including the ability to >>spread one grammar over multiple files or even multiple grammars in a single >>file, the ability to generate a version of the grammar with actions stripped >>out (for documentation purposes), and lots more. >>.SH OPTIONS >>.IP \fB-cr\fP >>Generate a cross-reference for all rules. For each rule, print a list >>of all other rules that reference it. >>.IP \fB-e1\fP >>Ambiguities/errors shown in low detail (default). >>.IP \fB-e2\fP >>Ambiguities/errors shown in more detail. >>.IP \fB-e3\fP >>Ambiguities/errors shown in excrutiating detail. >>.IP "\fB-fe\fP file" >>Rename \fBerr.c\fP to file. >>.IP "\fB-fh\fP file" >>Rename \fBstdpccts.h\fP header (turns on \fB-gh\fP) to file. >>.IP "\fB-fl\fP file" >>Rename lexical output, \fBparser.dlg\fP, to file. >>.IP "\fB-ft\fP file" >>Rename \fBtokens.h\fP to file. >>.IP \fB-ga\fP >>Generate ANSI-compatible code (default case). This has not been >>rigorously tested to be ANSI XJ11 C compliant, but it is close. The >>normal output of \fIantlr\fP is currently compilable under both K&R >>and ANSI C\(emthis option does nothing, but is reserved for the future. >>.IP \fB-gc\fP >>Indicates that \fIantlr\fP should generate no C code, i.e., only >>perform analysis on the grammar. >>.IP \fB-gd\fP >>C code is inserted in each of the \fIantlr\fR generated parsing functions to >>provide for user-defined handling of a detailed parse trace. The inserted >>code consists of calls to the user-supplied macros or functions called >>\fBzzTRACEIN\fR and \fBzzTRACEOUT\fP. The only argument is a >>\fIchar *\fR pointing to a C-style string which is the grammar rule >>recognized by the current parsing function. If no definition is given >>for the trace functions, upon rule entry and exit, a message will be >>printed indicating that a particular rule as been entered or exited. >>.IP \fB-ge\fP >>Generate an error class for each non-terminal. >>.IP \fB-gh\fP >>Generate \fBstdpccts.h\fP for non-ANTLR-generated files to include. >>This file contains all defines needed to describe the type of parser >>generated by \fIantlr\fP (e.g. how much lookahead is used and whether >>or not trees are constructed) and contains the \fBheader\fP action >>specified by the user. >>.IP \fB-gk\fP >>Generate parsers that delay lookahead fetches until needed. Without >>this option, \fIantlr\fP generates parsers which always have \fIk\fP >>tokens of lookahead available. This option is incompatible with >>\fB-pr\fP and renders references to \fBLA(\fIi\fB)\fR invalid as >>one never knows when the \fIith\fP token of lookahead will be fetched. >>.IP \fB-gl\fP >>Generate line info about grammar actions in C parser of the form >>\fB#\ \fIline\fP\ "\fIfile\fP"\fR which makes error messages from >>the C/C++ compiler make more sense as they will \*Qpoint\*U into the >>grammar file not the resulting C file. Debugging is easier as well, >>because you will step through the grammar not C file. >>.IP "\fB-gp \fIprefix\fR" >>Prefix all functions generated from rules with \fIprefix\fP. >>.IP \fB-gs\fR >>Do not generate sets for token expression lists; instead generate a >>\fB||\fP-separated sequence of \fBLA(1)==\fItoken_number\fR. The >>default is to generate sets. >>.IP \fB-gt\fP >>Generate code for Abstract-Syntax Trees. >>.IP \fB-gx\fP >>Do not create the lexical analyzer files (dlg-related). This option >>should be given when the user wishes to provide a customized lexical >>analyzer. It may also be used in \fImake\fR scripts to cause only the >>parser to be rebuilt when a change not affecting the lexical structure >>is made to the input grammars. >>.IP "\fB-k \fIn\fR" >>Set k of LL(k) to \fIn\fR; i.e. set tokens of look-ahead (default==1). >>.IP \fB-p\fP >>The complete grammar, collected from all input grammar files and >>stripped of all comments and embedded actions, is listed to >>\fBstdout\fP. This is intended to aid in viewing the entire grammar >>as a whole and to eliminate the need to keep actions concisely stated >>so that the grammar is easier to read. Hence, it is preferable to >>embed even complex actions directly in the grammar, rather than to >>call them as subroutines, since the subroutine call overhead will be >>saved. >>.IP \fB-pa\fP >>This option is the same as \fB-p\fP except that the output is >>annotated with the first sets determined from grammar analysis. >>.IP \fB-pr\fP >>Turn on use of predicates in parsing decisions (alpha version). When >>a syntactic ambiguity is discovered, \fIantlr\fP searches for >>predicates that can be used to disambiguate the decision. Predicates >>have dual roles as semantic validation and disambiguation predicates. >>.IP \fB-rl \fIn\fR >>Limit the maximum number of tree nodes used by grammar analysis to >>\fIn\fP. Occasionally, \fIantlr\fP is unable to analyze a grammar >>submitted by the user. This rare situation can only occur when the >>grammar is large and the amount of lookahead is greater than one. A >>nonlinear analysis algorithm is used by PCCTS to handle the general >>case of LL(k) parsing. The average complexity of analysis, however, is >>near linear due to some fancy footwork in the implementation which >>reduces the number of calls to the full LL(k) algorithm. An error >>message will be displayed, if this limit is reached, which indicates >>the grammar construct being analyzed when \fIantlr\fP hit a >>non-linearity. Use this option if \fIantlr\fP seems to go out to >>lunch and your disk start thrashing; try \fIn\fP=10000 to start. Once >>the offending construct has been identified, try to remove the >>ambiguity that \fIantlr\fP was trying to overcome with large lookahead >>analysis. >>.SH "SPECIAL CONSIDERATIONS" >>.PP >>\fIAntlr\fP works... we think. There is no implicit guarantee of >>anything. We reserve no \fBlegal\fP rights to the software known as >>the Purdue Compiler Construction Tool Set (PCCTS) \(em 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. As long as these guidelines are followed, >>we expect to continue enhancing this system and expect to make other >>tools available as they are completed. >>.SH FILES >>.IP *.c >>output C parser >>.IP \fBparser.dlg\fP >>output \fIdlg\fR lexical analyzer >>.IP \fBerr.c\fP >>token string array, error sets and error support routines >>.IP \fBtokens.h\fP >>output \fI#defines\fR for tokens used and function prototypes for >>functions generated for rules >>.IP \fBstdpccts.h\fP >>list of definitions needed by C files, not generated by PCCTS, that >>reference PCCTS objects. This is not generated by default. >>.SH "SEE ALSO" >>.LP >>dlg(1), pccts(1) >EOF_antlr.1 >cat << \EOF_antlr1.txt | sed 's/^>//' > antlr1.txt >> >> >> >>antlr - ANother Tool for Language Recognition >> >> >>antlr [options] grammar_files >> >> >> Antlr converts an extended form of context-free grammar into a >>set of C functions which directly implement an efficient form of >>deterministic recursive-descent LL(k) parser. Context-free grammars >>may be augmented with predicates to allow semantics to influence pars- >>ing; this allows a form of context-sensitive parsing. Antlr also pro- >>duces a definition of a lexer which can be automatically converted >>into C code for a DFA-based lexer by dlg. Hence, antlr serves a func- >>tion much like that of yacc, however, it is notably more flexible and >>is more integrated with a lexer generator (antlr directly generates >>dlg code, whereas yacc and lex are given independent descriptions). >>Unlike yacc which accepts LALR(1) grammars, antlr accepts LL(k) gram- >>mars in an extended BNF notation - which eliminates the need for pre- >>cedence rules. >> >> Like yacc grammars, antlr grammars can use automatically- >>maintained symbol attribute values referenced as dollar variables. >>Further, because antlr generates top-down parsers, arbitrary values >>may be inherited from parent rules (passed like function parameters). >>Antlr also has a mechanism for creating and manipulating abstract- >>syntax-trees. >> >> There are various other niceties in antlr, including the ability >>to spread one grammar over multiple files or even multiple grammars in >>a single file, the ability to generate a version of the grammar with >>actions stripped out (for documentation purposes), and lots more. >> >> >>-cr Generate a cross-reference for all rules. For each rule, print a >> list of all other rules that reference it. >> >>-e1 Ambiguities/errors shown in low detail (default). >> >>-e2 Ambiguities/errors shown in more detail. >> >>-e3 Ambiguities/errors shown in excrutiating detail. >> >>-fe file >> Rename err.c to file. >> >>-fh file >> Rename stdpccts.h header (turns on -gh) to file. >> >>-fl file >> Rename lexical output, parser.dlg, to file. >> >>-ft file >> Rename tokens.h to file. >> >> >> >> >> Page 1 >> >> PCCTS >> >> >>-ga Generate ANSI-compatible code (default case). This has not been >> rigorously tested to be ANSI XJ11 C compliant, but it is close. >> The normal output of antlr is currently compilable under both K&R >> and ANSI C-this option does nothing, but is reserved for the >> future. >> >>-gc Indicates that antlr should generate no C code, i.e., only per- >> form analysis on the grammar. >> >>-gd C code is inserted in each of the antlr generated parsing func- >> tions to provide for user-defined handling of a detailed parse >> trace. The inserted code consists of calls to the user-supplied >> macros or functions called zzTRACEIN and zzTRACEOUT. The only >> argument is a char * pointing to a C-style string which is the >> grammar rule recognized by the current parsing function. If no >> definition is given for the trace functions, upon rule entry and >> exit, a message will be printed indicating that a particular rule >> as been entered or exited. >> >>-ge Generate an error class for each non-terminal. >> >>-gh Generate stdpccts.h for non-ANTLR-generated files to include. >> This file contains all defines needed to describe the type of >> parser generated by antlr (e.g. how much lookahead is used and >> whether or not trees are constructed) and contains the header >> action specified by the user. >> >>-gk Generate parsers that delay lookahead fetches until needed. >> Without this option, antlr generates parsers which always have k >> tokens of lookahead available. This option is incompatible with >> -pr and renders references to LA(i) invalid as one never knows >> when the ith token of lookahead will be fetched. >> >>-gl Generate line info about grammar actions in C parser of the form >> # line "file" which makes error messages from the C/C++ compiler >> make more sense as they will "point" into the grammar file not >> the resulting C file. Debugging is easier as well, because you >> will step through the grammar not C file. >> >>-gp prefix >> Prefix all functions generated from rules with prefix. >> >>-gs Do not generate sets for token expression lists; instead generate >> a ||-separated sequence of LA(1)==token_number. The default is >> to generate sets. >> >>-gt Generate code for Abstract-Syntax Trees. >> >>-gx Do not create the lexical analyzer files (dlg-related). This >> option should be given when the user wishes to provide a custom- >> ized lexical analyzer. It may also be used in make scripts to >> cause only the parser to be rebuilt when a change not affecting >> the lexical structure is made to the input grammars. >> >> >> >> >> Page 2 >> >> PCCTS >> >> >>-k n Set k of LL(k) to n; i.e. set tokens of look-ahead (default==1). >> >>-p The complete grammar, collected from all input grammar files and >> stripped of all comments and embedded actions, is listed to >> stdout. This is intended to aid in viewing the entire grammar as >> a whole and to eliminate the need to keep actions concisely >> stated so that the grammar is easier to read. Hence, it is >> preferable to embed even complex actions directly in the grammar, >> rather than to call them as subroutines, since the subroutine >> call overhead will be saved. >> >>-pa This option is the same as -p except that the output is annotated >> with the first sets determined from grammar analysis. >> >>-pr Turn on use of predicates in parsing decisions (alpha version). >> When a syntactic ambiguity is discovered, antlr searches for >> predicates that can be used to disambiguate the decision. Predi- >> cates have dual roles as semantic validation and disambiguation >> predicates. >> >>-rl Limit the maximum number of tree nodes used by grammar analysis >> to n. Occasionally, antlr is unable to analyze a grammar submit- >> ted by the user. This rare situation can only occur when the >> grammar is large and the amount of lookahead is greater than one. >> A nonlinear analysis algorithm is used by PCCTS to handle the >> general case of LL(k) parsing. The average complexity of >> analysis, however, is near linear due to some fancy footwork in >> the implementation which reduces the number of calls to the full >> LL(k) algorithm. An error message will be displayed, if this >> limit is reached, which indicates the grammar construct being >> analyzed when antlr hit a non-linearity. Use this option if >> antlr seems to go out to lunch and your disk start thrashing; try >> n=10000 to start. Once the offending construct has been identi- >> fied, try to remove the ambiguity that antlr was trying to over- >> come with large lookahead analysis. >> >> >> Antlr works... we think. There is no implicit guarantee of any- >>thing. We reserve no legal rights to the software known as 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. How- >>ever, 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. As long as these guidelines are followed, we expect to con- >>tinue enhancing this system and expect to make other tools available >>as they are completed. >> >> >> >> >> Page 3 >> >> PCCTS >> >> >>*.c output C parser >> >>parser.dlg >> output dlg lexical analyzer >> >>err.ctoken string array, error sets and error support routines >> >>tokens.h >> output #defines for tokens used and function prototypes for func- >> tions generated for rules >> >>stdpccts.h >> list of definitions needed by C files, not generated by PCCTS, >> that reference PCCTS objects. This is not generated by default. >> >> >>dlg(1), pccts(1) >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> >> Page 4 >> >EOF_antlr1.txt EOF_antlr.bag cat << \EOF_dlg.bag | sed 's/^>//' > dlg.bag >cat << \EOF_dlg_p.g | sed 's/^>//' > dlg_p.g >>/* This is the parser for the dlg version 2 >> * This is a part of the Purdue Compiler Construction Toolset >> * 8/18/90 >> * >> * Will Cohen >> * >> */ >> >>#header << >>#include >>#include "dlg.h" >>#ifdef MEMCHK >>#include "trax.h" >>#else >>extern char *malloc(); >>extern char *calloc(); >>#endif >>>> >> >><< >>int action_no = 0; /* keep track of actions outputed */ >>int nfa_allocated = 0; /* keeps track of number of nfa nodes */ >>nfa_node *nfa_array = NULL;/* root of binary tree that stores nfa array */ >>nfa_node nfa_model_node; /* model to initialize new nodes */ >>set used_chars; /* used to label trans. arcs */ >>set used_classes; /* classes or chars used to label trans. arcs */ >>set normal_chars; /* mask to get rid elements that aren't used >> in set */ >>int flag_paren = FALSE; >>int flag_brace = FALSE; >>int mode_counter = 0; /* keep track of number of %%names */ >> >>>> >> >>#lexaction << >>#include "dlgdef.h" >> >>int func_action; /* should actions be turned into functions?*/ >>int lex_mode_counter = 0; /* keeps track of the number of %%names */ >>>> >> >>#token "[\r\t\ ]+" << zzskip(); >> /* Ignore white */ >>#token "[\n]" << zzline++; zzskip(); >> /* Track Line # */ >>#token L_EOF "\@" >>#token PER_PER "\%\%" >>#token NAME_PER_PER "\%\%[a-zA-Z_][a-zA-Z0-9_]*" >> << p_mode_def(&zzlextext[2],lex_mode_counter++); >> >>#token ACTION "\<\<" >> << if (func_action) >> fprintf(OUT,"static void\nact%d()\n{ ", ++action_no); >> zzmode(ACT); zzskip(); >> >> >>#token GREAT_GREAT "\>\>" >>#token L_BRACE "\{" >>#token R_BRACE "\}" >>#token L_PAR "\(" >>#token R_PAR "\)" >>#token L_BRACK "\[" >>#token R_BRACK "\]" >>#token ZERO_MORE "\*" >>#token ONE_MORE "\+" >>#token OR "\|" >>#token RANGE "\-" >>#token NOT "\~" >>#token OCTAL_VALUE "\\0[0-7]*" >> << {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;}>> >>#token HEX_VALUE "\\0[Xx][0-9a-fA-F]+" >> << {int t; sscanf(&zzlextext[1],"%x",&t); zzlextext[0] = t;}>> >>#token DEC_VALUE "\\[1-9][0-9]*" >> << {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;}>> >>#token TAB "\\t" << zzlextext[0] = '\t';>> >>#token NL "\\n" << zzlextext[0] = '\n';>> >>#token CR "\\r" << zzlextext[0] = '\r';>> >>#token BS "\\b" << zzlextext[0] = '\b';>> >>/* NOTE: this takes ANYTHING after the \ */ >>#token LIT "\\~[tnrb]" << zzlextext[0] = zzlextext[1];>> >>/* NOTE: this takes ANYTHING that doesn't match the other tokens */ >>#token REGCHAR "~[\\]" >> >> >>grammar : << p_head(); func_action = FALSE;>> (ACTION)* start_states >> << func_action = FALSE; p_tables(); p_tail(); >> >> (ACTION)* "@" >> ; >> >>start_states : ( PER_PER do_conversion >> | NAME_PER_PER do_conversion (NAME_PER_PER do_conversion)*) >> PER_PER >> ; >> >>do_conversion : <> >> rule_list >> << >> dfa_class_nop[mode_counter] = >> relabel($1.l,comp_level); >> if (comp_level) >> p_shift_table(mode_counter); >> dfa_basep[mode_counter] = dfa_allocated+1; >> make_dfa_model_node(dfa_class_nop[mode_counter]); >> nfa_to_dfa($1.l); >> ++mode_counter; >> func_action = FALSE; >> >> >> ; >> >>rule_list : rule <<$$.l=$1.l; $$.r=$1.r;>> >> (rule >> <<{nfa_node *t1; >> t1 = new_nfa_node(); >> (t1)->trans[0]=$$.l; >> (t1)->trans[1]=$1.l; >> /* all accept nodes "dead ends" */ >> $$.l=t1; $$.r=NULL; >> } >> >> >> )* >> | /* empty */ >> <<$$.l = new_nfa_node(); $$.r = NULL; >> warning("no regular expressions", zzline); >> >> >> ; >> >>rule : reg_expr ACTION >> <<$$.l=$1.l; $$.r=$1.r; ($1.r)->accept=action_no;>> >> | ACTION >> <<$$.l = NULL; $$.r = NULL; >> error("no expression for action ", zzline); >> >> >> ; >> >>reg_expr : and_expr <<$$.l=$1.l; $$.r=$1.r;>> >> (OR and_expr >> <<{nfa_node *t1, *t2; >> t1 = new_nfa_node(); t2 = new_nfa_node(); >> (t1)->trans[0]=$$.l; >> (t1)->trans[1]=$2.l; >> ($$.r)->trans[1]=t2; >> ($2.r)->trans[1]=t2; >> $$.l=t1; $$.r=t2; >> } >> >> >> )* >> ; >> >>and_expr : repeat_expr <<$$.l=$1.l; $$.r=$1.r;>> >> (repeat_expr <<($$.r)->trans[1]=$1.l; $$.r=$1.r;>>)* >> ; >> >>repeat_expr : expr <<$$.l=$1.l; $$.r=$1.r;>> >> { ZERO_MORE >> <<{ nfa_node *t1,*t2; >> ($$.r)->trans[0] = $$.l; >> t1 = new_nfa_node(); t2 = new_nfa_node(); >> t1->trans[0]=$$.l; >> t1->trans[1]=t2; >> ($$.r)->trans[1]=t2; >> $$.l=t1;$$.r=t2; >> } >> >> >> | ONE_MORE >> <<($$.r)->trans[0] = $$.l;>> >> } >> | ZERO_MORE >> << error("no expression for *", zzline);>> >> | ONE_MORE >> << error("no expression for +", zzline);>> >> ; >> >>expr : L_BRACK atom_list R_BRACK >> << $$.l = new_nfa_node(); $$.r = new_nfa_node(); >> ($$.l)->trans[0] = $$.r; >> ($$.l)->label = set_dup($2.label); >> set_orin(&used_chars,($$.l)->label); >> >> >> | NOT L_BRACK atom_list R_BRACK >> << $$.l = new_nfa_node(); $$.r = new_nfa_node(); >> ($$.l)->trans[0] = $$.r; >> ($$.l)->label = set_dif(normal_chars,$3.label); >> set_orin(&used_chars,($$.l)->label); >> >> >> | L_PAR reg_expr R_PAR >> << $$.l = new_nfa_node(); $$.r = new_nfa_node(); >> ($$.l)->trans[0] = $2.l; >> ($2.r)->trans[1] = $$.r; >> >> >> | L_BRACE reg_expr R_BRACE >> << $$.l = new_nfa_node(); $$.r = new_nfa_node(); >> ($$.l)->trans[0] = $2.l; >> ($$.l)->trans[1] = $$.r; >> ($2.r)->trans[1] = $$.r; >> >> >> | atom >> << $$.l = new_nfa_node(); $$.r = new_nfa_node(); >> ($$.l)->trans[0] = $$.r; >> ($$.l)->label = set_dup($1.label); >> set_orin(&used_chars,($$.l)->label); >> >> >> ; >> >>atom_list : << set_free($$.label); >> >> (near_atom <>)* >> ; >> >>near_atom : << register int i; >> register int i_prime; >> >> >> anychar >> <<$$.letter=$1.letter; $$.label=set_of($1.letter); >> i_prime = $1.letter + MIN_CHAR; >> if (case_insensitive && islower(i_prime)) >> set_orel(toupper(i_prime)-MIN_CHAR, >> &($$.label)); >> if (case_insensitive && isupper(i_prime)) >> set_orel(tolower(i_prime)-MIN_CHAR, >> &($$.label)); >> >> >> { RANGE anychar >> << for (i=$$.letter; i<= $2.letter; ++i){ >> set_orel(i,&($$.label)); >> i_prime = i+MIN_CHAR; >> if (case_insensitive && islower(i_prime)) >> set_orel(toupper(i_prime)-MIN_CHAR, >> &($$.label)); >> if (case_insensitive && isupper(i_prime)) >> set_orel(tolower(i_prime)-MIN_CHAR, >> &($$.label)); >> } >> >> >> } >> ; >> >>atom : << register int i_prime;>> >> anychar >> <<$$.label = set_of($1.letter); >> i_prime = $1.letter + MIN_CHAR; >> if (case_insensitive && islower(i_prime)) >> set_orel(toupper(i_prime)-MIN_CHAR, >> &($$.label)); >> if (case_insensitive && isupper(i_prime)) >> set_orel(tolower(i_prime)-MIN_CHAR, >> &($$.label)); >> >> >> ; >> >>anychar : REGCHAR <<$$.letter = $1.letter - MIN_CHAR;>> >> | OCTAL_VALUE <<$$.letter = $1.letter - MIN_CHAR;>> >> | HEX_VALUE <<$$.letter = $1.letter - MIN_CHAR;>> >> | DEC_VALUE <<$$.letter = $1.letter - MIN_CHAR;>> >> | TAB <<$$.letter = $1.letter - MIN_CHAR;>> >> | NL <<$$.letter = $1.letter - MIN_CHAR;>> >> | CR <<$$.letter = $1.letter - MIN_CHAR;>> >> | BS <<$$.letter = $1.letter - MIN_CHAR;>> >> | LIT <<$$.letter = $1.letter - MIN_CHAR;>> >> /* NOTE: LEX_EOF is ALWAYS shifted to 0 = MIN_CHAR - MIN_CHAR*/ >> | L_EOF <<$$.letter = 0;>> >> ; >> >><> >> >>#lexclass ACT >>#token "@" << error("unterminated action", zzline); zzmode(START); >> >>#token ACTION "\>\>" >> << if (func_action) fprintf(OUT,"}\n\n"); >> zzmode(START); >> >> >>#token "\>" << putc(zzlextext[0], OUT); zzskip(); >> >>#token "\\\>" << putc('>', OUT); zzskip(); >> >>#token "\\" << putc('\\', OUT); zzskip(); >> >>#token "\n" << putc(zzlextext[0], OUT); ++zzline; zzskip(); >> >>#token "~[\>\\@\n]+" << fprintf(OUT, "%s", &(zzlextext[0])); zzskip(); >> >> >><< >>/* finds nfa state i in the binary tree nfa_array */ >>nfa_node *index_nfa(i) >>register int i; >>{ >> register nfa_node *p = nfa_array; >> >> if (i){ >> while((i>1) && p){ >> if(i & 1) >> p = p->right; >> else >> p = p->left; >> i = i\>\>1; >> } >> return p; >> }else{ >> return NIL_INDEX; >> } >>} >> >> >>/* adds a new nfa to the binary tree and returns a pointer to it */ >>nfa_node *new_nfa_node() >>{ >> register nfa_node *p = nfa_array; >> nfa_node *t; >> register int i; >> >> i = ++nfa_allocated; >> >> t = (nfa_node*) malloc(sizeof(nfa_node)); >> *t = nfa_model_node; >> t->node_no = i; >> >> while((i>3) && p){ >> if(i & 1) >> p = p->right; >> else >> p = p->left; >> i = i\>\>1; >> } >> if (nfa_allocated == 1) >> nfa_array = t; >> else if (p != NIL_INDEX){ >> if (i & 1) >> p->right = t; >> else >> p->left = t; >> } >> else{ >> internal_error("%s(%d): missing node on binary tree\n", >> __FILE__,__LINE__); >> } >> return t; >>} >> >>/* initialize the model node used to fill in newly made nfa_nodes */ >>make_nfa_model_node() >>{ >> nfa_model_node.left = NULL; >> nfa_model_node.right = NULL; >> nfa_model_node.node_no = -1; /* impossible value for real nfa node */ >> nfa_model_node.nfa_set = 0; >> nfa_model_node.accept = 0; /* error state default*/ >> nfa_model_node.trans[0] = NULL; >> nfa_model_node.trans[1] = NULL; >> nfa_model_node.label = empty; >> >>} >>>> >EOF_dlg_p.g >cat << \EOF_dlg_a.c | sed 's/^>//' > dlg_a.c >> >>/* parser.dlg -- DLG Description of scanner >> * >> * Generated from: dlg_p.g >> * >> * Terence Parr, Hank Dietz and Will Cohen: 1989-1992 >> * Purdue University Electrical Engineering >> * ANTLR Version 1.06 >> */ >>#include >>#include >>#include "dlg.h" >>#ifdef MEMCHK >>#include "trax.h" >>#else >>extern char *malloc(); >>extern char *calloc(); >>#endif >>#include "antlr.h" >>#include "tokens.h" >>#include "dlgdef.h" >>LOOKAHEAD >>void zzerraction() >>{ >> (*zzerr)("invalid token"); >> zzadvance(); >> zzskip(); >>} >>/* >> * D L G tables >> * >> * Generated from: parser.dlg >> * >> * 1989-1992 by Will Cohen, Terence Parr, and Hank Dietz >> * Purdue University Electrical Engineering >> * DLG Version 1.06 >> */ >> >>#include "mode.h" >> >> >> >>#include "dlgdef.h" >>int func_action; /* should actions be turned into functions?*/ >>int lex_mode_counter = 0; /* keeps track of the number of %%names */ >>static void >>act1() >>{ >> NLA = 1; >> } >> >>static void >>act2() >>{ >> NLA = 2; >> zzskip(); >> } >> >>static void >>act3() >>{ >> NLA = 3; >> zzline++; zzskip(); >> } >> >>static void >>act4() >>{ >> NLA = L_EOF; >> } >> >>static void >>act5() >>{ >> NLA = PER_PER; >> } >> >>static void >>act6() >>{ >> NLA = NAME_PER_PER; >> p_mode_def(&zzlextext[2],lex_mode_counter++); >> } >> >>static void >>act7() >>{ >> NLA = ACTION; >> if (func_action) >> fprintf(OUT,"static void\nact%d()\n{ ", ++action_no); >> zzmode(ACT); zzskip(); >> } >> >>static void >>act8() >>{ >> NLA = GREAT_GREAT; >> } >> >>static void >>act9() >>{ >> NLA = L_BRACE; >> } >> >>static void >>act10() >>{ >> NLA = R_BRACE; >> } >> >>static void >>act11() >>{ >> NLA = L_PAR; >> } >> >>static void >>act12() >>{ >> NLA = R_PAR; >> } >> >>static void >>act13() >>{ >> NLA = L_BRACK; >> } >> >>static void >>act14() >>{ >> NLA = R_BRACK; >> } >> >>static void >>act15() >>{ >> NLA = ZERO_MORE; >> } >> >>static void >>act16() >>{ >> NLA = ONE_MORE; >> } >> >>static void >>act17() >>{ >> NLA = OR; >> } >> >>static void >>act18() >>{ >> NLA = RANGE; >> } >> >>static void >>act19() >>{ >> NLA = NOT; >> } >> >>static void >>act20() >>{ >> NLA = OCTAL_VALUE; >> {int t; sscanf(&zzlextext[1],"%o",&t); zzlextext[0] = t;} >> } >> >>static void >>act21() >>{ >> NLA = HEX_VALUE; >> {int t; sscanf(&zzlextext[1],"%x",&t); zzlextext[0] = t;} >> } >> >>static void >>act22() >>{ >> NLA = DEC_VALUE; >> {int t; sscanf(&zzlextext[1],"%d",&t); zzlextext[0] = t;} >> } >> >>static void >>act23() >>{ >> NLA = TAB; >> zzlextext[0] = '\t'; >> } >> >>static void >>act24() >>{ >> NLA = NL; >> zzlextext[0] = '\n'; >> } >> >>static void >>act25() >>{ >> NLA = CR; >> zzlextext[0] = '\r'; >> } >> >>static void >>act26() >>{ >> NLA = BS; >> zzlextext[0] = '\b'; >> } >> >>static void >>act27() >>{ >> NLA = LIT; >> zzlextext[0] = zzlextext[1]; >> } >> >>static void >>act28() >>{ >> NLA = REGCHAR; >> } >> >>unsigned char shift0[257] = { >> 0, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 1, 2, 29, 29, 1, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 1, 29, 29, 29, 29, 4, 29, >> 29, 19, 20, 23, 24, 29, 26, 29, 29, 12, >> 13, 13, 13, 13, 13, 13, 13, 14, 14, 29, >> 29, 15, 29, 16, 29, 3, 7, 7, 7, 7, >> 7, 7, 11, 11, 11, 11, 11, 11, 11, 11, >> 11, 11, 11, 11, 11, 11, 11, 11, 11, 5, >> 11, 11, 21, 28, 22, 29, 11, 29, 7, 6, >> 7, 7, 7, 7, 11, 11, 11, 11, 11, 11, >> 11, 9, 11, 11, 11, 10, 11, 8, 11, 11, >> 11, 5, 11, 11, 17, 25, 18, 27, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 29, 29, 29, 29, >> 29, 29, 29, 29, 29, 29, 30 >>}; >> >>static void >>act29() >>{ >> NLA = 1; >> error("unterminated action", zzline); zzmode(START); >> } >> >>static void >>act30() >>{ >> NLA = ACTION; >> if (func_action) fprintf(OUT,"}\n\n"); >> zzmode(START); >> } >> >>static void >>act31() >>{ >> NLA = 29; >> putc(zzlextext[0], OUT); zzskip(); >> } >> >>static void >>act32() >>{ >> NLA = 30; >> putc('>', OUT); zzskip(); >> } >> >>static void >>act33() >>{ >> NLA = 31; >> putc('\\', OUT); zzskip(); >> } >> >>static void >>act34() >>{ >> NLA = 32; >> putc(zzlextext[0], OUT); ++zzline; zzskip(); >> } >> >>static void >>act35() >>{ >> NLA = 33; >> fprintf(OUT, "%s", &(zzlextext[0])); zzskip(); >> } >> >>unsigned char shift1[257] = { >> 0, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 3, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 1, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 2, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, >> 4, 4, 4, 4, 4, 4, 5 >>}; >> >>#define DfaStates 46 >>typedef unsigned char DfaState; >> >>static DfaState st0[31] = { >> 1, 2, 3, 4, 5, 6, 6, 6, 6, 6, >> 6, 6, 6, 6, 6, 7, 8, 9, 10, 11, >> 12, 13, 14, 15, 16, 17, 18, 19, 20, 6, >> 46 >>}; >> >>static DfaState st1[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st2[31] = { >> 46, 21, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st3[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st4[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st5[31] = { >> 46, 46, 46, 46, 22, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st6[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st7[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 23, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st8[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 24, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st9[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st10[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st11[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st12[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st13[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st14[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st15[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st16[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st17[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st18[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st19[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st20[31] = { >> 46, 25, 25, 25, 25, 25, 26, 25, 27, 28, >> 29, 25, 30, 31, 31, 25, 25, 25, 25, 25, >> 25, 25, 25, 25, 25, 25, 25, 25, 25, 25, >> 46 >>}; >> >>static DfaState st21[31] = { >> 46, 21, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st22[31] = { >> 46, 46, 46, 46, 46, 32, 32, 32, 32, 32, >> 32, 32, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st23[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st24[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st25[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st26[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st27[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st28[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st29[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st30[31] = { >> 46, 46, 46, 46, 46, 33, 46, 46, 46, 46, >> 46, 46, 34, 34, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st31[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 35, 35, 35, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st32[31] = { >> 46, 46, 46, 46, 46, 36, 36, 36, 36, 36, >> 36, 36, 36, 36, 36, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st33[31] = { >> 46, 46, 46, 46, 46, 46, 37, 37, 46, 46, >> 46, 46, 37, 37, 37, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st34[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 34, 34, 46, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st35[31] = { >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46, 46, 35, 35, 35, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st36[31] = { >> 46, 46, 46, 46, 46, 36, 36, 36, 36, 36, >> 36, 36, 36, 36, 36, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st37[31] = { >> 46, 46, 46, 46, 46, 46, 37, 37, 46, 46, >> 46, 46, 37, 37, 37, 46, 46, 46, 46, 46, >> 46, 46, 46, 46, 46, 46, 46, 46, 46, 46, >> 46 >>}; >> >>static DfaState st38[6] = { >> 39, 40, 41, 42, 43, 46 >>}; >> >>static DfaState st39[6] = { >> 46, 46, 46, 46, 46, 46 >>}; >> >>static DfaState st40[6] = { >> 46, 44, 46, 46, 46, 46 >>}; >> >>static DfaState st41[6] = { >> 46, 45, 46, 46, 46, 46 >>}; >> >>static DfaState st42[6] = { >> 46, 46, 46, 46, 46, 46 >>}; >> >>static DfaState st43[6] = { >> 46, 46, 46, 46, 43, 46 >>}; >> >>static DfaState st44[6] = { >> 46, 46, 46, 46, 46, 46 >>}; >> >>static DfaState st45[6] = { >> 46, 46, 46, 46, 46, 46 >>}; >> >> >>DfaState *dfa[46] = { >> st0, >> st1, >> st2, >> st3, >> st4, >> st5, >> st6, >> st7, >> st8, >> st9, >> st10, >> st11, >> st12, >> st13, >> st14, >> st15, >> st16, >> st17, >> st18, >> st19, >> st20, >> st21, >> st22, >> st23, >> st24, >> st25, >> st26, >> st27, >> st28, >> st29, >> st30, >> st31, >> st32, >> st33, >> st34, >> st35, >> st36, >> st37, >> st38, >> st39, >> st40, >> st41, >> st42, >> st43, >> st44, >> st45 >>}; >> >> >>DfaState accepts[46] = { >> 0, 1, 2, 3, 4, 28, 28, 28, 28, 9, >> 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, >> 0, 2, 5, 7, 8, 27, 26, 23, 24, 25, >> 20, 22, 6, 0, 20, 22, 6, 21, 0, 29, >> 31, 33, 34, 35, 30, 32 >>}; >> >>void (*actions[36])() = { >> zzerraction, >> act1, >> act2, >> act3, >> act4, >> act5, >> act6, >> act7, >> act8, >> act9, >> act10, >> act11, >> act12, >> act13, >> act14, >> act15, >> act16, >> act17, >> act18, >> act19, >> act20, >> act21, >> act22, >> act23, >> act24, >> act25, >> act26, >> act27, >> act28, >> act29, >> act30, >> act31, >> act32, >> act33, >> act34, >> act35 >>}; >> >>static int dfa_base[] = { >> 0, >> 38 >>}; >> >>static int dfa_class_no[] = { >> 30, >> 5 >>}; >> >>static unsigned char *b_class_no[] = { >> shift0, >> shift1 >>}; >> >> >> >>#define ZZSHIFT(c) (b_class_no[zzauto][1+c]) >>#define MAX_MODE 2 >>#include "dlgauto.h" >EOF_dlg_a.c >cat << \EOF_dlg_p.c | sed 's/^>//' > dlg_p.c >>/* >> * A n t l r T r a n s l a t i o n H e a d e r >> * >> * Terence Parr, Hank Dietz and Will Cohen: 1989-1992 >> * Purdue University Electrical Engineering >> * ANTLR Version 1.06 >> */ >>#include >>#include >>#include "dlg.h" >>#ifdef MEMCHK >>#include "trax.h" >>#else >>extern char *malloc(); >>extern char *calloc(); >>#endif >>#include "antlr.h" >>#include "tokens.h" >>#include "dlgdef.h" >>#include "mode.h" >>ANTLR_INFO >>int action_no = 0; /* keep track of actions outputed */ >>int nfa_allocated = 0; /* keeps track of number of nfa nodes */ >>nfa_node *nfa_array = NULL;/* root of binary tree that stores nfa array */ >>nfa_node nfa_model_node; /* model to initialize new nodes */ >>set used_chars; /* used to label trans. arcs */ >>set used_classes; /* classes or chars used to label trans. arcs */ >>set normal_chars; /* mask to get rid elements that aren't used >>in set */ >>int flag_paren = FALSE; >>int flag_brace = FALSE; >>int mode_counter = 0; /* keep track of number of %%names */ >> >>#ifdef __STDC__ >>void >>grammar() >>#else >>grammar() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> p_head(); func_action = FALSE; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> while ( (LA(1)==ACTION) ) { >> zzmatch(ACTION); zzCONSUME; >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> start_states(); >> func_action = FALSE; p_tables(); p_tail(); >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> while ( (LA(1)==ACTION) ) { >> zzmatch(ACTION); zzCONSUME; >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> zzmatch(1); zzCONSUME; >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x1); >> } >>} >> >>#ifdef __STDC__ >>void >>start_states() >>#else >>start_states() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==PER_PER) ) { >> zzmatch(PER_PER); zzCONSUME; >> do_conversion(); >> } >> else if ( (LA(1)==NAME_PER_PER) ) { >> zzmatch(NAME_PER_PER); zzCONSUME; >> do_conversion(); >> { >> zzBLOCK(zztasp3); >> zzMake0; >> { >> while ( (LA(1)==NAME_PER_PER) ) { >> zzmatch(NAME_PER_PER); zzCONSUME; >> do_conversion(); >> zzLOOP(zztasp3); >> } >> zzEXIT(zztasp3); >> } >> } >> } >> else {zzFAIL(1,zzerr1,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp2); >> } >> } >> zzmatch(PER_PER); zzCONSUME; >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x2); >> } >>} >> >>#ifdef __STDC__ >>void >>do_conversion() >>#else >>do_conversion() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> new_automaton_mode(); func_action = TRUE; >> rule_list(); >> dfa_class_nop[mode_counter] = >> relabel(zzaArg(zztasp1,1 ).l,comp_level); >> if (comp_level) >> p_shift_table(mode_counter); >> dfa_basep[mode_counter] = dfa_allocated+1; >> make_dfa_model_node(dfa_class_nop[mode_counter]); >> nfa_to_dfa(zzaArg(zztasp1,1 ).l); >> ++mode_counter; >> func_action = FALSE; >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x4); >> } >>} >> >>#ifdef __STDC__ >>void >>rule_list() >>#else >>rule_list() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> if ( (setwd1[LA(1)]&0x8) ) { >> rule(); >> zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> while ( (setwd1[LA(1)]&0x10) ) { >> rule(); >> {nfa_node *t1; >> t1 = new_nfa_node(); >> (t1)->trans[0]=zzaRet.l; >> (t1)->trans[1]=zzaArg(zztasp2,1 ).l; >> /* all accept nodes "dead ends" */ >> zzaRet.l=t1; zzaRet.r=NULL; >> } >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> } >> else if ( (setwd1[LA(1)]&0x20) ) { >> zzaRet.l = new_nfa_node(); zzaRet.r = NULL; >> warning("no regular expressions", zzline); >> } >> else {zzFAIL(1,zzerr2,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x40); >> } >>} >> >>#ifdef __STDC__ >>void >>rule() >>#else >>rule() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> if ( (setwd1[LA(1)]&0x80) ) { >> reg_expr(); >> zzmatch(ACTION); >> zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; (zzaArg(zztasp1,1 ).r)->accept=action_no; >> zzCONSUME; >> } >> else if ( (LA(1)==ACTION) ) { >> zzmatch(ACTION); >> zzaRet.l = NULL; zzaRet.r = NULL; >> error("no expression for action ", zzline); >> zzCONSUME; >> } >> else {zzFAIL(1,zzerr3,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x100); >> } >>} >> >>#ifdef __STDC__ >>void >>reg_expr() >>#else >>reg_expr() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> and_expr(); >> zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> while ( (LA(1)==OR) ) { >> zzmatch(OR); zzCONSUME; >> and_expr(); >> {nfa_node *t1, *t2; >> t1 = new_nfa_node(); t2 = new_nfa_node(); >> (t1)->trans[0]=zzaRet.l; >> (t1)->trans[1]=zzaArg(zztasp2,2 ).l; >> (zzaRet.r)->trans[1]=t2; >> (zzaArg(zztasp2,2 ).r)->trans[1]=t2; >> zzaRet.l=t1; zzaRet.r=t2; >> } >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x200); >> } >>} >> >>#ifdef __STDC__ >>void >>and_expr() >>#else >>and_expr() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> repeat_expr(); >> zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> while ( (setwd1[LA(1)]&0x400) ) { >> repeat_expr(); >> (zzaRet.r)->trans[1]=zzaArg(zztasp2,1 ).l; zzaRet.r=zzaArg(zztasp2,1 ).r; >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x800); >> } >>} >> >>#ifdef __STDC__ >>void >>repeat_expr() >>#else >>repeat_expr() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> if ( (setwd1[LA(1)]&0x1000) ) { >> expr(); >> zzaRet.l=zzaArg(zztasp1,1 ).l; zzaRet.r=zzaArg(zztasp1,1 ).r; >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==ZERO_MORE) ) { >> zzmatch(ZERO_MORE); >> { nfa_node *t1,*t2; >> (zzaRet.r)->trans[0] = zzaRet.l; >> t1 = new_nfa_node(); t2 = new_nfa_node(); >> t1->trans[0]=zzaRet.l; >> t1->trans[1]=t2; >> (zzaRet.r)->trans[1]=t2; >> zzaRet.l=t1;zzaRet.r=t2; >> } >> zzCONSUME; >> } >> else if ( (LA(1)==ONE_MORE) ) { >> zzmatch(ONE_MORE); >> (zzaRet.r)->trans[0] = zzaRet.l; >> zzCONSUME; >> } >> zzEXIT(zztasp2); >> } >> } >> } >> else if ( (LA(1)==ZERO_MORE) ) { >> zzmatch(ZERO_MORE); >> error("no expression for *", zzline); >> zzCONSUME; >> } >> else if ( (LA(1)==ONE_MORE) ) { >> zzmatch(ONE_MORE); >> error("no expression for +", zzline); >> zzCONSUME; >> } >> else {zzFAIL(1,zzerr4,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x2000); >> } >>} >> >>#ifdef __STDC__ >>void >>expr() >>#else >>expr() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> if ( (LA(1)==L_BRACK) ) { >> zzmatch(L_BRACK); zzCONSUME; >> atom_list(); >> zzmatch(R_BRACK); >> zzaRet.l = new_nfa_node(); zzaRet.r = new_nfa_node(); >> (zzaRet.l)->trans[0] = zzaRet.r; >> (zzaRet.l)->label = set_dup(zzaArg(zztasp1,2 ).label); >> set_orin(&used_chars,(zzaRet.l)->label); >> zzCONSUME; >> } >> else if ( (LA(1)==NOT) ) { >> zzmatch(NOT); zzCONSUME; >> zzmatch(L_BRACK); zzCONSUME; >> atom_list(); >> zzmatch(R_BRACK); >> zzaRet.l = new_nfa_node(); zzaRet.r = new_nfa_node(); >> (zzaRet.l)->trans[0] = zzaRet.r; >> (zzaRet.l)->label = set_dif(normal_chars,zzaArg(zztasp1,3 ).label); >> set_orin(&used_chars,(zzaRet.l)->label); >> zzCONSUME; >> } >> else if ( (LA(1)==L_PAR) ) { >> zzmatch(L_PAR); zzCONSUME; >> reg_expr(); >> zzmatch(R_PAR); >> zzaRet.l = new_nfa_node(); zzaRet.r = new_nfa_node(); >> (zzaRet.l)->trans[0] = zzaArg(zztasp1,2 ).l; >> (zzaArg(zztasp1,2 ).r)->trans[1] = zzaRet.r; >> zzCONSUME; >> } >> else if ( (LA(1)==L_BRACE) ) { >> zzmatch(L_BRACE); zzCONSUME; >> reg_expr(); >> zzmatch(R_BRACE); >> zzaRet.l = new_nfa_node(); zzaRet.r = new_nfa_node(); >> (zzaRet.l)->trans[0] = zzaArg(zztasp1,2 ).l; >> (zzaRet.l)->trans[1] = zzaRet.r; >> (zzaArg(zztasp1,2 ).r)->trans[1] = zzaRet.r; >> zzCONSUME; >> } >> else if ( (setwd1[LA(1)]&0x4000) ) { >> atom(); >> zzaRet.l = new_nfa_node(); zzaRet.r = new_nfa_node(); >> (zzaRet.l)->trans[0] = zzaRet.r; >> (zzaRet.l)->label = set_dup(zzaArg(zztasp1,1 ).label); >> set_orin(&used_chars,(zzaRet.l)->label); >> } >> else {zzFAIL(1,zzerr5,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x8000); >> } >>} >> >>#ifdef __STDC__ >>void >>atom_list() >>#else >>atom_list() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> set_free(zzaRet.label); >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> while ( (setwd1[LA(1)]&0x10000) ) { >> near_atom(); >> set_orin(&(zzaRet.label),zzaArg(zztasp2,1 ).label); >> zzLOOP(zztasp2); >> } >> zzEXIT(zztasp2); >> } >> } >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x20000); >> } >>} >> >>#ifdef __STDC__ >>void >>near_atom() >>#else >>near_atom() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> register int i; >> register int i_prime; >> anychar(); >> zzaRet.letter=zzaArg(zztasp1,1 ).letter; zzaRet.label=set_of(zzaArg(zztasp1,1 ).letter); >> i_prime = zzaArg(zztasp1,1 ).letter + MIN_CHAR; >> if (case_insensitive && islower(i_prime)) >> set_orel(toupper(i_prime)-MIN_CHAR, >> &(zzaRet.label)); >> if (case_insensitive && isupper(i_prime)) >> set_orel(tolower(i_prime)-MIN_CHAR, >> &(zzaRet.label)); >> { >> zzBLOCK(zztasp2); >> zzMake0; >> { >> if ( (LA(1)==RANGE) ) { >> zzmatch(RANGE); zzCONSUME; >> anychar(); >> for (i=zzaRet.letter; i<= zzaArg(zztasp2,2 ).letter; ++i){ >> set_orel(i,&(zzaRet.label)); >> i_prime = i+MIN_CHAR; >> if (case_insensitive && islower(i_prime)) >> set_orel(toupper(i_prime)-MIN_CHAR, >> &(zzaRet.label)); >> if (case_insensitive && isupper(i_prime)) >> set_orel(tolower(i_prime)-MIN_CHAR, >> &(zzaRet.label)); >> } >> } >> zzEXIT(zztasp2); >> } >> } >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x40000); >> } >>} >> >>#ifdef __STDC__ >>void >>atom() >>#else >>atom() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> register int i_prime; >> anychar(); >> zzaRet.label = set_of(zzaArg(zztasp1,1 ).letter); >> i_prime = zzaArg(zztasp1,1 ).letter + MIN_CHAR; >> if (case_insensitive && islower(i_prime)) >> set_orel(toupper(i_prime)-MIN_CHAR, >> &(zzaRet.label)); >> if (case_insensitive && isupper(i_prime)) >> set_orel(tolower(i_prime)-MIN_CHAR, >> &(zzaRet.label)); >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x80000); >> } >>} >> >>#ifdef __STDC__ >>void >>anychar() >>#else >>anychar() >>#endif >>{ >> zzRULE; >> zzBLOCK(zztasp1); >> zzMake0; >> { >> if ( (LA(1)==REGCHAR) ) { >> zzmatch(REGCHAR); >> zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; >> zzCONSUME; >> } >> else if ( (LA(1)==OCTAL_VALUE) ) { >> zzmatch(OCTAL_VALUE); >> zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; >> zzCONSUME; >> } >> else if ( (LA(1)==HEX_VALUE) ) { >> zzmatch(HEX_VALUE); >> zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; >> zzCONSUME; >> } >> else if ( (LA(1)==DEC_VALUE) ) { >> zzmatch(DEC_VALUE); >> zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; >> zzCONSUME; >> } >> else if ( (LA(1)==TAB) ) { >> zzmatch(TAB); >> zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; >> zzCONSUME; >> } >> else if ( (LA(1)==NL) ) { >> zzmatch(NL); >> zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; >> zzCONSUME; >> } >> else if ( (LA(1)==CR) ) { >> zzmatch(CR); >> zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; >> zzCONSUME; >> } >> else if ( (LA(1)==BS) ) { >> zzmatch(BS); >> zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; >> zzCONSUME; >> } >> else if ( (LA(1)==LIT) ) { >> zzmatch(LIT); >> zzaRet.letter = zzaArg(zztasp1,1 ).letter - MIN_CHAR; >> zzCONSUME; >> } >> else if ( (LA(1)==L_EOF) ) { >> zzmatch(L_EOF); >> zzaRet.letter = 0; >> zzCONSUME; >> } >> else {zzFAIL(1,zzerr6,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText,&zzErrk); goto fail;} >> zzEXIT(zztasp1); >> return; >>fail: >> zzEXIT(zztasp1); >> /* empty action */ >> zzsyn(zzMissText, zzBadTok, "", zzMissSet, zzMissTok, zzErrk, zzBadText); >> zzresynch(setwd1, 0x100000); >> } >>} >>/* finds nfa state i in the binary tree nfa_array */ >>nfa_node *index_nfa(i) >>register int i; >>{ >> register nfa_node *p = nfa_array; >> if (i){ >> while((i>1) && p){ >> if(i & 1) >> p = p->right; >> else >> p = p->left; >> i = i>>1; >> } >> return p; >> }else{ >> return NIL_INDEX; >> } >>} >>/* adds a new nfa to the binary tree and returns a pointer to it */ >>nfa_node *new_nfa_node() >>{ >> register nfa_node *p = nfa_array; >> nfa_node *t; >> register int i; >> i = ++nfa_allocated; >> t = (nfa_node*) malloc(sizeof(nfa_node)); >> *t = nfa_model_node; >> t->node_no = i; >> while((i>3) && p){ >> if(i & 1) >> p = p->right; >> else >> p = p->left; >> i = i>>1; >> } >> if (nfa_allocated == 1) >> nfa_array = t; >> else if (p != NIL_INDEX){ >> if (i & 1) >> p->right = t; >> else >> p->left = t; >> } >> else{ >> internal_error("%s(%d): missing node on binary tree\n", >> __FILE__,__LINE__); >> } >> return t; >>} >>/* initialize the model node used to fill in newly made nfa_nodes */ >>make_nfa_model_node() >>{ >> nfa_model_node.left = NULL; >> nfa_model_node.right = NULL; >> nfa_model_node.node_no = -1; /* impossible value for real nfa node */ >> nfa_model_node.nfa_set = 0; >> nfa_model_node.accept = 0; /* error state default*/ >> nfa_model_node.trans[0] = NULL; >> nfa_model_node.trans[1] = NULL; >> nfa_model_node.label = empty; >>} >EOF_dlg_p.c >cat << \EOF_main.c | sed 's/^>//' > main.c >>/* Main function for dlg version >> * >> * Will Cohen >> * 8/23/90 >> */ >> >>#include >>#include "dlg.h" >>#include "dlgdef.h" >>#include "antlr.h" >>#ifdef MEMCHK >>#include "trax.h" >>#endif >> >>char version[] = "1.06"; >>int numfiles = 0; >>char *file_str[2] = {NULL, NULL}; >>char *mode_file = "mode.h"; >> >>/* Option variables */ >>int comp_level = 0; >>int interactive = FALSE; >>int case_insensitive = FALSE; >> >>/* Option List Stuff */ >>void p_comp0() {comp_level = 0;} >>void p_comp1() {comp_level = 1;} >>void p_comp2() {comp_level = 2;} >>void p_stdio() { file_str[numfiles++] = NULL;} >>void p_file(s) char *s; { file_str[numfiles++] = s;} >>void p_mode_file(s,t) char *s,*t;{mode_file=t;} >>void p_ansi() {gen_ansi = TRUE;} >>void p_interactive() {interactive = TRUE;} >>void p_case_s() { case_insensitive = FALSE; } >>void p_case_i() { case_insensitive = TRUE; } >> >>typedef struct { >> char *option; >> int arg; >> void (*process)(); >> char *descr; >> } Opt; >> >>Opt options[] = { >> { "-C0", 0, p_comp0, "No compression" }, >> { "-C1", 0, p_comp1, "Compression level 1" }, >> { "-C2", 0, p_comp2, "Compression level 2" }, >> { "-ga", 0, p_ansi, "Generate ansi C"}, >> { "-m", 1, p_mode_file, "Rename lexical mode output file"}, >> { "-i", 0, p_interactive, "Build interactive scanner"}, >> { "-ci", 0, p_case_i, "Make lexical analyzer case insensitive"}, >> { "-cs", 0, p_case_s, "Make lexical analyzer case sensitive"}, >> { "-", 0, p_stdio, "Use standard i/o rather than file"}, >> { "*", 0, p_file, ""}, /* anything else is a file */ >> { NULL, 0, NULL } >>}; >> >>int main(argc,argv) >>int argc; >>char *argv[]; >>{ >> init(); >> fprintf(stderr, "%s Version %s 1989-1992\n", argv[0], version); >> if ( argc == 1 ) >> { >> Opt *p = options; >> fprintf(stderr, "%s [options] f1 f2 ... fn\n",argv[0]); >> while ( *(p->option) != '*' ) >> { >> fprintf(stderr, "\t%s %s\t%s\n", >> p->option, >> (p->arg)?"___":" ", >> p->descr); >> p++; >> } >> }else{ >> ProcessArgs(argc-1, &(argv[1]), options); >> if (input_stream = read_stream(file_str[0])){ >> /* don't overwrite unless input okay */ >> output_stream = write_stream(file_str[1]); >> mode_stream = write_stream(mode_file); >> } >> /* make sure that error reporting routines in grammar >> know what the file really is */ >> /* make sure that reading and writing somewhere */ >> if (input_stream && output_stream && mode_stream){ >> ANTLR(grammar(), input_stream); >> } >> } >> return err_found; >>} >> >> >>ProcessArgs(argc, argv, options) >>int argc; >>char **argv; >>Opt *options; >>{ >> Opt *p; >> >> while ( argc-- > 0 ) >> { >> p = options; >> while ( p->option != NULL ) >> { >> if ( strcmp(p->option, "*") == 0 || >> strcmp(p->option, *argv) == 0 ) >> { >> if ( p->arg ) >> { >> (*p->process)( *argv, *(argv+1) ); >> argv++; >> argc--; >> } >> else >> (*p->process)( *argv ); >> break; >> } >> p++; >> } >> argv++; >> } >>} >> >>/* initialize all the variables */ >>init() >>{ >> register int i; >> >> used_chars = empty; >> used_classes = empty; >> /* make the valid character set */ >> normal_chars = empty; >> /* NOTE: MIN_CHAR is EOF */ >> /* NOTE: EOF is not quite a valid char, it is special. Skip it*/ >> for (i = 1; i> set_orel(i,&normal_chars); >> } >> make_nfa_model_node(); >> clear_hash(); >> /* NOTE: need to set this flag before the lexer starts getting */ >> /* tokens */ >> func_action = FALSE; >>} >> >>/* stuff that needs to be reset when a new automaton is being built */ >>new_automaton_mode() >>{ >> set_free(used_chars); >> clear_hash(); >>} >EOF_main.c >cat << \EOF_err.c | sed 's/^>//' > err.c >>/* >> * A n t l r S e t s / E r r o r F i l e H e a d e r >> * >> * Generated from: dlg_p.g >> * >> * Terence Parr, Hank Dietz and Will Cohen: 1989-1992 >> * Purdue University Electrical Engineering >> * ANTLR Version 1.06 >> */ >> >>#include >>#include >>#include "dlg.h" >>#ifdef MEMCHK >>#include "trax.h" >>#else >>extern char *malloc(); >>extern char *calloc(); >>#endif >>#define zzEOF_TOKEN 1 >>#define zzSET_SIZE 2 >>#include "antlr.h" >>#include "dlgdef.h" >>#include "err.h" >> >>char *zztokens[34]={ >> /* 00 */ "Invalid", >> /* 01 */ "EOF", >> /* 02 */ "[\\r\\t\\ ]+", >> /* 03 */ "[\\n]", >> /* 04 */ "L_EOF", >> /* 05 */ "PER_PER", >> /* 06 */ "NAME_PER_PER", >> /* 07 */ "ACTION", >> /* 08 */ "GREAT_GREAT", >> /* 09 */ "L_BRACE", >> /* 10 */ "R_BRACE", >> /* 11 */ "L_PAR", >> /* 12 */ "R_PAR", >> /* 13 */ "L_BRACK", >> /* 14 */ "R_BRACK", >> /* 15 */ "ZERO_MORE", >> /* 16 */ "ONE_MORE", >> /* 17 */ "OR", >> /* 18 */ "RANGE", >> /* 19 */ "NOT", >> /* 20 */ "OCTAL_VALUE", >> /* 21 */ "HEX_VALUE", >> /* 22 */ "DEC_VALUE", >> /* 23 */ "TAB", >> /* 24 */ "NL", >> /* 25 */ "CR", >> /* 26 */ "BS", >> /* 27 */ "LIT", >> /* 28 */ "REGCHAR", >> /* 29 */ "\\>", >> /* 30 */ "\\\\>", >> /* 31 */ "\\", >> /* 32 */ "\\n", >> /* 33 */ "~[\\>\\@\\n]+" >>}; >>unsigned zzerr1[2] = {0x60, 0x0}; >>unsigned zzerr2[2] = {0x1ff9aaf0, 0x0}; >>unsigned zzerr3[2] = {0x1ff9aa90, 0x0}; >>unsigned zzerr4[2] = {0x1ff9aa10, 0x0}; >>unsigned zzerr5[2] = {0x1ff82a10, 0x0}; >>unsigned zzerr6[2] = {0x1ff00010, 0x0}; >>unsigned setwd1[34] = {0x0,0x3,0x0,0x0,0x1df598,0x164,0x164, >> 0x18ab1a,0x0,0x18b598,0x18aa00,0x18b598,0x18aa00,0x18b598,0x160000, >> 0x18a598,0x18a598,0x18a800,0x100000,0x18b598,0x1df598,0x1df598,0x1df598, >> 0x1df598,0x1df598,0x1df598,0x1df598,0x1df598,0x1df598,0x0,0x0, >> 0x0,0x0,0x0}; >EOF_err.c >cat << \EOF_support.c | sed 's/^>//' > support.c >>#include >>#include "dlg.h" >>#ifdef MEMCHK >>#include "trax.h" >>#else >>extern char *malloc(); >>extern char *calloc(); >>#endif >> >>int err_found = 0; /* indicates whether problem found */ >> >>internal_error(s,file,line) >>char *s,*file; >>int line; >>{ >> fprintf(stderr,s,file,line); >> exit(1); >>} >> >>char *dlg_malloc(bytes,file,line) >>int bytes; >>char *file; >>int line; >>{ >> char *t; >> >> t = (char *) malloc(bytes); >> if (!t){ >> /* error */ >> internal_error("%s(%d): unable to allocate memory\n", >> file,line); >> } >> return t; >>} >> >> >>char *dlg_calloc(n,bytes,file,line) >>int n,bytes; >>char *file; >>int line; >>{ >> char *t; >> >> t = (char *) calloc(n,bytes); >> if (!t){ >> /* error */ >> internal_error("%s(%d): unable to allocate memory\n", >> file,line); >> } >> return t; >>} >> >> >>FILE *read_stream(name) >>char *name; >>{ >> FILE *f; >> >> if (name){ >> if (name[0] == '-') { >> fprintf(stderr, "dlg: invalid option: '%s'\n", name); >> f = NULL; >> }else{ >> f = fopen(name, "r"); >> if (f == NULL){ >> /* couldn't open file */ >> fprintf(stderr, >> "dlg: Warning: Can't read file %s.\n", >> name); >> } >> } >> }else{ >> /* open stdin if nothing there */ >> f = stdin; >> } >> return f; >>} >> >>FILE *write_stream(name) >>char *name; >>{ >> FILE *f; >> >> if (name){ >> if (name[0] == '-') { >> fprintf(stderr, "dlg: invalid option: '%s'\n", name); >> f = NULL; >> }else{ >> f = fopen(name, "w"); >> if (f == NULL){ >> /* couldn't open file */ >> fprintf(stderr, >> "dlg: Warning: Can't write to file %s.\n", >> name); >> } >> } >> }else{ >> /* open stdin if nothing there */ >> f = stdout; >> } >> return f; >>} >> >> >>void fatal(message,line_no) >>char *message; >>int line_no; >>{ >> fprintf(stderr,"Fatal : %s, line : %d\n",message,line_no); >> exit(2); >>} >> >>void error(message,line_no) >>char *message; >>int line_no; >>{ >> fprintf(stderr,"\"%s\", line %d: %s\n", >> (file_str[0] ? file_str[0] : "stdin"), line_no, message); >> err_found = 1; >>} >> >>void warning(message,line_no) >>char *message; >>int line_no; >>{ >> fprintf(stderr,"Warning : %s, line : %d\n",message,line_no); >>} >EOF_support.c >cat << \EOF_output.c | sed 's/^>//' > output.c >>/* output.c, output generator for dlg >> * >> * Will Cohen >> * 10/24/92 >> */ >> >>#include >>#include "dlg.h" >>#ifdef MEMCHK >>#include "trax.h" >>#endif >> >>int operation_no = 0; /* used to mark nodes so that infinite loops avoided */ >>int dfa_basep[MAX_MODES]; /* start of each group of states */ >>int dfa_class_nop[MAX_MODES]; /* number of elements in each group of states*/ >> >>int gen_ansi = FALSE; /* allows ansi code to be generated */ >> >>FILE *input_stream; /* where to read description from */ >>FILE *output_stream; /* where to put the output */ >>FILE *mode_stream; /* where to put the mode.h stuff */ >> >>/* NOTE: This section is MACHINE DEPENDENT */ >>#define DIF_SIZE 4 >>#ifdef PC >>long typesize[DIF_SIZE] = { 0x7f, 0x7fff, 0x7fff, 0x7fffffff }; >>char t0[] = "unsigned char"; >>char t1[] = "unsigned short"; >>char t2[] = "unsigned int"; >>char t3[] = "unsigned long"; >>char *typevar[DIF_SIZE] = { t0, t1, t2, t3}; >>#else >>long typesize[DIF_SIZE] = { 0x7f, 0x7fff, 0x7fffffff, 0x7fffffff }; >>char t0[] = "unsigned char"; >>char t1[] = "unsigned short"; >>char t2[] = "unsigned int"; >>char t3[] = "unsigned long"; >>char *typevar[DIF_SIZE] = { t0, t1, t2, t3}; >>#endif >> >>/* generate require header on output */ >>p_head() >>{ >> fprintf(OUT, "/*\n"); >> fprintf(OUT, " * D L G tables\n"); >> fprintf(OUT, " *\n"); >> fprintf(OUT, " * Generated from:"); >> fprintf(OUT, " %s", file_str[0]); >> fprintf(OUT, "\n"); >> fprintf(OUT, " *\n"); >> fprintf(OUT, " * 1989-1992 by Will Cohen, Terence Parr, and Hank Dietz\n"); >> fprintf(OUT, " * Purdue University Electrical Engineering\n"); >> fprintf(OUT, " * DLG Version %s\n", version); >> fprintf(OUT, " */\n\n"); >> fprintf(OUT, "#include \"%s\"\n\n", mode_file); >> fprintf(OUT,"\n"); >>} >> >> >>/* generate code to tie up any loose ends */ >>p_tail() >>{ >> fprintf(OUT, "\n"); >> fprintf(OUT, "\n"); >> if (comp_level) >> fprintf(OUT, "#define ZZSHIFT(c) (b_class_no[zzauto][1+c])\n"); >> else >> fprintf(OUT, "#define ZZSHIFT(c) (1+c)\n"); >> fprintf(OUT, "#define MAX_MODE %d\n",mode_counter); >> fprintf(OUT, "#include \"dlgauto.h\"\n"); >>} >> >> >>/* output the table of DFA for general use */ >>p_tables() >>{ >> char *minsize(); >> >> fprintf(OUT, "#define DfaStates\t%d\n", dfa_allocated); >> fprintf(OUT, "typedef %s DfaState;\n\n", minsize(dfa_allocated)); >> >> p_node_table(); >> p_dfa_table(); >> p_accept_table(); >> p_action_table(); >> p_base_table(); >> p_class_table(); >> if (comp_level) >> p_bshift_table(); >> if (interactive) >> p_alternative_table(); >>} >> >> >>/* figures out the smallest variable type that will hold the transitions >> */ >>char *minsize(elements) >>int elements; >>{ >> int i = 0; >> >> while (elements > typesize[i]) >> ++i; >> return typevar[i]; >> >>} >> >> >>p_node_table() >>{ >> register int i; >> register int m = 0; >> >> for(m=0; m<(mode_counter-1); ++m){ >> for(i=dfa_basep[m]; i> p_single_node(i,dfa_class_nop[m]); >> } >> for(i=dfa_basep[m]; i<=dfa_allocated; ++i) >> p_single_node(i,dfa_class_nop[m]); >>} >> >> >>p_single_node(i,classes) >>int i,classes; >>{ >> register int j; >> register int trans, items_on_line; >> >> fprintf(OUT, "static DfaState st%d[%d] = {\n ", (i-1), (classes+1)); >> items_on_line = MAX_ON_LINE; >> for(j=0; j> trans = DFA(i)->trans[j]; >> if (trans == NIL_INDEX) >> trans = dfa_allocated+1; >> /* all of DFA moved down one in array */ >> fprintf(OUT, "%d", trans-1); >> fprintf(OUT, ", "); >> if (!(--items_on_line)){ >> fprintf(OUT, "\n "); >> items_on_line = MAX_ON_LINE; >> } >> } >> fprintf(OUT, "%d\n};\n\n", dfa_allocated); >>} >> >> >>p_dfa_table() >>{ >> register int i; >> >> fprintf(OUT, "\nDfaState *dfa[%d] = {\n", dfa_allocated); >> for (i=0; i<(dfa_allocated-1); ++i){ >> fprintf(OUT, "\tst%d,\n", i); >> } >> fprintf(OUT, "\tst%d\n", i); >> fprintf(OUT, "};\n\n"); >>} >> >> >>p_accept_table() >>{ >> register int i = 1; >> register int items_on_line = 0; >> int true_interactive = TRUE; >> >> fprintf(OUT,"\nDfaState accepts[%d] = {\n ",dfa_allocated); >> while (TRUE){ >> int accept; >> set nfa_states; >> unsigned int *t, *nfa_i; >> >> nfa_states = DFA(i)->nfa_states; >> t = nfa_i = set_pdq(nfa_states); >> /* NOTE: picks lowest accept because accepts monotonic */ >> /* with respect to nfa node numbers and set_pdq */ >> /* returns in that order */ >> while((*nfa_i != nil) && (!(accept = NFA(*nfa_i)->accept))){ >> nfa_i++; >> } >> if ((DFA(i)->alternatives) && (accept != 0)){ >> true_interactive = FALSE; >> } >> fprintf(OUT, "%d", accept); >> if ((++i)>dfa_allocated) >> break; >> fprintf(OUT, ", "); >> if ((++items_on_line)>=MAX_ON_LINE){ >> fprintf(OUT,"\n "); >> items_on_line = 0; >> } >> free(t); >> } >> fprintf(OUT, "\n};\n\n"); >>} >> >> >>p_action_table() >>{ >> register int i; >> >> fprintf(OUT, "void (*actions[%d])() = {\n", action_no+1); >> fprintf(OUT, "\tzzerraction,\n"); >> for (i=1; i> fprintf(OUT,"\tact%d,\n", i); >> } >> fprintf(OUT, "\tact%d\n", i); >> fprintf(OUT, "};\n\n"); >>} >> >> >>p_shift_table(m) >>int m; >>{ >> register int i = 0, j; >> register int items_on_line = 0; >> >> fprintf(OUT, "unsigned char shift%d[%d] = {\n ", m, MAX_CHAR+2); >> while (TRUE){ >> /* find which partition character i is in */ >> for (j=0; j> if (set_el(i,class[j])) >> break; >> } >> fprintf(OUT,"%d",j); >> if ((++i)>(MAX_CHAR+1)) >> break; >> fprintf(OUT,", "); >> if ((++items_on_line)>=MAX_ON_LINE){ >> fprintf(OUT,"\n "); >> items_on_line = 0; >> } >> } >> fprintf(OUT, "\n};\n\n"); >>} >> >> >>p_base_table() >>{ >> register int m; >> >> fprintf(OUT, "static int dfa_base[] = {\n"); >> for(m=0; m<(mode_counter-1); ++m) >> fprintf(OUT, "\t%d,\n", dfa_basep[m]-1); >> fprintf(OUT, "\t%d\n};\n\n", dfa_basep[m]-1); >>} >> >> >>p_class_table() >>{ >> register int m; >> >> fprintf(OUT,"static int dfa_class_no[] = {\n"); >> for(m=0; m<(mode_counter-1); ++m) >> fprintf(OUT,"\t%d,\n", dfa_class_nop[m]); >> fprintf(OUT,"\t%d\n};\n\n", dfa_class_nop[m]); >>} >> >> >>p_bshift_table() >>{ >> register int m; >> >> fprintf(OUT,"static unsigned char *b_class_no[] = {\n"); >> for(m=0; m<(mode_counter-1); ++m) >> fprintf(OUT, "\tshift%d,\n", m); >> fprintf(OUT, "\tshift%d\n};\n\n", m); >>} >> >>p_alternative_table() >>{ >> register int i; >> >> fprintf(OUT, "#define ZZINTERACTIVE\n\n"); >> fprintf(OUT, "char zzalternatives[DfaStates+1] = {\n"); >> for(i=1; i<=dfa_allocated; ++i) >> fprintf(OUT, "\t%d,\n", DFA(i)->alternatives); >> fprintf(OUT, "/* must have 0 for zzalternatives[DfaStates] */\n"); >> fprintf(OUT, "\t0\n};\n\n"); >>} >> >>p_mode_def(s,m) >>char *s; >>int m; >>{ >> fprintf(mode_stream, "#define %s %d\n", s, m); >>} >> >> >>#ifdef DEBUG >>/* print out a particular nfa node that is pointed to by p */ >>p_nfa_node(p) >>nfa_node *p; >>{ >> register nfa_node *t; >> >> if (p != NIL_INDEX){ >> printf("NFA state : %d\naccept state : %d\n", >> NFA_NO(p),p->accept); >> if (p->trans[0] != NIL_INDEX){ >> printf("trans[0] => %d on ", NFA_NO(p->trans[0])); >> p_set(p->label); >> printf("\n"); >> } >> else >> printf("trans[0] => nil\n"); >> if (p->trans[1] != NIL_INDEX) >> printf("trans[1] => %d on epsilon\n", >> NFA_NO(p->trans[1])); >> else >> printf("trans[1] => nil\n"); >> printf("\n"); >> } >>} >>#endif >> >>#ifdef DEBUG >>/* code to print out special structures when using a debugger */ >> >>p_nfa(p) >>nfa_node *p; /* state number also index into array */ >>{ >>/* each node has a marker on it so it only gets printed once */ >> >> operation_no++; /* get new number */ >> s_p_nfa(p); >>} >> >>s_p_nfa(p) >>nfa_node *p; /* state number also index into array */ >>{ >> if ((p != NIL_INDEX) && (p->nfa_set != operation_no)){ >> /* so it is only printed once */ >> p->nfa_set = operation_no; >> p_nfa_node(p); >> s_p_nfa(p->trans[0]); >> s_p_nfa(p->trans[1]); >> } >>} >> >>p_dfa_node(p) >>dfa_node *p; >>{ >> int i; >> >> if (p != NIL_INDEX){ >> printf("DFA state :%d\n",NFA_NO(p)); >> if (p->done) >> printf("done\n"); >> else >> printf("undone\n"); >> printf("from nfa states : "); >> p_set(p->nfa_states); >> printf("\n"); >> /* NOTE: trans arcs stored as ints rather than pointer*/ >> for (i=0; i> printf("%d ",p->trans[i]); >> } >> printf("\n\n"); >> } >>} >> >>p_dfa() >>{ >>/* prints out all the dfa nodes actually allocated */ >> >> int i; >> >> for (i = 1; i<=dfa_allocated; i++) >> p_dfa_node(NFA(i)); >>} >> >> >>/* print out numbers in the set label */ >>p_set(label) >>set label; >>{ >> unsigned *t, *e; >> >> if (set_nil(label)){ >> printf("epsilon\n"); >> }else{ >> t = e = set_pdq(label); >> while(*e != nil){ >> printf("%d ", (*e+MIN_CHAR)); >> e++; >> } >> printf("\n"); >> free(t); >> } >> >>} >>#endif >EOF_output.c >cat << \EOF_relabel.c | sed 's/^>//' > relabel.c >>/* This group of functions does the character class compression. >> It goes over the dfa and relabels the arcs with the partitions >> of characters in the NFA. The partitions are stored in the >> array class. >> >> Will Cohen >> 9/3/90 >> */ >> >>#include >>#include "dlg.h" >>#ifdef MEMCHK >>#include "trax.h" >>#endif >> >>int class_no = CHAR_RANGE; /* number of classes for labels */ >>int first_el[CHAR_RANGE]; /* first element in each class partition */ >>set class[CHAR_RANGE]; /* array holds partitions from class */ >> /* compression */ >> >>/* goes through labels on NFA graph and partitions the characters into >> * character classes. This reduces the amount of space required for each >> * dfa node, since only one arc is required each class instead of one arc >> * for each character >> * level: >> * 0 no compression done >> * 1 remove unused characters from classes >> * 2 compress equivalent characters into same class >> * >> * returns the number of character classes required >> */ >>int relabel(start,level) >>int level; >>nfa_node *start; >>{ >> if (level){ >> set_free(used_classes); >> partition(start,level); >> label_with_classes(start); >> }else{ >> /* classes equivalent to all characters in alphabet */ >> class_no = CHAR_RANGE; >> } >> return class_no; >>} >> >>/* makes character class sets for new labels */ >>partition(start,level) >>nfa_node *start; /* beginning of nfa graph */ >>int level; /* compression level to uses */ >>{ >> set current_class; >> set unpart_chars; >> set temp; >> >> unpart_chars = set_dup(used_chars); >> /* EOF (-1+1) alway in class 0 */ >> class[0] = set_of(0); >> first_el[0] = 0; >> used_classes = set_of(0); >> temp = set_dif(unpart_chars, class[0]); >> set_free(unpart_chars); >> unpart_chars = temp; >> class_no = 1; >> while (!set_nil(unpart_chars)){ >> /* don't look for equivalent labels if c <= 1 */ >> if (level <= 1){ >> current_class = set_of(set_int(unpart_chars)); >> }else{ >> current_class = set_dup(unpart_chars); >> intersect_nfa_labels(start,¤t_class); >> } >> set_orel(class_no,&used_classes); >> first_el[class_no] = set_int(current_class); >> class[class_no] = current_class; >> temp = set_dif(unpart_chars,current_class); >> set_free(unpart_chars); >> unpart_chars = temp; >> class_no++; >> } >>} >> >> >>/* given pointer to beginning of graph and recursively walks it trying >> * to find a maximal partition. This partion in returned in maximal_class >> */ >>intersect_nfa_labels(start,maximal_class) >>nfa_node *start; >>set *maximal_class; >>{ >> /* pick a new operation number */ >> operation_no++; >> r_intersect(start,maximal_class); >>} >> >>r_intersect(start,maximal_class) >>nfa_node *start; >>set * maximal_class; >>{ >> set temp; >> >> if(start && start->nfa_set != operation_no) >> { >> start->nfa_set = operation_no; >> temp = set_and(*maximal_class,start->label); >> if (!set_nil(temp)) >> { >> set_free(*maximal_class); >> *maximal_class = temp; >> }else{ >> set_free(temp); >> } >> r_intersect(start->trans[0],maximal_class); >> r_intersect(start->trans[1],maximal_class); >> } >>} >> >> >>/* puts class labels in place of old character labels */ >>label_with_classes(start) >>nfa_node *start; >>{ >> operation_no++; >> label_node(start); >>} >> >>label_node(start) >>nfa_node *start; >>{ >> set new_label; >> register int i; >> >> /* only do node if it hasn't been done before */ >> if (start && start->nfa_set != operation_no){ >> start->nfa_set = operation_no; >> new_label = empty; >> for (i = 0; i> /* if one element of class in old_label, >> all elements are. */ >> if (set_el(first_el[i],start->label)) >> set_orel(i,&new_label); >> } >> set_free(start->label); >> start->label = new_label; >> /* do any nodes that can be reached from this one */ >> label_node(start->trans[0]); >> label_node(start->trans[1]); >> } >>} >EOF_relabel.c >cat << \EOF_automata.c | sed 's/^>//' > automata.c >>/* Automata conversion functions for dlg version 2 >> * >> * Will Cohen >> * 8/24/90 >> */ >> >>#include >>#include "dlg.h" >>#ifdef MEMCHK >>#include "trax.h" >>#else >>extern char *malloc(); >>extern char *calloc(); >>#endif >> >>#define hash_list struct _hash_list_ >>hash_list{ >> hash_list *next; /* next thing in list */ >> dfa_node *node; >>}; >> >>int dfa_allocated = 0; /* keeps track of number of dfa nodes */ >>dfa_node *dfa_array; /* root of binary tree that stores dfa array */ >>dfa_node *dfa_model_node; >>hash_list *dfa_hash[HASH_SIZE]; /* used to quickly find */ >> /* desired dfa node */ >> >>make_dfa_model_node(width) >>int width; >>{ >> register int i; >> dfa_model_node = (dfa_node*) malloc(sizeof(dfa_node) >> + sizeof(int)*width); >> dfa_model_node->left = NULL; >> dfa_model_node->right = NULL; >> dfa_model_node->node_no = -1; /* impossible value for real dfa node */ >> dfa_model_node->dfa_set = 0; >> dfa_model_node->alternatives = FALSE; >> dfa_model_node->done = FALSE; >> dfa_model_node->nfa_states = empty; >> for(i = 0; i> dfa_model_node->trans[i] = NIL_INDEX; >>} >> >>/* finds dfa state number and returns a pointer to it */ >>/* right now uses binary tree to store dfa nodes */ >>dfa_node *index_dfa(i) >>register int i; >>{ >> dfa_node *p = dfa_array; >> >> if (i == NIL_INDEX) >> return NULL; >> while((i>1) && p){ >> if(i & 1) >> p = p->right; >> else >> p = p->left; >> i = i>>1; >> } >> return p; >>} >> >> >>/* adds a new dfa to the binary tree and returns a pointer to it */ >>dfa_node *new_dfa_node(nfa_states) >>set nfa_states; >>{ >> dfa_node *p = dfa_array; >> dfa_node *t; >> int i,j; >> >> i = ++dfa_allocated; >> >> t = (dfa_node*) malloc(sizeof(nfa_node)+sizeof(int)*class_no); >> *t = *dfa_model_node; >> for (j=0; j> t->trans[j] = NIL_INDEX; >> t->node_no = i; >> t->nfa_states = set_dup(nfa_states); >> >> while((i>3) && p){ >> if(i & 1) >> p = p->right; >> else >> p = p->left; >> i = i>>1; >> } >> if (dfa_allocated == 1) >> dfa_array = t; >> else if (p != NIL_INDEX){ >> if (i & 1) >> p->right = t; >> else >> p->left = t; >> } >> else >> /* error if here */ >> internal_error("%s(%d): missing node on binary tree\n", >> __FILE__,__LINE__); >> return t; >>} >> >>/* past a pointer to the start start of the nfa graph >> * nfa_to_dfa convers this graph to dfa. The function returns >> * a pointer to the first dfa state. >> * NOTE: The function that prints out the table will have to figure out how >> * to find the other dfa states given the first dfa_state and the number of dfa >> * nodes allocated >> */ >>dfa_node *nfa_to_dfa(start) >>nfa_node *start; >>{ >> set x, t; >> dfa_node *d_state, *trans_d_state; >> int a; >> int last_done; >> >> >> if (!start) return NULL; >> t = empty; >> x = set_of(NFA_NO(start)); >> closure(&x); >> /* Make x a dfa state */ >> d_state = dfastate(x); >> last_done = DFA_NO(d_state); >> >> do { >> /* Mark dfa state x as "done" */ >> d_state->done = TRUE; >> last_done++; /* move forward in queue */ >> for (a = 0; a> /* Build an empty set */ >> set_free(t); >> /* Add NFA states reached by a from state b */ >> t = reach(d_state->nfa_states,a); >> /* Were any states found? */ >> if (!set_nil(t)) { >> /* yes, compute closure */ >> closure(&t); >> /* Make DFA state of it ... */ >> trans_d_state = dfastate(t); >> /* And make transition x->t, labeled with a */ >> d_state->trans[a] = DFA_NO(trans_d_state); >> d_state->alternatives = TRUE; >> } >> } >> /* And so forth until nothing isn't done */ >> d_state = DFA(last_done); >> } while (last_done<=dfa_allocated); >> /* returns pointer to the array that holds the automaton */ >> return dfa_array; >>} >> >>clear_hash() >>{ >> register int i; >> >> for(i=0; i> dfa_hash[i] = 0; >>} >> >>/* Returns a pointer to a dfa node that has the same nfa nodes in it. >> * This may or maynot be a newly created node. >> */ >>dfa_node *dfastate(nfa_states) >>set nfa_states; /* list of nfa states it could be */ >>{ >> int bin; >> hash_list *p; >> >> /* hash using set and see if it exists */ >> bin = set_hash(nfa_states,HASH_SIZE); >> p = dfa_hash[bin]; >> while(p && !set_equ(nfa_states,(p->node)->nfa_states)){ >> p = p->next; >> } >> if(!p){ >> /* next state to add to hash table */ >> p = (hash_list*)malloc(sizeof(hash_list)); >> p->node = new_dfa_node(nfa_states); >> p->next = dfa_hash[bin]; >> dfa_hash[bin] = p; >> } >> return (p->node); >>} >> >> >>/* this reach assumes the closure has been done already on set */ >>set reach(b,a) >>set b; >>register int a; >>{ >> register unsigned int *t,*e; >> nfa_node *node; >> set temp; >> >> temp = set_of(nil); >> t = e = set_pdq(b); >> while (*e != nil){ >> node = NFA(*e); >> if (set_el(a,node->label)) >> set_orel(NFA_NO(node->trans[0]),&temp); >> e++; >> } >> free(t); >> return temp; >>} >> >>/* finds all the nodes that can be reached by epsilon transitions >> from the set of a nodes and returns puts them back in set b */ >>set closure(b) >>set *b; >>{ >> register nfa_node *node,*n; /* current node being examined */ >> unsigned *t,*e; >> >> ++operation_no; >> t = e = set_pdq(*b); >> while (*e != nil){ >> node = NFA(*e); >> /* mark it done */ >> node->nfa_set = operation_no; >> if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) && >> (n->nfa_set != operation_no)){ >> /* put in b */ >> set_orel(NFA_NO(n),b); >> close1(n,operation_no,b); >> } >> if ((n=node->trans[1]) != NIL_INDEX && >> (n->nfa_set != operation_no)){ >> /* put in b */ >> set_orel(NFA_NO(node->trans[1]),b); >> close1(n,operation_no,b); >> } >> e++; >> } >> free(t); >> return *b; >>} >> >>close1(node,o,b) >>nfa_node *node; >>int o; /* marker to avoid cycles */ >>set *b; >>{ >> register nfa_node *n; /* current node being examined */ >> >> /* mark it done */ >> node->nfa_set = o; >> if ((n=node->trans[0]) != NIL_INDEX && set_nil(node->label) && >> (n->nfa_set != o)){ >> /* put in b */ >> set_orel(NFA_NO(n),b); >> close1(n,o,b); >> } >> if ((n=node->trans[1]) != NIL_INDEX && >> (n->nfa_set != o)){ >> /* put in b */ >> set_orel(NFA_NO(node->trans[1]),b); >> close1(n,o,b); >> } >>} >EOF_automata.c >cat << \EOF_mode.h | sed 's/^>//' > mode.h >>#define START 0 >>#define ACT 1 >EOF_mode.h >cat << \EOF_tokens.h | sed 's/^>//' > tokens.h >>/* tokens.h -- List of labelled tokens >> * >> * Generated from: dlg_p.g >> * >> * Terence Parr, Hank Dietz and Will Cohen: 1989-1992 >> * Purdue University Electrical Engineering >> * ANTLR Version 1.06 >> */ >>#define L_EOF 4 >>#define PER_PER 5 >>#define NAME_PER_PER 6 >>#define ACTION 7 >>#define GREAT_GREAT 8 >>#define L_BRACE 9 >>#define R_BRACE 10 >>#define L_PAR 11 >>#define R_PAR 12 >>#define L_BRACK 13 >>#define R_BRACK 14 >>#define ZERO_MORE 15 >>#define ONE_MORE 16 >>#define OR 17 >>#define RANGE 18 >>#define NOT 19 >>#define OCTAL_VALUE 20 >>#define HEX_VALUE 21 >>#define DEC_VALUE 22 >>#define TAB 23 >>#define NL 24 >>#define CR 25 >>#define BS 26 >>#define LIT 27 >>#define REGCHAR 28 >> >>#ifdef __STDC__ >>void grammar(); >>#else >>extern grammar(); >>#endif >> >>#ifdef __STDC__ >>void start_states(); >>#else >>extern start_states(); >>#endif >> >>#ifdef __STDC__ >>void do_conversion(); >>#else >>extern do_conversion(); >>#endif >> >>#ifdef __STDC__ >>void rule_list(); >>#else >>extern rule_list(); >>#endif >> >>#ifdef __STDC__ >>void rule(); >>#else >>extern rule(); >>#endif >> >>#ifdef __STDC__ >>void reg_expr(); >>#else >>extern reg_expr(); >>#endif >> >>#ifdef __STDC__ >>void and_expr(); >>#else >>extern and_expr(); >>#endif >> >>#ifdef __STDC__ >>void repeat_expr(); >>#else >>extern repeat_expr(); >>#endif >> >>#ifdef __STDC__ >>void expr(); >>#else >>extern expr(); >>#endif >> >>#ifdef __STDC__ >>void atom_list(); >>#else >>extern atom_list(); >>#endif >> >>#ifdef __STDC__ >>void near_atom(); >>#else >>extern near_atom(); >>#endif >> >>#ifdef __STDC__ >>void atom(); >>#else >>extern atom(); >>#endif >> >>#ifdef __STDC__ >>void anychar(); >>#else >>extern anychar(); >>#endif >>extern unsigned zzerr1[]; >>extern unsigned zzerr2[]; >>extern unsigned zzerr3[]; >>extern unsigned zzerr4[]; >>extern unsigned zzerr5[]; >>extern unsigned zzerr6[]; >>extern unsigned setwd1[]; >EOF_tokens.h >cat << \EOF_dlg.h | sed 's/^>//' > dlg.h >>/* dlg header file >> * >> * Will Cohen >> * 8/18/90 >> */ >>#include "set.h" >> >>#define TRUE 1 >>#define FALSE 0 >> >>/***** output related stuff *******************/ >>#define IN input_stream >>#define OUT output_stream >> >>#define MAX_MODES 50 /* number of %%names allowed */ >>#define MAX_ON_LINE 10 >> >>/* these macros allow the size of the character set to be easily changed */ >>/* NOTE: do NOT change MIN_CHAR since EOF is the lowest char, -1 */ >>#define MIN_CHAR (-1) /* lowest possible character possible on input */ >>#define MAX_CHAR 255 /* highest possible character possible on input */ >>#define CHAR_RANGE ((MAX_CHAR) - (MIN_CHAR)) >> >>/* indicates that the not an "array" reference */ >>#define NIL_INDEX 0 >> >>/* size of hash table used to find dfa_states quickly */ >>#define HASH_SIZE 200 >> >>#define nfa_node struct _nfa_node >>nfa_node { >> nfa_node *left,*right; /* for binary tree storage of array */ >> int node_no; >> int nfa_set; >> int accept; /* what case to use */ >> nfa_node *trans[2]; >> set label; /* one arc always labelled with epsilon */ >>}; >> >>#define dfa_node struct _dfa_node >>dfa_node { >> dfa_node *left,*right; /* for binary tree storage of array */ >> int node_no; >> int dfa_set; >> int alternatives; /* used for interactive mode */ >> /* are more characters needed */ >> int done; >> set nfa_states; >> int trans[1];/* size of transition table depends on >> * number of classes required for automata. >> */ >> >> >>}; >> >>/******** macros for accessing the NFA and DFA nodes ****/ >>#define NFA(x) index_nfa(x) >>#define DFA(x) index_dfa(x) >>#define DFA_NO(x) ( (x) ? (x)->node_no : NIL_INDEX) >>#define NFA_NO(x) ( (x) ? (x)->node_no : NIL_INDEX) >> >>/******** wrapper for memory checking ***/ >>/*#define malloc(x) dlg_malloc((x),__FILE__,__LINE__)*/ >>extern char *dlg_malloc(); /* wrapper for memory allocations */ >> >>/*#define calloc(x,y) dlg_calloc((x),(y),__FILE__,__LINE__)*/ >>extern char *dlg_calloc(); /* wrapper for memory allocations */ >> >>/******** antlr attributes *************/ >>typedef struct { >> char letter; >> nfa_node *l,*r; >> set label; >> } Attrib; >> >>#define zzcr_attr(attr, token, text) { \ >> (attr)->letter = text[0]; (attr)->l = NULL; \ >> (attr)->r = NULL; (attr)->label = empty; \ >>} >>#define zzd_attr(a) set_free((a)->label); >> >>/******************** Variable ******************************/ >>extern char version[]; /* tells what version this is */ >>extern char *file_str[]; /* file names being used */ >>extern int err_found; /* flag to indicate error occured */ >>extern int action_no; /* last action function printed */ >>extern int func_action; /* should actions be turned into functions?*/ >>extern set used_chars; /* used to label trans. arcs */ >>extern set used_classes; /* classes or chars used to label trans. arcs */ >>extern int class_no; /* number of classes used */ >>extern set class[]; /* shows char. in each class */ >>extern set normal_chars; /* mask off unused portion of set */ >>extern int comp_level; /* what compression level to use */ >>extern int interactive; /* interactive scanner (avoid lookahead)*/ >>extern int mode_counter; /* keeps track of the number of %%name */ >>extern int dfa_basep[]; /* start of each group of dfa */ >>extern int dfa_class_nop[];/* number of transistion arcs in */ >> /* each dfa in each mode */ >>extern int nfa_allocated; >>extern int dfa_allocated; >>extern nfa_node *nfa_array; /* start of nfa "array" */ >>extern dfa_node *dfa_array; /* start of dfa "array" */ >>extern int operation_no; /* unique number for each operation */ >>extern FILE *input_stream; /* where description read from */ >>extern FILE *output_stream; /* where to put the output */ >>extern FILE *mode_stream; /* where to put the mode output */ >>extern char *mode_file; /* name of file for mode output */ >>extern int gen_ansi; /* produce ansi compatible code */ >>extern int case_insensitive;/* ignore case of input spec. */ >> >>/******************** Functions ******************************/ >>#ifdef __STDC__ >>extern set reach(set, register int); >>extern set closure(set *); >>extern dfa_node *new_dfa_node(set); >>extern nfa_node *new_nfa_node(); >>extern dfa_node *dfastate(set); >>extern dfa_node *index_dfa(register int); >>extern nfa_node *index_nfa(register int); >>extern dfa_node *nfa_to_dfa(nfa_node *); >>extern internal_error(char *, char *, int); >>extern FILE *read_stream(char *); /* opens file for reading */ >>extern FILE *write_stream(char *); /* opens file for writing */ >>#else >>extern set reach(); >>extern set closure(); >>extern dfa_node *new_dfa_node(); >>extern nfa_node *new_nfa_node(); >>extern dfa_node *dfastate(); >>extern dfa_node *index_dfa(); >>extern nfa_node *index_nfa(); >>extern dfa_node *nfa_to_dfa(); >>extern internal_error(); >>extern FILE *read_stream(); /* opens file for reading */ >>extern FILE *write_stream(); /* opens file for writing */ >>#endif >EOF_dlg.h >cat << \EOF_makefile.user | sed 's/^>//' > makefile.user >># DLG make file >># June 1991 >> >>SET=../support/set >>ANTLR=../bin/antlr >>DLG=../bin/dlg >>SRC = dlg_p.c dlg_a.c main.c err.c $(SET)/set.c support.c output.c \ >> relabel.c automata.c >>OBJ = dlg_p.o dlg_a.o main.o err.o set.o support.o output.o \ >> relabel.o automata.o >> >>CFLAGS = -O -I$(SET) -I../h >> >>dlg : $(OBJ) $(SRC) >> $(CC) $(CFLAGS) -o dlg $(OBJ) >> mv dlg ../bin >> >>dlg_p.c parser.dlg err.c tokens.h : dlg_p.g >> $(ANTLR) dlg_p.g >> >>dlg_a.c mode.h : parser.dlg >> $(DLG) -C2 parser.dlg dlg_a.c >> >>dlg_p.o : dlg_p.c dlg.h tokens.h mode.h >> $(CC) $(CFLAGS) -c dlg_p.c >> >>dlg_a.o : dlg_a.c dlg.h tokens.h mode.h >> $(CC) $(CFLAGS) -c dlg_a.c >> >>main.o : main.c dlg.h >> $(CC) $(CFLAGS) -c main.c >> >>set.o : $(SET)/set.c >> $(CC) -c -o set.o $(CFLAGS) $(SET)/set.c >> >>lint: >> lint *.c >> >>#clean up all the intermediate files >>clean: >> rm -f *.o core >EOF_makefile.user >cat << \EOF_makefile.os2 | sed 's/^>//' > makefile.os2 >># >># DLG make file >># June 1991 >># >># Ported to Microsoft 6.0 by >># Ed Harfmann >># Micro Data Base Systems >># Lafayette, Indiana >># >> >>LIBS=/NOD:LLIBCE LLIBCEP >>SET=../support/set >>SRC = dlg_a.c dlg_p.c main.c err.c $(SET)/set.c support.c output.c \ >> relabel.c automata.c >> >>OBJ = dlg_a.obj dlg_p.obj main.obj err.obj set.obj support.obj output.obj \ >> relabel.obj automata.obj >> >>SYSTEM=PC >>CFLAGS = -I$(SET) -I../h -D$(SYSTEM) /AL /Za >>ANTLR=..\bin\antlr >>DLG=..\bin\dlg >> >>dlg.exe : $(OBJ) $(SRC) >> link @<< >>$(OBJ: = +^ >>) /NOI >>$@ /STACK:16384 /CO >> >>$(LIBS: = +^ >>) >>$(DEF_FILE) $(LFLAGS) ; >><< >> bind $@ c:\os2\doscalls.lib >> copy *.exe ..\bin >> >>dlg_p.c parser.dlg err.c tokens.h : dlg_p.g >> $(ANTLR) dlg_p.g >> >>dlg_a.c mode.h : parser.dlg >> $(DLG) -C2 parser.dlg dlg_a.c >> >> >>dlg_p.obj : dlg_p.c dlg.h tokens.h mode.h >> $(CC) $(CFLAGS) -c dlg_p.c >> >>dlg_a.obj : dlg_a.c dlg.h tokens.h mode.h >> $(CC) $(CFLAGS) -c dlg_a.c >> >>main.obj : main.c dlg.h >> $(CC) $(CFLAGS) -c main.c >> >>set.obj : $(SET)/set.c >> $(CC) $(CFLAGS) -c $(SET)/set.c >EOF_makefile.os2 >cat << \EOF_dlg.1 | sed 's/^>//' > dlg.1 >>.TH dlg 1 "December 1992" "DLG" "PCCTS Manual Pages" >>.SH NAME >>dlg \- DFA Lexical Analyzer Generator >>.SH SYNOPSIS >>.B dlg >>[ >>.B \-C >>[ >>.I level >>] >>] >>[ >>.B \-m >>.I mode_file >>] >>[ >>.B \-i >>] >>[ >>.B \-cs >>or >>.B \-ci >>] >>.I lexical_spec >>.I output_file >>.SH DESCRIPTION >>.B dlg >>is a tool that produces fast deterministic finite automata for recognizing >>regular expressions in input. >>.SH OPTIONS >>.TP 8 >>.B \-C\fR[\fP level\fR] >>Where \fPlevel\fR is the compression level used. 0 indications no >>compression, 1 removes all unused characters from the transition from table, >>and 2 maps equivalent characters into the same character classes. It is >>suggested that level -C2 is used, since it will significantly reduce the size >>of the dfa produced for lexical analyzer. >>.TP >>.B \-m >>Produces the header file for the lexical mode with a name other than >>the default name of "mode.h". >>.TP >>.B \-i >>An interactive, or as interactive as possible, parser is produced. A character >>is only obtained when required to decide which state to go to. Some care >>must be taken to obtain accept states that do not require look ahead at the >>next character to determine if that is the stop state. Any regular expression >>with a Kleene closure at the end is guaranteed to require another character >>of look ahead. >>.TP >>.B \-ci >>The automaton will treat upper and lower case characters identically. >>This is accomplished in the automaton; the characters in the lexical >>buffer are unmodified. >>.TP >>.B \-cs >>Upper and lower case characters are treated as distinct. This is the >>default. >>.TP >>.B \- >>Used in place of file names to get input from standard in or send output >>to standard out. >>.SH "SPECIAL CONSIDERATIONS" >>.PP >>\fIDlg\fP works... we think. There is no implicit guarantee of >>anything. We reserve no \fBlegal\fP rights to the software known as >>the Purdue Compiler Construction Tool Set (PCCTS) \(em 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. As long as these guidelines are followed, we >>expect to continue enhancing this system and expect to make other >>tools available as they are completed. >>.SH FILES >>.B mode.h >>, >>.B dlgauto.h >>, >>.B dlgdef.h >>.SH SEE ALSO >>.BR antlr (1), >>.BR pccts (1) >>.SH BUGS >EOF_dlg.1 >cat << \EOF_dlg1.txt | sed 's/^>//' > dlg1.txt >> >> >> >>dlg - DFA Lexical Analyzer Generator >> >>dlg [ -C [ level ] ] [ -m mode_file ] [ -i ] [ -cs or -ci ] >>lexical_spec output_file >> >>dlg is a tool that produces fast deterministic finite automata for >>recognizing regular expressions in input. >> >>-C[level] Where level is the compression level used. 0 indications no >>compression, 1 removes all unused characters from the transition from >>table, and 2 maps equivalent characters into the same character >>classes. It is suggested that level -C2 is used, since it will signi- >>ficantly reduce the size of the dfa produced for lexical analyzer. -m >>Produces the header file for the lexical mode with a name other than >>the default name of "mode.h". -i An interactive, or as interactive as >>possible, parser is produced. A character is only obtained when >>required to decide which state to go to. Some care must be taken to >>obtain accept states that do not require look ahead at the next char- >>acter to determine if that is the stop state. Any regular expression >>with a Kleene closure at the end is guaranteed to require another >>character of look ahead. -ci The automaton will treat upper and lower >>case characters identically. This is accomplished in the automaton; >>the characters in the lexical buffer are unmodified. -cs Upper and >>lower case characters are treated as distinct. This is the default. >>- Used in place of file names to get input from standard in or send >>output to standard out. >> >> >> Dlg works... we think. There is no implicit guarantee of any- >>thing. We reserve no legal rights to the software known as 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. How- >>ever, 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. As long as these guidelines are followed, we expect to con- >>tinue enhancing this system and expect to make other tools available >>as they are completed. >> >>mode.h , dlgauto.h , dlgdef.h >> >> >> >> >> >> >> >> >> >> >> >> Page 1 >> >EOF_dlg1.txt EOF_dlg.bag cat << \EOF_h.bag | sed 's/^>//' > h.bag >cat << \EOF_antlr.h | sed 's/^>//' > antlr.h >>/* >> * a n t l r . h >> * >> * Define all of the stack setup and manipulation of $i, #i variables. >> * >> * Notes: >> * The type 'Attrib' must be defined before entry into this .h file. >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >>/* can make this a power of 2 for more efficient lookup */ >>#ifndef ZZLEXBUFSIZE >>#define ZZLEXBUFSIZE 2000 >>#endif >> >>#define zzOvfChk \ >> if ( zzasp <= 0 ) \ >> { \ >> fprintf(stderr, zzStackOvfMsg, __FILE__, __LINE__); \ >> exit(-1); \ >> } >> >>#ifndef ZZA_STACKSIZE >>#define ZZA_STACKSIZE 400 >>#endif >>#ifndef ZZAST_STACKSIZE >>#define ZZAST_STACKSIZE 400 >>#endif >> >>#ifdef LL_K >>#define LOOKAHEAD \ >> int zztokenLA[LL_K]; \ >> char zztextLA[LL_K][ZZLEXBUFSIZE]; \ >> int zzlap = 0, zzlabase=0; /* labase only used for DEMAND_LOOK */ >>#else >>#define LOOKAHEAD \ >> int zztoken; >>#endif >> >> >>#ifndef zzcr_ast >>#define zzcr_ast(ast,attr,tok,text) >>#endif >> >>#ifdef DEMAND_LOOK >>#define DemandLookData int zzdirty=1; >>#else >>#define DemandLookData >>#endif >> >>/* The zzStackOvfMsg error message is repeated often and therefore only one >> * copy is made to save space. >> */ >>#ifdef LL_K >> >>#ifdef __STDC__ >>#define ANTLR_INFO \ >> Attrib zzempty_attr() {static Attrib a; return a;} \ >> Attrib zzconstr_attr(int _tok, char *_text)\ >> {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ >> int zzasp=ZZA_STACKSIZE; \ >> char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ >> Attrib zzaStack[ZZA_STACKSIZE]; \ >> int TCount=0, TComp=0; DemandLookData >>#else >>#define ANTLR_INFO \ >> Attrib zzempty_attr() {static Attrib a; return a;} \ >> Attrib zzconstr_attr(_tok, _text) int _tok; char *_text;\ >> {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ >> int zzasp=ZZA_STACKSIZE; \ >> char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ >> Attrib zzaStack[ZZA_STACKSIZE]; \ >> int TCount=0, TComp=0; DemandLookData >>#endif >> >>#else >> >>#ifdef __STDC__ >>#define ANTLR_INFO \ >> Attrib zzempty_attr() {static Attrib a; return a;} \ >> Attrib zzconstr_attr(int _tok, char *_text)\ >> {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ >> int zzasp=ZZA_STACKSIZE; \ >> char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ >> Attrib zzaStack[ZZA_STACKSIZE]; \ >> int TCount=0, TComp=0; DemandLookData >>#else >>#define ANTLR_INFO \ >> Attrib zzempty_attr() {static Attrib a; return a;} \ >> Attrib zzconstr_attr(_tok, _text) int _tok; char *_text;\ >> {Attrib a; zzcr_attr((&a),_tok,_text); return a;} \ >> int zzasp=ZZA_STACKSIZE; \ >> char zzStackOvfMsg[]="fatal: attrib/AST stack overflow %s(%d)!\n"; \ >> Attrib zzaStack[ZZA_STACKSIZE]; \ >> int TCount=0, TComp=0; DemandLookData >>#endif >> >>#endif /* LL_k */ >> >>#ifdef LL_K >> >>#ifdef DEMAND_LOOK >>#define zzPrimeLookAhead {zzdirty=LL_K; zzlap = zzlabase = 0;} >>#else >>#define zzPrimeLookAhead {int _i; for(_i=1;_i<=LL_K; _i++) \ >> {zzCONSUME;} zzlap = 0;} >>#endif >>#else >> >>#ifdef DEMAND_LOOK >>#define zzPrimeLookAhead zzdirty=1 >>#else >>#define zzPrimeLookAhead zzgettok() >>#endif >> >>#endif /* LL_K */ >> >>#ifdef LL_K >>#define zzenterANTLRf(f) \ >> zzlextext = &(zztextLA[0][0]); zzrdfunc( f ); zzPrimeLookAhead; >>#define zzenterANTLR(f) \ >> zzlextext = &(zztextLA[0][0]); zzrdstream( f ); zzPrimeLookAhead; >>#else >>#define zzenterANTLRf(f) \ >> {static char zztoktext[ZZLEXBUFSIZE]; \ >> zzlextext = zztoktext; zzrdfunc( f ); zzPrimeLookAhead;} >>#define zzenterANTLR(f) \ >> {static char zztoktext[ZZLEXBUFSIZE]; \ >> zzlextext = zztoktext; zzrdstream( f ); zzPrimeLookAhead;} >>#endif >> >>#define ANTLR(st, f) zzbufsize = ZZLEXBUFSIZE; \ >> zzenterANTLR(f); \ >> st; ++zzasp; >>/* >>#define ANTLR(st, f) zzbufsize = ZZLEXBUFSIZE; \ >> zzenterANTLR(f); \ >> st; ++zzasp; \ >> fprintf(stderr, "TCount %d, TComp %d; Ratio %f\n", \ >> TCount, TComp, \ >> ((float)TComp)/TCount); >>*/ >>#define ANTLRf(st, f) zzbufsize = ZZLEXBUFSIZE; \ >> zzenterANTLRf(f); \ >> st; ++zzasp; >> >>/*#define ANTLRf(st, f) zzbufsize = ZZLEXBUFSIZE; \ >> zzenterANTLRf(f); \ >> st; ++zzasp; \ >> fprintf(stderr, "TCount %d, TComp %d; Ratio %f\n", \ >> TCount, TComp, \ >> ((float)TComp)/TCount); >>*/ >>#ifdef LL_K >>#define zztext (&(zztextLA[zzlap][0])) >>#else >>#define zztext zzlextext >>#endif >> >> >> /* A r g u m e n t A c c e s s */ >> >>#define zzaCur (zzaStack[zzasp]) >>#define zzaRet (*zzaRetPtr) >>#define zzaArg(v,n) zzaStack[v-n] >>#define zzMakeAttr {zzOvfChk; --zzasp; zzcr_attr(&(zzaStack[zzasp]),LA(1),LATEXT(1));} >>#ifdef zzdef0 >>#define zzMake0 {zzOvfChk; --zzasp; zzdef0(&(zzaStack[zzasp]));} >>#else >>#define zzMake0 {zzOvfChk; --zzasp;} >>#endif >>#define zzaPush(_v) {zzOvfChk; zzaStack[--zzasp] = _v;} >>#ifndef zzd_attr >>#define zzREL(t) zzasp=(t); /* Restore state of stack */ >>#else >>#define zzREL(t) for (; zzasp<(t); zzasp++) \ >> { zzd_attr(&(zzaStack[zzasp])); } >>#endif >> >>#ifdef DEMAND_LOOK >> >>#ifdef LL_K >>#define zzmatch(_t) \ >> { \ >> if ( zzdirty==LL_K ) { \ >> zzCONSUME; \ >> } \ >> if ( LA(1)!=_t ) { \ >> zzBadText=zzMissText=LATEXT(1); \ >> zzMissTok=_t; zzBadTok=LA(1); \ >> zzMissSet=NULL; \ >> goto fail; \ >> } \ >> zzMakeAttr \ >> zzdirty++; \ >> zzlabase++; \ >> } >>#else >>#define zzmatch(_t) \ >> { \ >> if ( zzdirty ) {zzCONSUME;} \ >> if ( LA(1)!=_t ) { \ >> zzBadText=zzMissText=LATEXT(1); \ >> zzMissTok=_t; zzBadTok=LA(1); \ >> zzMissSet=NULL; \ >> goto fail; \ >> } \ >> zzdirty = 1; \ >> zzMakeAttr \ >> } >>#endif >> >>#else >> >>#define zzmatch(_t) \ >> { \ >> if ( LA(1)!=_t ) { \ >> zzBadText=zzMissText=LATEXT(1); \ >> zzMissTok=_t; zzBadTok=LA(1); \ >> zzMissSet=NULL; \ >> goto fail; \ >> } \ >> zzMakeAttr \ >> } >> >>#endif /* DEMAND_LOOK */ >> >>#ifdef GENAST >>#define zzRULE Attrib *zzaRetPtr = &(zzaStack[zzasp-1]); \ >> unsigned *zzMissSet; int zzMissTok=0; \ >> unsigned zzBadTok; char *zzBadText=""; \ >> int zzErrk=1; \ >> char *zzMissText; zzASTVars >>#else >>#define zzRULE Attrib *zzaRetPtr = &(zzaStack[zzasp-1]); \ >> unsigned zzBadTok; char *zzBadText=""; \ >> int zzErrk=1; \ >> unsigned *zzMissSet; int zzMissTok=0; char *zzMissText >>#endif >> >>#ifdef GENAST >>#define zzBLOCK(i) int i = zzasp - 1; int zztsp = zzast_sp >>#define zzEXIT(i) zzREL(i); zzastREL; zzastPush(*_root); >>#define zzLOOP(i) zzREL(i); zzastREL >>#else >>#define zzBLOCK(i) int i = zzasp - 1 >>#define zzEXIT(i) zzREL(i) >>#define zzLOOP(i) zzREL(i) >>#endif >> >>#ifdef LL_K >> >>#ifdef DEMAND_LOOK >>#define LOOK(_k) {int i,stop=_k-(LL_K-zzdirty); for (i=1; i<=stop; i++) \ >> zzCONSUME;} >>#define zzCONSUME {zzgettok(); zzdirty--; \ >> zzlap = (zzlap+1)&(LL_K-1); \ >> zzlextext = &(zztextLA[zzlap][0]);} >>#else >>#define zzCONSUME {zzgettok(); \ >> zzlap = (zzlap+1)&(LL_K-1); \ >> zzlextext = &(zztextLA[zzlap][0]);} >>#endif >> >>#else >> >>#ifdef DEMAND_LOOK >>#define LOOK(_k) if ( zzdirty) zzCONSUME; >>#define zzCONSUME zzgettok(); zzdirty=0; >>#else >>#define zzCONSUME zzgettok(); >> >>#endif /* LL_K */ >> >>#endif /* LL_K */ >> >>#ifdef LL_K >>#define NLA zztokenLA[zzlap&(LL_K-1)] /* --> next LA */ >>#define NLATEXT zztextLA[zzlap&(LL_K-1)] /* --> next text of LA */ >>#ifdef DEMAND_LOOK >>#define LA(i) zztokenLA[(zzlabase+(i)-1)&(LL_K-1)] >>#define LATEXT(i) (&(zztextLA[(zzlabase+(i)-1)&(LL_K-1)][0])) >>#else >>#define LA(i) zztokenLA[(zzlap+(i)-1)&(LL_K-1)] >>#define LATEXT(i) (&(zztextLA[(zzlap+(i)-1)&(LL_K-1)][0])) >>#endif >>#else >>#define NLA zztoken >>#define NLATEXT zztext >>#define LA(i) zztoken >>#define LATEXT(i) zztext >>#endif >> >> /* F u n c t i o n T r a c i n g */ >> >>#ifndef zzTRACEIN >>#define zzTRACEIN(r) fprintf(stderr, "enter rule \"%s\"\n", r); >>#endif >>#ifndef zzTRACEOUT >>#define zzTRACEOUT(r) fprintf(stderr, "exit rule \"%s\"\n", r); >>#endif >> >> /* E x t e r n D e f s */ >> >>#ifdef __STDC__ >>extern Attrib zzempty_attr(); >>extern Attrib zzconstr_attr(int, char *); >>extern void zzsyn(char *, unsigned, char *, unsigned *, int, int, char *); >>extern int zzset_el(unsigned , unsigned *); >>extern int zzset_deg(unsigned *); >>extern void zzedecode(unsigned *); >>extern void zzFAIL(int k, ...); >>extern void zzresynch(unsigned *,unsigned); >>#else >>extern Attrib zzempty_attr(); >>extern Attrib zzconstr_attr(); >>extern void zzsyn(); >>extern int zzset_el(); >>extern int zzset_deg(); >>extern void zzedecode(); >>extern void zzFAIL(); >>extern void zzresynch(); >>#endif >> >>extern int TCount, TComp; >>extern char zzStackOvfMsg[]; >>extern char *zztokens[]; >>extern int zzasp; >>extern int zzbufsize; >>extern Attrib zzaStack[]; >>#ifdef LL_K >>extern int zztokenLA[]; >>extern char zztextLA[][ZZLEXBUFSIZE]; >>extern int zzlap; >>extern int zzlabase; >>#else >>extern int zztoken; >>#endif >>extern int zzdirty; >EOF_antlr.h >cat << \EOF_ast.h | sed 's/^>//' > ast.h >>/* Abstract syntax tree >> * >> * Macros, definitions >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >>#define zzastOvfChk \ >> if ( zzast_sp <= 0 ) \ >> { \ >> fprintf(stderr, zzStackOvfMsg, __FILE__, __LINE__); \ >> exit(-1); \ >> } >> >>#ifndef AST_FIELDS >>#define AST_FIELDS >>#endif >> >>typedef struct _ast { >> struct _ast *right, *down; >>#ifdef zzAST_DOUBLE >> struct _ast *left, *up; >>#endif >> AST_FIELDS >> } AST; >> >> >>/* N o d e a c c e s s m a c r o s */ >>#define zzchild(t) (((t)==NULL)?NULL:(t->down)) >>#define zzsibling(t) (((t)==NULL)?NULL:(t->right)) >> >> >>/* define global variables needed by #i stack */ >>#define zzASTgvars \ >> AST *zzastStack[ZZAST_STACKSIZE]; \ >> int zzast_sp = ZZAST_STACKSIZE; >> >>#define zzASTVars AST *_ast = NULL, *_sibling = NULL, *_tail = NULL >>#define zzSTR ( (_tail==NULL)?(&_sibling):(&(_tail->right)) ) >>#define zzastCur (zzastStack[zzast_sp]) >>#define zzastArg(i) (zzastStack[zztsp-i]) >>#define zzastPush(p) zzastOvfChk; zzastStack[--zzast_sp] = p; >>#define zzastDPush --zzast_sp >>#define zzastMARK zztsp=zzast_sp; /* Save state of stack */ >>#define zzastREL zzast_sp=zztsp; /* Return state of stack */ >>#define zzrm_ast {zzfree_ast(*_root); _tail = _sibling = (*_root)=NULL;} >> >>extern int zzast_sp; >>extern AST *zzastStack[]; >> >>#ifdef __STDC__ >>void zzlink(AST **, AST **, AST **); >>AST *zzastnew(); >>void zzsubchild(AST **, AST **, AST **); >>void zzsubroot(AST **, AST **, AST **); >>void zzpre_ast(AST *, void (*)(), void (*)(), void (*)()); >>void zzfree_ast(AST *); >>AST *zztmake(AST *, ...); >>AST *zzdup_ast(AST *); >>void zztfree(AST *); >>void zzdouble_link(AST *, AST *, AST *); >> >>#else >> >>void zzlink(); >>AST *zzastnew(); >>void zzsubchild(); >>void zzsubroot(); >>void zzpre_ast(); >>void zzfree_ast(); >>AST *zztmake(); >>AST *zzdup_ast(); >>void zztfree(); >>void zzdouble_link(); >>#endif >EOF_ast.h >cat << \EOF_dlgauto.h | sed 's/^>//' > dlgauto.h >>/* dlgauto.h automaton >> * >> * 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.06 >> * Will Cohen >> * Purdue University >> * 1989-1992 >> */ >> >>char *zzlextext; /* text of most recently matched token */ >>char *zzbegexpr; /* beginning of last reg expr recogn. */ >>char *zzendexpr; /* beginning of last reg expr recogn. */ >>int zzbufsize; /* number of characters in zzlextext */ >>int zzbegcol = 0; /* column that first character of token is in*/ >>int zzendcol = 0; /* column that last character of token is in */ >>int zzline = 1; /* line current token is on */ >>int zzchar; /* character to determine next state */ >>int zzbufovf; /* indicates that buffer too small for text */ >>int zzcharfull = 0; >>static char *zznextpos;/* points to next available position in zzlextext*/ >>static int zzclass; >> >>#ifdef __STDC__ >>void zzerrstd(char *); >>void (*zzerr)(char *)=zzerrstd;/* pointer to error reporting function */ >>#else >>void zzerrstd(); >>void (*zzerr)()=zzerrstd; /* pointer to error reporting function */ >>#endif >> >>static FILE *zzstream_in; >>extern int zzerr_in(); >>static int (*zzfunc_in)() = zzerr_in; >> >>static int zzauto = 0; >>static int zzadd_erase; >>static char zzebuf[70]; >> >>#ifdef ZZCOL >>#define ZZINC (++zzendcol) >>#else >>#define ZZINC >>#endif >> >> >>#define ZZGETC_STREAM {zzchar = getc(zzstream_in); zzclass = ZZSHIFT(zzchar);} >> >>#define ZZGETC_FUNC {zzchar = (*zzfunc_in)(); zzclass = ZZSHIFT(zzchar);} >> >>void >>#ifdef __STDC__ >>zzrdstream( FILE *f ) >>#else >>zzrdstream( f ) >>FILE *f; >>#endif >>{ >> /* make sure that it is really set to something, otherwise just >> leave it be. >> */ >> if (f){ >> /* make sure that there is always someplace to get input >> before closing zzstream_in >> */ >> if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in ); >> zzline = 1; >> zzstream_in = f; >> zzfunc_in = NULL; >> zzcharfull = 0; >> } >>} >> >>void >>#ifdef __STDC__ >>zzrdfunc( int (*f)() ) >>#else >>zzrdfunc( f ) >>int (*f)(); >>#endif >>{ >> /* make sure that it is really set to something, otherwise just >> leave it be. >> */ >> if (f){ >> /* make sure that there is always someplace to get input >> before closing zzstream_in >> */ >> if (zzstream_in && zzstream_in!=stdin) fclose( zzstream_in ); >> zzline = 1; >> zzstream_in = NULL; >> zzfunc_in = f; >> zzcharfull = 0; >> } >>} >> >> >>void >>zzclose_stream() >>{ >>#if 0 >> fclose( zzstream_in ); >> zzstream_in = NULL; >> zzfunc_in = NULL; >>#endif >>} >> >>void >>#ifdef __STDC__ >>zzmode( int m ) >>#else >>zzmode( m ) >>int m; >>#endif >>{ >> /* points to base of dfa table */ >> if (m> zzauto = m; >> /* have to redo class since using different compression */ >> zzclass = ZZSHIFT(zzchar); >> }else{ >> sprintf(zzebuf,"Invalid automaton mode = %d ",m); >> zzerr(zzebuf); >> } >>} >> >>/* erase what is currently in the buffer, and get a new reg. expr */ >>void >>zzskip() >>{ >> zzadd_erase = 1; >>} >> >>/* don't erase what is in the zzlextext buffer, add on to it */ >>void >>zzmore() >>{ >> zzadd_erase = 2; >>} >> >>/* substitute c for the reg. expr last matched and is in the buffer */ >>#ifdef __STDC__ >>void >>zzreplchar(char c) >>#else >>void >>zzreplchar(c) >>char c; >>#endif >>{ >> /* can't allow overwriting null at end of string */ >> if (zzbegexpr < &zzlextext[zzbufsize-1]){ >> *zzbegexpr = c; >> *(zzbegexpr+1) = '\0'; >> } >> zzendexpr = zzbegexpr; >> zznextpos = zzbegexpr + 1; >>} >> >>/* replace the string s for the reg. expr last matched and in the buffer */ >>void >>#ifdef __STDC__ >>zzreplstr(register char *s) >>#else >>zzreplstr(s) >>register char *s; >>#endif >>{ >> register char *l= &zzlextext[zzbufsize -1]; >> >> zznextpos = zzbegexpr; >> if (s){ >> while ((zznextpos <= l) && (*(zznextpos++) = *(s++))){ >> /* empty */ >> } >> /* correct for NULL at end of string */ >> zznextpos--; >> } >> if ((zznextpos <= l) && (*(--s) == 0)){ >> zzbufovf = 0; >> }else{ >> zzbufovf = 1; >> } >> *(zznextpos) = '\0'; >> zzendexpr = zznextpos - 1; >>} >> >>void >>zzgettok() >>{ >> register int state, newstate; >> /* last space reserved for the null char */ >> register char *lastpos; >> >>skip: >> zzbufovf = 0; >> lastpos = &zzlextext[zzbufsize-1]; >> zznextpos = zzlextext; >> zzbegcol = zzendcol+1; >>more: >> zzbegexpr = zznextpos; >>#ifdef ZZINTERACTIVE >> /* interactive version of automaton */ >> /* if there is something in zzchar, process it */ >> state = newstate = dfa_base[zzauto]; >> if (zzcharfull){ >> ZZINC; >> /* Truncate matching buffer to size (not an error) */ >> if (zznextpos < lastpos){ >> *(zznextpos++) = zzchar; >> }else{ >> zzbufovf = 1; >> } >> newstate = dfa[state][zzclass]; >> } >> if (zzstream_in) >> while (zzalternatives[newstate]){ >> state = newstate; >> ZZGETC_STREAM; >> ZZINC; >> /* Truncate matching buffer to size (not an error) */ >> if (zznextpos < lastpos){ >> *(zznextpos++) = zzchar; >> }else{ >> zzbufovf = 1; >> } >> newstate = dfa[state][zzclass]; >> } >> else if (zzfunc_in) >> while (zzalternatives[newstate]){ >> state = newstate; >> ZZGETC_STREAM; >> ZZINC; >> /* Truncate matching buffer to size (not an error) */ >> if (zznextpos < lastpos){ >> *(zznextpos++) = zzchar; >> }else{ >> zzbufovf = 1; >> } >> newstate = dfa[state][zzclass]; >> } >> /* figure out if last character really part of token */ >> if ((state != dfa_base[zzauto]) && (newstate == DfaStates)){ >> zzcharfull = 1; >> --zznextpos; >> }else{ >> zzcharfull = 0; >> state = newstate; >> } >> *(zznextpos) = '\0'; >> /* Able to transition out of start state to some non err state?*/ >> if ( state == dfa_base[zzauto] ){ >> /* make sure doesn't get stuck */ >> zzadvance(); >> } >>#else >> /* non-interactive version of automaton */ >> if (!zzcharfull) >> zzadvance(); >> else >> ZZINC; >> state = dfa_base[zzauto]; >> if (zzstream_in) >> while ((newstate = dfa[state][zzclass]) != DfaStates){ >> state = newstate; >> /* Truncate matching buffer to size (not an error) */ >> if (zznextpos < lastpos){ >> *(zznextpos++) = zzchar; >> }else{ >> zzbufovf = 1; >> } >> ZZGETC_STREAM; >> ZZINC; >> } >> else if (zzfunc_in) >> while ((newstate = dfa[state][zzclass]) != DfaStates){ >> state = newstate; >> /* Truncate matching buffer to size (not an error) */ >> if (zznextpos < lastpos){ >> *(zznextpos++) = zzchar; >> }else{ >> zzbufovf = 1; >> } >> ZZGETC_FUNC; >> ZZINC; >> } >> zzcharfull = 1; >> if ( state == dfa_base[zzauto] ){ >> if (zznextpos < lastpos){ >> *(zznextpos++) = zzchar; >> }else{ >> zzbufovf = 1; >> } >> *zznextpos = '\0'; >> /* make sure doesn't get stuck */ >> zzadvance(); >> }else{ >> *zznextpos = '\0'; >> } >>#endif >>#ifdef ZZCOL >> zzendcol -= zzcharfull; >>#endif >> zzendexpr = zznextpos -1; >> zzadd_erase = 0; >> (*actions[accepts[state]])(); >> switch (zzadd_erase) { >> case 1: goto skip; >> case 2: goto more; >> } >>} >> >>void >>zzadvance() >>{ >> if (zzstream_in) { ZZGETC_STREAM; zzcharfull = 1; ZZINC;} >> if (zzfunc_in) { ZZGETC_FUNC; zzcharfull = 1; ZZINC;} >> if (!(zzstream_in || zzfunc_in)){ >> zzerr_in(); >> } >>} >> >>void >>#ifdef __STDC__ >>zzerrstd(char *s) >>#else >>zzerrstd(s) >>char *s; >>#endif >>{ >> fprintf(stderr, >> "%s near line %d (text was '%s')\n", >> ((s == NULL) ? "Lexical error" : s), >> zzline,zzlextext); >>} >> >>int >>zzerr_in() >>{ >> fprintf(stderr,"No input stream or function\n"); >> /* return eof to get out gracefully */ >> return -1; >>} >EOF_dlgauto.h >cat << \EOF_err.h | sed 's/^>//' > err.h >>/* >> * err.h >> * >> * Standard error handling mechanism >> * >> * Terence Parr, Hank Dietz and Will Cohen: 1989, 1990, 1991, 1992 >> * Purdue University Electrical Engineering >> * ANTLR Version 1.06 >> */ >> >>#include >>#ifdef __STDC__ >>#include >>#else >>#include >>#endif >> >>/* Define usable bits per unsigned int word (used for set stuff) */ >>#ifdef PC >>#define WORDSIZE 16 >>#define LogWordSize 4 >>#else >>#define WORDSIZE 32 >>#define LogWordSize 5 >>#endif >> >>#define MODWORD(x) ((x) & (WORDSIZE-1)) /* x % WORDSIZE */ >>#define DIVWORD(x) ((x) >> LogWordSize) /* x / WORDSIZE */ >> >>/* maximum of 32 bits/unsigned int and must be 8 bits/byte */ >>static unsigned bitmask[] = { >> 0x00000001, 0x00000002, 0x00000004, 0x00000008, >> 0x00000010, 0x00000020, 0x00000040, 0x00000080, >> 0x00000100, 0x00000200, 0x00000400, 0x00000800, >> 0x00001000, 0x00002000, 0x00004000, 0x00008000, >> 0x00010000, 0x00020000, 0x00040000, 0x00080000, >> 0x00100000, 0x00200000, 0x00400000, 0x00800000, >> 0x01000000, 0x02000000, 0x04000000, 0x08000000, >> 0x10000000, 0x20000000, 0x40000000, 0x80000000 >>}; >> >>void >>#ifdef __STDC__ >>zzresynch(unsigned *wd,unsigned mask) >>#else >>zzresynch(wd,mask) >>unsigned *wd, mask; >>#endif >>{ >> while ( !(wd[LA(1)]&mask) && LA(1) != zzEOF_TOKEN ) {zzCONSUME;} >>} >> >>/* input looks like: >> * zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText) >> * where the zzMiss stuff is set here to the token that did not match >> * (and which set wasn't it a member of). >> */ >>void >>#ifdef __STDC__ >>zzFAIL(int k, ...) >>#else >>zzFAIL(va_alist) >>va_dcl >>#endif >>{ >>#ifdef LL_K >> static char text[LL_K*ZZLEXBUFSIZE+1]; >> unsigned *f[LL_K]; >>#else >> static char text[ZZLEXBUFSIZE+1]; >> unsigned *f[1]; >>#endif >> unsigned **miss_set; >> char **miss_text; >> unsigned *bad_tok; >> char **bad_text; >> unsigned *err_k; >> int i; >> va_list ap; >>#ifndef __STDC__ >> int k; >>#endif >>#ifdef __STDC__ >> va_start(ap, k); >>#else >> va_start(ap); >> k = va_arg(ap, int); /* how many lookahead sets? */ >>#endif >> text[0] = '\0'; >> for (i=1; i<=k; i++) /* collect all lookahead sets */ >> { >> f[i-1] = va_arg(ap, unsigned *); >> } >> for (i=1; i<=k; i++) /* look for offending token */ >> { >> if ( i>1 ) strcat(text, " "); >> strcat(text, LATEXT(i)); >> if ( !zzset_el(LA(i), f[i-1]) ) break; >> } >> miss_set = va_arg(ap, unsigned **); >> miss_text = va_arg(ap, char **); >> bad_tok = va_arg(ap, unsigned *); >> bad_text = va_arg(ap, char **); >> err_k = va_arg(ap, unsigned *); >> if ( i>k ) >> { >> /* bad; lookahead is permutation that cannot be matched, >> * but, the ith token of lookahead is valid at the ith position >> * (The old LL sub 1 (k) versus LL(k) parsing technique) >> */ >> *miss_set = NULL; >> *miss_text = zzlextext; >> *bad_tok = LA(1); >> *bad_text = LATEXT(1); >> *err_k = k; >> return; >> } >>/* fprintf(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/ >> *miss_set = f[i-1]; >> *miss_text = text; >> *bad_tok = LA(i); >> *bad_text = LATEXT(i); >> if ( i==1 ) *err_k = 1; >> else *err_k = k; >>} >> >>/* standard error reporting function */ >>void >>#ifdef __STDC__ >>zzsyn(char *text, unsigned tok, char *egroup, unsigned *eset, int etok, int k, char *bad_text) >>#else >>zzsyn(text, tok, egroup, eset, etok, k, bad_text) >>char *text, *egroup, *bad_text; >>unsigned tok; >>int etok, k; >>unsigned *eset; >>#endif >>{ >> >> fprintf(stderr, "line %d: syntax error at \"%s\"", zzline, (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) > 0 ) fprintf(stderr, " in %s", egroup); >> fprintf(stderr, "\n"); >>} >> >>/* is b an element of set p? */ >>int >>#ifdef __STDC__ >>zzset_el(unsigned b, unsigned *p) >>#else >>zzset_el(b,p) >>unsigned b; >>unsigned *p; >>#endif >>{ >> return( p[DIVWORD(b)] & bitmask[MODWORD(b)] ); >>} >> >>int >>#ifdef __STDC__ >>zzset_deg(unsigned *a) >>#else >>zzset_deg(a) >>unsigned *a; >>#endif >>{ >> /* Fast compute degree of a set... the number >> of elements present in the set. Assumes >> that all word bits are used in the set >> */ >> register unsigned *p = a; >> register unsigned *endp = &(a[zzSET_SIZE]); >> register unsigned degree = 0; >> >> if ( a == NULL ) return 0; >> while ( p < endp ) >> { >> register unsigned t = *p; >> register unsigned *b = &(bitmask[0]); >> do { >> if (t & *b) ++degree; >> } while (++b < &(bitmask[WORDSIZE])); >> p++; >> } >> >> return(degree); >>} >> >>void >>#ifdef __STDC__ >>zzedecode(unsigned *a) >>#else >>zzedecode(a) >>unsigned *a; >>#endif >>{ >> register unsigned *p = a; >> register unsigned *endp = &(p[zzSET_SIZE]); >> register unsigned e = 0; >> >> if ( zzset_deg(a)>1 ) fprintf(stderr, " {"); >> do { >> register unsigned t = *p; >> register unsigned *b = &(bitmask[0]); >> do { >> if ( t & *b ) fprintf(stderr, " %s", zztokens[e]); >> e++; >> } while (++b < &(bitmask[sizeof(unsigned)*8])); >> } while (++p < endp); >> if ( zzset_deg(a)>1 ) fprintf(stderr, " }"); >>} >EOF_err.h >cat << \EOF_charptr.h | sed 's/^>//' > charptr.h >>/* >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >>typedef char *Attrib; >>#define zzdef0(a) {*(a)=NULL;} >>#define zzd_attr(a) {if ( *(a)!=NULL ) free(*a);} >> >>#ifdef __STDC__ >>extern zzcr_attr(Attrib *,int,char *); >>extern void free(void *); >>#endif >EOF_charptr.h >cat << \EOF_ast.c | sed 's/^>//' > ast.c >>/* Abstract syntax tree manipulation functions >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#ifdef __STDC__ >>#include >>#else >>#include >>#endif >> >>/* ensure that tree manipulation variables are current after a rule >> * reference >> */ >>void >>zzlink(_root, _sibling, _tail) >>AST **_root, **_sibling, **_tail; >>{ >> if ( *_sibling == NULL ) return; >> if ( *_root == NULL ) *_root = *_sibling; >> else if ( *_root != *_sibling ) (*_root)->down = *_sibling; >> if ( *_tail==NULL ) *_tail = *_sibling; >> while ( (*_tail)->right != NULL ) *_tail = (*_tail)->right; >>} >> >>AST * >>zzastnew() >>{ >>#ifdef __STDC__ >> extern char *calloc(unsigned, unsigned); >>#else >> extern char *calloc(); >>#endif >> >> AST *p = (AST *) calloc(1, sizeof(AST)); >> if ( p == NULL ) fprintf(stderr,"%s(%d): cannot allocate AST node\n",__FILE__,__LINE__); >> return p; >>} >> >>/* add a child node to the current sibling list */ >>void >>zzsubchild(_root, _sibling, _tail) >>AST **_root, **_sibling, **_tail; >>{ >> AST *n = zzastnew(); >>#ifdef DEMAND_LOOK >> zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0)); >>#else >> zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1)); >>#endif >> zzastPush( n ); >> if ( *_tail != NULL ) (*_tail)->right = n; >> else { >> *_sibling = n; >> if ( *_root != NULL ) (*_root)->down = *_sibling; >> } >> *_tail = n; >> if ( *_root == NULL ) *_root = *_sibling; >>} >> >>/* make a new AST node. Make the newly-created >> * node the root for the current sibling list. If a root node already >> * exists, make the newly-created node the root of the current root. >> */ >>void >>zzsubroot(_root, _sibling, _tail) >>AST **_root, **_sibling, **_tail; >>{ >> AST *n = zzastnew(); >>#ifdef DEMAND_LOOK >> zzcr_ast(n, &(zzaCur), LA(0), LATEXT(0)); >>#else >> zzcr_ast(n, &(zzaCur), LA(1), LATEXT(1)); >>#endif >> zzastPush( n ); >> if ( *_root != NULL ) >> if ( (*_root)->down == *_sibling ) *_sibling = *_tail = *_root; >> *_root = n; >> (*_root)->down = *_sibling; >>} >> >>/* Apply function to root then each sibling >> * example: print tree in child-sibling LISP-format (AST has token field) >> * >> * void show(tree) >> * AST *tree; >> * { >> * if ( tree == NULL ) return; >> * printf(" %s", zztokens[tree->token]); >> * } >> * >> * void before() { printf(" ("); } >> * void after() { printf(" )"); } >> * >> * LISPdump() { zzpre_ast(tree, show, before, after); } >> * >> */ >>void >>zzpre_ast(tree, func, before, after) >>AST *tree; >>void (*func)(), /* apply this to each tree node */ >> (*before)(), /* apply this to root of subtree before preordering it */ >> (*after)(); /* apply this to root of subtree after preordering it */ >>{ >> while ( tree!= NULL ) >> { >> if ( tree->down != NULL ) (*before)(tree); >> (*func)(tree); >> zzpre_ast(tree->down, func, before, after); >> if ( tree->down != NULL ) (*after)(tree); >> tree = tree->right; >> } >>} >> >>/* free all AST nodes in tree; apply func to each before freeing */ >>void >>zzfree_ast(tree) >>AST *tree; >>{ >> if ( tree == NULL ) return; >> zzfree_ast( tree->down ); >> zzfree_ast( tree->right ); >> zztfree( tree ); >>} >> >>/* build a tree (root child1 child2 ... NULL) >> * If root is NULL, simply make the children siblings and return ptr >> * to 1st sibling (child1). If root is not single node, return NULL. >> * >> * Siblings that are actually siblins lists themselves are handled >> * correctly. For example #( NULL, #( NULL, A, B, C), D) results >> * in the tree ( NULL A B C D ). >> * >> * Requires at least two parameters with the last one being NULL. If >> * both are NULL, return NULL. >> */ >>#ifdef __STDC__ >>AST *zztmake(AST *rt, ...) >>#else >>AST *zztmake(va_alist) >>va_dcl >>#endif >>{ >> va_list ap; >> register AST *child, *sibling=NULL, *tail, *w; >> AST *root; >> >>#ifdef __STDC__ >> va_start(ap, rt); >> root = rt; >>#else >> va_start(ap); >> root = va_arg(ap, AST *); >>#endif >> >> if ( root != NULL ) >> if ( root->down != NULL ) return NULL; >> child = va_arg(ap, AST *); >> while ( child != NULL ) >> { >> for (w=child; w->right!=NULL; w=w->right) {;} /* find end of child */ >> if ( sibling == NULL ) {sibling = child; tail = w;} >> else {tail->right = child; tail = w;} >> child = va_arg(ap, AST *); >> } >> if ( root==NULL ) root = sibling; >> else root->down = sibling; >> va_end(ap); >> return root; >>} >> >>/* tree duplicate */ >>AST * >>zzdup_ast(t) >>AST *t; >>{ >> AST *u; >> >> if ( t == NULL ) return NULL; >> u = zzastnew(); >> *u = *t; >> u->right = zzdup_ast(t->right); >> u->down = zzdup_ast(t->down); >> return u; >>} >> >>void >>zztfree(t) >>AST *t; >>{ >>#ifdef zzd_ast >> zzd_ast( t ); >>#endif >> free( t ); >>} >> >>#ifdef zzAST_DOUBLE >>/* >> * Set the 'up', and 'left' pointers of all nodes in 't'. >> * USER MUST CREATE up, left FIELDS using AST_FIELDS macro. >> * Initial call is double_link(your_tree, NULL, NULL). >> */ >>void >>zzdouble_link(t, left, up) >>AST *t, *left, *up; >>{ >> if ( t==NULL ) return; >> t->left = left; >> t->up = up; >> zzdouble_link(t->down, NULL, t); >> zzdouble_link(t->right, t, up); >>} >>#endif >EOF_ast.c >cat << \EOF_dlgdef.h | sed 's/^>//' > dlgdef.h >>/* dlg2.h >> * Things in scanner produced by dlg that should be visible to the outside >> * world >> * >> * 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.06 >> * Will Cohen >> * Purdue University >> * 1989-1992 >> */ >> >>#ifdef __STDC__ >>extern char *zzlextext; /* text of most recently matched token */ >>extern char *zzbegexpr; /* beginning of last reg expr recogn. */ >>extern char *zzendexpr; /* beginning of last reg expr recogn. */ >>extern int zzbufsize; /* how long zzlextext is */ >>extern int zzbegcol; /* column that first character of token is in*/ >>extern int zzendcol; /* column that last character of token is in */ >>extern int zzline; /* line current token is on */ >>extern int zzchar; /* character to determine next state */ >>extern int zzbufovf; /* indicates that buffer too small for text */ >> >>/* functions */ >>extern void zzadvance(); >>extern void (*zzerr)(char *);/* pointer to error reporting function */ >>extern void zzskip(); /* erase zzlextext, look for antoher token */ >>extern void zzmore(); /* keep zzlextext, look for another token */ >>extern void zzmode(int k); /* switch to automaton 'k' */ >>extern void zzrdstream(FILE *);/* what stream to read from */ >>extern void zzclose_stream();/* close the current input stream */ >>extern void zzrdfunc(int (*)());/* what function to get char from */ >>extern void zzgettok(); /* get next token */ >>extern void zzreplchar(char c);/* replace last recognized reg. expr. with >> a character */ >>extern void zzreplstr(char *s);/* replace last recognized reg. expr. with >> a string */ >>#else >>extern char *zzlextext; /* text of most recently matched token */ >>extern char *zzbegexpr; /* beginning of last reg expr recogn. */ >>extern char *zzendexpr; /* beginning of last reg expr recogn. */ >>extern int zzbufsize; /* how long zzlextext is */ >>extern int zzbegcol; /* column that first character of token is in*/ >>extern int zzendcol; /* column that last character of token is in */ >>extern int zzline; /* line current token is on */ >>extern int zzchar; /* character to determine next state */ >>extern int zzbufovf; /* indicates that buffer too small for text */ >> >>/* functions */ >>extern void zzadvance(); >>extern void (*zzerr)(); /* pointer to error reporting function */ >>extern void zzskip(); /* erase zzlextext, look for antoher token */ >>extern void zzmore(); /* keep zzlextext, look for another token */ >>extern void zzmode(/*k*/); /* switch to automaton 'k' */ >>extern void zzrdstream(); /* what stream to read from */ >>extern void zzclose_stream();/* close the current input stream */ >>extern void zzrdfunc(); /* what function to get char from */ >>extern void zzgettok(); /* get next token */ >>extern void zzreplchar(); /* replace last recognized reg. expr. with >> a character */ >>extern void zzreplstr(); /* replace last recognized reg. expr. with >> a string */ >>#endif >EOF_dlgdef.h >cat << \EOF_int.h | sed 's/^>//' > int.h >>/* ANTLR attribute definition -- long integers >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >>typedef long Attrib; >> >>#define zzcr_attr(a,tok,t) *(a) = atoi(t); >EOF_int.h >cat << \EOF_charptr.c | sed 's/^>//' > charptr.c >>/* >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >>#ifdef __STDC__ >>char *malloc(unsigned); >>int strlen(char *); >>void strcpy(char *, char *); >>#else >>char *malloc(); >>int strlen(); >>void strcpy(); >>#endif >> >>#ifdef __STDC__ >>zzcr_attr(Attrib *a,int token,char *text) >>#else >>zzcr_attr(a,token,text) >>Attrib *a; >>int token; >>char *text; >>#endif >>{ >> *a = malloc(strlen(text)+1); >> if ( *a == NULL ) {fprintf(stderr, "zzcr_attr: out of memory!\n"); exit(-1);} >> strcpy(*a, text); >>} >EOF_charptr.c >cat << \EOF_charbuf.h | sed 's/^>//' > charbuf.h >>/* ANTLR attribute definition -- constant width text >> * >> * 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.06 >> * Terence Parr >> * Purdue University >> * 1989-1992 >> */ >> >>#ifndef D_TextSize >>#define D_TextSize 30 >>#endif >> >>typedef struct { char text[D_TextSize]; } Attrib; >> >>#define zzcr_attr(a,tok,t) strncpy((a)->text, t, D_TextSize-1); >EOF_charbuf.h >cat << \EOF_err.h | sed 's/^>//' > err.h >>/* >> * err.h >> * >> * Standard error handling mechanism >> * >> * Terence Parr, Hank Dietz and Will Cohen: 1989, 1990, 1991, 1992 >> * Purdue University Electrical Engineering >> * ANTLR Version 1.06 >> */ >> >>#include >>#ifdef __STDC__ >>#include >>#else >>#include >>#endif >> >>/* Define usable bits per unsigned int word (used for set stuff) */ >>#ifdef PC >>#define WORDSIZE 16 >>#define LogWordSize 4 >>#else >>#define WORDSIZE 32 >>#define LogWordSize 5 >>#endif >> >>#define MODWORD(x) ((x) & (WORDSIZE-1)) /* x % WORDSIZE */ >>#define DIVWORD(x) ((x) >> LogWordSize) /* x / WORDSIZE */ >> >>/* maximum of 32 bits/unsigned int and must be 8 bits/byte */ >>static unsigned bitmask[] = { >> 0x00000001, 0x00000002, 0x00000004, 0x00000008, >> 0x00000010, 0x00000020, 0x00000040, 0x00000080, >> 0x00000100, 0x00000200, 0x00000400, 0x00000800, >> 0x00001000, 0x00002000, 0x00004000, 0x00008000, >> 0x00010000, 0x00020000, 0x00040000, 0x00080000, >> 0x00100000, 0x00200000, 0x00400000, 0x00800000, >> 0x01000000, 0x02000000, 0x04000000, 0x08000000, >> 0x10000000, 0x20000000, 0x40000000, 0x80000000 >>}; >> >>void >>#ifdef __STDC__ >>zzresynch(unsigned *wd,unsigned mask) >>#else >>zzresynch(wd,mask) >>unsigned *wd, mask; >>#endif >>{ >> while ( !(wd[LA(1)]&mask) && LA(1) != zzEOF_TOKEN ) {zzCONSUME;} >>} >> >>/* input looks like: >> * zzFAIL(k, e1, e2, ...,&zzMissSet,&zzMissText,&zzBadTok,&zzBadText) >> * where the zzMiss stuff is set here to the token that did not match >> * (and which set wasn't it a member of). >> */ >>void >>#ifdef __STDC__ >>zzFAIL(int k, ...) >>#else >>zzFAIL(va_alist) >>va_dcl >>#endif >>{ >>#ifdef LL_K >> static char text[LL_K*ZZLEXBUFSIZE+1]; >> unsigned *f[LL_K]; >>#else >> static char text[ZZLEXBUFSIZE+1]; >> unsigned *f[1]; >>#endif >> unsigned **miss_set; >> char **miss_text; >> unsigned *bad_tok; >> char **bad_text; >> unsigned *err_k; >> int i; >> va_list ap; >>#ifndef __STDC__ >> int k; >>#endif >>#ifdef __STDC__ >> va_start(ap, k); >>#else >> va_start(ap); >> k = va_arg(ap, int); /* how many lookahead sets? */ >>#endif >> text[0] = '\0'; >> for (i=1; i<=k; i++) /* collect all lookahead sets */ >> { >> f[i-1] = va_arg(ap, unsigned *); >> } >> for (i=1; i<=k; i++) /* look for offending token */ >> { >> if ( i>1 ) strcat(text, " "); >> strcat(text, LATEXT(i)); >> if ( !zzset_el(LA(i), f[i-1]) ) break; >> } >> miss_set = va_arg(ap, unsigned **); >> miss_text = va_arg(ap, char **); >> bad_tok = va_arg(ap, unsigned *); >> bad_text = va_arg(ap, char **); >> err_k = va_arg(ap, unsigned *); >> if ( i>k ) >> { >> /* bad; lookahead is permutation that cannot be matched, >> * but, the ith token of lookahead is valid at the ith position >> * (The old LL sub 1 (k) versus LL(k) parsing technique) >> */ >> *miss_set = NULL; >> *miss_text = zzlextext; >> *bad_tok = LA(1); >> *bad_text = LATEXT(1); >> *err_k = k; >> return; >> } >>/* fprintf(stderr, "%s not in %dth set\n", zztokens[LA(i)], i);*/ >> *miss_set = f[i-1]; >> *miss_text = text; >> *bad_tok = LA(i); >> *bad_text = LATEXT(i); >> if ( i==1 ) *err_k = 1; >> else *err_k = k; >>} >> >>/* standard error reporting function */ >>void >>#ifdef __STDC__ >>zzsyn(char *text, unsigned tok, char *egroup, unsigned *eset, int etok, int k, char *bad_text) >>#else >>zzsyn(text, tok, egroup, eset, etok, k, bad_text) >>char *text, *egroup, *bad_text; >>unsigned tok; >>int etok, k; >>unsigned *eset; >>#endif >>{ >> >> fprintf(stderr, "line %d: syntax error at \"%s\"", zzline, (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) > 0 ) fprintf(stderr, " in %s", egroup); >> fprintf(stderr, "\n"); >>} >> >>/* is b an element of set p? */ >>int >>#ifdef __STDC__ >>zzset_el(unsigned b, unsigned *p) >>#else >>zzset_el(b,p) >>unsigned b; >>unsigned *p; >>#endif >>{ >> return( p[DIVWORD(b)] & bitmask[MODWORD(b)] ); >>} >> >>int >>#ifdef __STDC__ >>zzset_deg(unsigned *a) >>#else >>zzset_deg(a) >>unsigned *a; >>#endif >>{ >> /* Fast compute degree of a set... the number >> of elements present in the set. Assumes >> that all word bits are used in the set >> */ >> register unsigned *p = a; >> register unsigned *endp = &(a[zzSET_SIZE]); >> register unsigned degree = 0; >> >> if ( a == NULL ) return 0; >> while ( p < endp ) >> { >> register unsigned t = *p; >> register unsigned *b = &(bitmask[0]); >> do { >> if (t & *b) ++degree; >> } while (++b < &(bitmask[WORDSIZE])); >> p++; >> } >> >> return(degree); >>} >> >>void >>#ifdef __STDC__ >>zzedecode(unsigned *a) >>#else >>zzedecode(a) >>unsigned *a; >>#endif >>{ >> register unsigned *p = a; >> register unsigned *endp = &(p[zzSET_SIZE]); >> register unsigned e = 0; >> >> if ( zzset_deg(a)>1 ) fprintf(stderr, " {"); >> do { >> register unsigned t = *p; >> register unsigned *b = &(bitmask[0]); >> do { >> if ( t & *b ) fprintf(stderr, " %s", zztokens[e]); >> e++; >> } while (++b < &(bitmask[sizeof(unsigned)*8])); >> } while (++p < endp); >> if ( zzset_deg(a)>1 ) fprintf(stderr, " }"); >>} >EOF_err.h EOF_h.bag cat << \EOF_set.bag | sed 's/^>//' > set.bag >cat << \EOF_set.c | sed 's/^>//' > set.c >>/* set.c >> >> The following is a general-purpose set library originally developed >> by Hank Dietz and enhanced by Terence Parr to allow dynamic sets. >> >> Sets are now structs containing the #words in the set and >> a pointer to the actual set words. >> >> Generally, sets need not be explicitly allocated. They are >> created/extended/shrunk when appropriate (e.g. in set_of()). >> HOWEVER, sets need to be destroyed (free()ed) when they go out of scope >> or are otherwise no longer needed. A routine is provided to >> free a set. >> >> Sets can be explicitly created with set_new(s, max_elem). >> >> Sets can be declared to have minimum size to reduce realloc traffic. >> Default minimum size = 1. >> >> Sets can be explicitly initialized to have no elements (set.n == 0) >> by using the 'empty' initializer: >> >> Examples: >> set a = empty; -- set_deg(a) == 0 >> >> return( empty ); >> >> Example set creation and destruction: >> >> set >> set_of2(e,g) >> unsigned e,g; >> { >> set a,b,c; >> >> b = set_of(e); -- Creates space for b and sticks in e >> set_new(c, g); -- set_new(); set_orel() ==> set_of() >> set_orel(g, &c); >> a = set_or(b, c); >> . >> . >> . >> set_free(b); >> set_free(c); >> return( a ); >> } >> >> 1987 by Hank Dietz >> >> Modified by: >> Terence Parr >> Purdue University >> October 1989 >>*/ >> >>#include >>#ifdef MEMCHK >>#include "trax.h" >>#else >>char *calloc(), *malloc(), *realloc(); >>#endif >>#include "set.h" >> >>/* elems can be a maximum of 32 bits */ >>static unsigned bitmask[] = { >> 0x00000001, 0x00000002, 0x00000004, 0x00000008, >> 0x00000010, 0x00000020, 0x00000040, 0x00000080, >> 0x00000100, 0x00000200, 0x00000400, 0x00000800, >> 0x00001000, 0x00002000, 0x00004000, 0x00008000, >> 0x00010000, 0x00020000, 0x00040000, 0x00080000, >> 0x00100000, 0x00200000, 0x00400000, 0x00800000, >> 0x01000000, 0x02000000, 0x04000000, 0x08000000, >> 0x10000000, 0x20000000, 0x40000000, 0x80000000 >>}; >> >>set empty = set_init; >>static unsigned min=1; >> >>#define StrSize 200 >> >>#ifdef MEMCHK >>#define CHK(a) \ >> if ( a.setword != NULL ) \ >> if ( !valid(a.setword) ) \ >> {fprintf(stderr, "%s(%d): invalid set\n",__FILE__,__LINE__); exit(-1);} >>#else >>#define CHK(a) >>#endif >> >>/* >> * Set the minimum size (in words) of a set to reduce realloc calls >> */ >>void >>set_size(n) >>unsigned n; >>{ >> min = n; >>} >> >>unsigned int >>set_deg(a) >>set a; >>{ >> /* Fast compute degree of a set... the number >> of elements present in the set. Assumes >> that all word bits are used in the set >> and that SETSIZE(a) is a multiple of WORDSIZE. >> */ >> register unsigned *p = &(a.setword[0]); >> register unsigned *endp = &(a.setword[a.n]); >> register unsigned degree = 0; >> >> CHK(a); >> if ( a.n == 0 ) return(0); >> while ( p < endp ) >> { >> register unsigned t = *p; >> register unsigned *b = &(bitmask[0]); >> do { >> if (t & *b) ++degree; >> } while (++b < &(bitmask[WORDSIZE])); >> p++; >> } >> >> return(degree); >>} >> >>set >>set_or(b,c) >>set b, c; >>{ >> /* Fast set union operation */ >> /* resultant set size is max(b, c); */ >> set *big; >> set t; >> unsigned int m,n; >> register unsigned *r, *p, *q, *endp; >> >> CHK(b); CHK(c); >> t = empty; >> if (b.n > c.n) {big= &b; m=b.n; n=c.n;} else {big= &c; m=c.n; n=b.n;} >> set_ext(&t, m); >> r = t.setword; >> >> /* Or b,c until max of smaller set */ >> q = c.setword; >> p = b.setword; >> endp = &(b.setword[n]); >> while ( p < endp ) *r++ = *p++ | *q++; >> >> /* Copy rest of bigger set into result */ >> p = &(big->setword[n]); >> endp = &(big->setword[m]); >> while ( p < endp ) *r++ = *p++; >> >> return(t); >>} >> >>set >>set_and(b,c) >>set b, c; >>{ >> /* Fast set intersection operation */ >> /* resultant set size is min(b, c); */ >> set t; >> unsigned int n; >> register unsigned *r, *p, *q, *endp; >> >> CHK(b); CHK(c); >> t = empty; >> n = (b.n > c.n) ? c.n : b.n; >> if ( n == 0 ) return t; /* TJP 4-27-92 fixed for empty set */ >> set_ext(&t, n); >> r = t.setword; >> >> /* & b,c until max of smaller set */ >> q = c.setword; >> p = b.setword; >> endp = &(b.setword[n]); >> while ( p < endp ) *r++ = *p++ & *q++; >> >> return(t); >>} >> >>set >>set_dif(b,c) >>set b, c; >>{ >> /* Fast set difference operation b - c */ >> /* resultant set size is size(b) */ >> set t; >> unsigned int n; >> register unsigned *r, *p, *q, *endp; >> >> CHK(b); CHK(c); >> t = empty; >> n = (b.n <= c.n) ? b.n : c.n ; >> if ( b.n == 0 ) return t; /* TJP 4-27-92 fixed for empty set */ >> /* WEC 12-1-92 fixed for c.n = 0 */ >> set_ext(&t, b.n); >> r = t.setword; >> >> /* Dif b,c until smaller set size */ >> q = c.setword; >> p = b.setword; >> endp = &(b.setword[n]); >> while ( p < endp ) *r++ = *p++ & (~ *q++); >> >> /* Copy rest of b into result if size(b) > c */ >> if ( b.n > n ) >> { >> p = &(b.setword[n]); >> endp = &(b.setword[b.n]); >> while ( p < endp ) *r++ = *p++; >> } >> >> return(t); >>} >> >>set >>set_of(b) >>unsigned b; >>{ >> /* Fast singleton set constructor operation */ >> static set a; >> >> if ( b == nil ) return( empty ); >> set_new(a, b); >> a.setword[DIVWORD(b)] = bitmask[MODWORD(b)]; >> >> return(a); >>} >> >>/* >> * Extend (or shrink) the set passed in to have n words. >> * >> * if n is smaller than the minimum, boost n to have the minimum. >> * if the new set size is the same as the old one, do nothing. >> * >> * TJP 4-27-92 Fixed so won't try to alloc 0 bytes >> */ >>void >>set_ext(a, n) >>set *a; >>unsigned int n; >>{ >> register unsigned *p; >> register unsigned *endp; >> unsigned int size; >> >> CHK((*a)); >> if ( a->n == 0 ) >> { >> if ( n == 0 ) return; >> a->setword = (unsigned *) calloc(n, BytesPerWord); >> if ( a->setword == NULL ) >> { >> fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n); >> *((char *)5) = 1; >> exit(-1); >> } >> a->n = n; >> return; >> } >> if ( n < min ) n = min; >> if ( a->n == n || n == 0 ) return; >> size = a->n; >> a->n = n; >> a->setword = (unsigned *) realloc( a->setword, (n*BytesPerWord) ); >> if ( a->setword == NULL ) >> { >> fprintf(stderr, "set_ext(%d words): cannot allocate set\n", n); >> exit(-1); >> } >> >> p = &(a->setword[size]); /* clear from old size to new size */ >> endp = &(a->setword[a->n]); >> do { >> *p++ = 0; >> } while ( p < endp ); >>} >> >>set >>set_not(a) >>set a; >>{ >> /* Fast not of set a (assumes all bits used) */ >> /* size of resultant set is size(a) */ >> /* ~empty = empty cause we don't know how bit to make set */ >> set t; >> register unsigned *r; >> register unsigned *p = a.setword; >> register unsigned *endp = &(a.setword[a.n]); >> >> CHK(a); >> t = empty; >> if ( a.n == 0 ) return( empty ); >> set_ext(&t, a.n); >> r = t.setword; >> >> do { >> *r++ = (~ *p++); >> } while ( p < endp ); >> >> return(t); >>} >> >>int >>set_equ(a,b) >>set a, b; >>{ >> /* Fast set equality comparison operation */ >> register unsigned *p = a.setword; >> register unsigned *q = b.setword; >> register unsigned *endp = &(a.setword[a.n]); >> >> CHK(a); CHK(b); >> if ( a.n != b.n ) return(0); >> else if ( a.n==0 ) return(1); /* empty == empty */ >> >> do { >> if (*p != *q) return(0); >> ++q; >> } while ( ++p < endp ); >> >> return(1); >>} >> >>int >>set_sub(a,b) >>set a, b; >>{ >> /* Fast check for a is a proper subset of b (alias a < b) */ >> register unsigned *p = a.setword; >> register unsigned *q = b.setword; >> register unsigned *endp = &(a.setword[a.n]); >> register int asubset = 0; >> >> CHK(a); CHK(b); >> if ( a.n > b.n ) return(0); >> if ( a.n == 0 ) return(1); /* empty is sub of everything */ >> if (a.n==0 && b.n==0) return(1);/* empty prop sub of empty */ >> >> do { >> /* Prune tests based on guess that most set words >> will match, particularly if a is a subset of b. >> */ >> if (*p != *q) { >> if (*p & ~(*q)) { >> /* Fail -- a contains something b does not */ >> return(0); >> } >> /* At least this word was a proper subset, hence >> even if all other words are equal, a is a >> proper subset of b. >> */ >> asubset = 1; >> } >> ++q; >> } while (++p < endp); >> >> /* at this point, a,b are equ or a subset */ >> if ( asubset || b.n == a.n ) return(asubset); >> >> /* if !asubset, size(b) > size(a), then a=b and must check rest of b */ >> p = q; >> endp = &(a.setword[b.n]); >> do >> { >> if ( *p++ ) return(1); >> } while ( p < endp ); >> >> return(0); >>} >> >>unsigned >>set_int(b) >>set b; >>{ >> /* Fast pick any element of the set b */ >> register unsigned *p = b.setword; >> register unsigned *endp = &(b.setword[b.n]); >> >> CHK(b); >> if ( b.n == 0 ) return( nil ); >> >> do { >> if (*p) { >> /* Found a non-empty word of the set */ >> register unsigned i = ((p - b.setword) << LogWordSize); >> register unsigned t = *p; >> p = &(bitmask[0]); >> while (!(*p & t)) { >> ++i; ++p; >> } >> return(i); >> } >> } while (++p < endp); >> >> /* Empty -- only element it contains is nil */ >> return(nil); >>} >> >>int >>set_el(b,a) >>unsigned b; >>set a; >>{ >> CHK(a); >> /* nil is an element of every set */ >> if (b == nil) return(1); >> if ( a.n == 0 || NumWords(b) > a.n ) return(0); >> >> /* Otherwise, we have to check */ >> return( a.setword[DIVWORD(b)] & bitmask[MODWORD(b)] ); >>} >> >>set_nil(a) >>set a; >>{ >> /* Fast check for nil set */ >> register unsigned *p = a.setword; >> register unsigned *endp = &(a.setword[a.n]); >> >> CHK(a); >> if ( a.n == 0 ) return(1); >> /* The set is not empty if any word used to store >> the set is non-zero. This means one must be a >> bit careful about doing things like negation. >> */ >> do { >> if (*p) return(0); >> } while (++p < endp); >> >> return(1); >>} >> >>char * >>set_str(a) >>set a; >>{ >> /* Fast convert set a into ASCII char string... >> assumes that all word bits are used in the set >> and that SETSIZE is a multiple of WORDSIZE. >> Trailing 0 bits are removed from the string. >> if no bits are on or set is empty, "" is returned. >> */ >> register unsigned *p = a.setword; >> register unsigned *endp = &(a.setword[a.n]); >> static char str_tmp[StrSize+1]; >> register char *q = &(str_tmp[0]); >> >> CHK(a); >> if ( a.n==0 ) {*q=0; return( &(str_tmp[0]) );} >> do { >> register unsigned t = *p; >> register unsigned *b = &(bitmask[0]); >> do { >> *(q++) = ((t & *b) ? '1' : '0'); >> } while (++b < &(bitmask[WORDSIZE])); >> } while (++p < endp); >> >> /* Trim trailing 0s & NULL terminate the string */ >> while ((q > &(str_tmp[0])) && (*(q-1) != '1')) --q; >> *q = 0; >> >> return(&(str_tmp[0])); >>} >> >>set >>set_val(s) >>register char *s; >>{ >> /* Fast convert set ASCII char string into a set. >> If the string ends early, the remaining set bits >> are all made zero. >> The resulting set size is just big enough to hold all elements. >> */ >> static set a; >> register unsigned *p, *endp; >> >> set_new(a, strlen(s)); >> p = a.setword; >> endp = &(a.setword[a.n]); >> do { >> register unsigned *b = &(bitmask[0]); >> /* Start with a word with no bits on */ >> *p = 0; >> do { >> if (*s) { >> if (*s == '1') { >> /* Turn-on this bit */ >> *p |= *b; >> } >> ++s; >> } >> } while (++b < &(bitmask[WORDSIZE])); >> } while (++p < endp); >> >> return(a); >>} >> >>/* >> * Or element e into set a. a can be empty. >> */ >>void >>set_orel(e, a) >>unsigned e; >>set *a; >>{ >> CHK((*a)); >> if ( e == nil ) return; >> if ( NumWords(e) > a->n ) set_ext(a, NumWords(e)); >> a->setword[DIVWORD(e)] |= bitmask[MODWORD(e)]; >>} >> >>/* >> * Or set b into set a. a can be empty. does nothing if b empty. >> */ >>void >>set_orin(a, b) >>set *a, b; >>{ >> /* Fast set union operation */ >> /* size(a) is max(a, b); */ >> unsigned int m; >> register unsigned *p, >> *q = b.setword, >> *endq = &(b.setword[b.n]); >> >> CHK((*a)); CHK(b); >> if ( b.n == 0 ) return; >> m = (a->n > b.n) ? a->n : b.n; >> set_ext(a, m); >> p = a->setword; >> do { >> *p++ |= *q++; >> } while ( q < endq ); >>} >> >>void >>set_rm(e,a) /* removes elem arg1 from set arg2 */ >>unsigned e; >>set a; >>{ >> /* Does not effect size of set */ >> CHK(a); >> if ( (e == nil) || (NumWords(e) > a.n) ) return; >> a.setword[DIVWORD(e)] ^= (a.setword[DIVWORD(e)]&bitmask[MODWORD(e)]); >>} >> >>void >>set_clr(a) /* clears all elems of set arg1 */ >>set a; >>{ >> /* Does not effect size of set */ >> register unsigned *p = a.setword; >> register unsigned *endp = &(a.setword[a.n]); >> >> CHK(a); >> if ( a.n == 0 ) return; >> do { >> *p++ = 0; >> } while ( p < endp ); >>} >> >>set >>set_dup(a) >>set a; >>{ >> set b; >> register unsigned *p, >> *q = a.setword, >> *endq = &(a.setword[a.n]); >> >> CHK(a); >> b = empty; >> if ( a.n == 0 ) return( empty ); >> set_ext(&b, a.n); >> p = b.setword; >> do { >> *p++ = *q++; >> } while ( q < endq ); >> >> return(b); >>} >> >>/* >> * Return a nil terminated list of unsigned ints that represents all >> * "on" bits in the bit set. >> * >> * e.g. {011011} --> {1, 2, 4, 5, nil} >> * >> * set_PDQ and set_pdq are useful when an operation is required on each element >> * of a set. Normally, the sequence is: >> * >> * while ( set_deg(a) > 0 ) { >> * e = set_int(a); >> * set_rm(e, a); >> * ...process e... >> * } >> * Now, >> * >> * t = e = set_pdq(a); >> * while ( *e != nil ) { >> * ...process *e... >> * e++; >> * } >> * free( t ); >> * >> * We have saved many set calls and have not destroyed set a. >> */ >>void >>set_PDQ(a, q) >>set a; >>register unsigned *q; >>{ >> register unsigned *p = a.setword, >> *endp = &(a.setword[a.n]); >> register unsigned e=0; >> >> CHK(a); >> /* are there any space (possibility of elements)? */ >> if ( a.n == 0 ) return; >> do { >> register unsigned t = *p; >> register unsigned *b = &(bitmask[0]); >> do { >> if ( t & *b ) *q++ = e; >> ++e; >> } while (++b < &(bitmask[WORDSIZE])); >> } while (++p < endp); >> *q = nil; >>} >> >>/* >> * Same as set_PDQ except allocate memory. set_pdq is the natural function >> * to use. >> */ >>unsigned * >>set_pdq(a) >>set a; >>{ >> unsigned *q; >> int max_deg; >> >> CHK(a); >> max_deg = WORDSIZE*a.n; >> /* assume a.n!=0 & no elements is rare, but still ok */ >> if ( a.n == 0 ) return(NULL); >> q = (unsigned *) malloc((max_deg+1)*BytesPerWord); >> if ( q == NULL ) return( NULL ); >> set_PDQ(a, q); >> return( q ); >>} >> >>/* a function that produces a hash number for the set >> */ >>unsigned int set_hash(a,mod) >>set a; >>register unsigned int mod; >>{ >> /* Fast hash of set a (assumes all bits used) */ >> register unsigned *p = &(a.setword[0]); >> register unsigned *endp = &(a.setword[a.n]); >> register unsigned int i= 0; >> >> CHK(a); >> while (p> i = ((i + i + (i<0)) ^ (~ *p)); >> p++; >> } >> >> return(((i< 0) ? -i : i) % mod); >>} >EOF_set.c >cat << \EOF_set.h | sed 's/^>//' > set.h >>/* set.h >> >> The following is a general-purpose set library originally developed >> by Hank Dietz and enhanced by Terence Parr to allow dynamic sets. >> >> Sets are now structs containing the #words in the set and >> a pointer to the actual set words. >> >> 1987 by Hank Dietz >> >> Modified by: >> Terence Parr >> Purdue University >> October 1989 >> >> Added ANSI prototyping Dec. 1992 -- TJP >>*/ >> >>/* Define usable bits per unsigned int word */ >>#ifdef PC >>#define WORDSIZE 16 >>#define LogWordSize 4 >>#else >>#define WORDSIZE 32 >>#define LogWordSize 5 >>#endif >>#define BytesPerWord sizeof(unsigned) >> >>#define SETSIZE(a) ((a).n<>#define MODWORD(x) ((x) & (WORDSIZE-1)) /* x % WORDSIZE */ >>#define DIVWORD(x) ((x) >> LogWordSize) /* x / WORDSIZE */ >>#define nil ((unsigned) -1) /* An impossible set member all bits on (big!) */ >> >>typedef struct { >> unsigned int n; /* Number of words in set */ >> unsigned *setword; >> } set; >> >>#define set_init {0, NULL} >>#define set_null(a) ((a).setword==NULL) >> >>#define NumBytes(x) (((x)>>3)+1) /* Num bytes to hold x */ >>#define NumWords(x) (((x)>>LogWordSize)+1) /* Num words to hold x */ >> >> >>/* M a c r o s */ >> >>/* make arg1 a set big enough to hold max elem # of arg2 */ >>#define set_new(a,max) \ >>if (((a).setword=(unsigned *)calloc(NumWords(max),BytesPerWord))==NULL) \ >> fprintf(stderr, "set_new: Cannot allocate set with max of %d\n", max); \ >> (a).n = NumWords(max); >> >>#define set_free(a) \ >> {if ( (a).setword != NULL ) free((a).setword); \ >> (a) = empty;} >> >>#ifdef __STDC__ >>extern void set_size( unsigned ); >>extern unsigned int set_deg( set ); >>extern set set_or( set, set ); >>extern set set_and( set, set ); >>extern set set_dif( set, set ); >>extern set set_of( unsigned ); >>extern void set_ext( set *, unsigned int ); >>extern set set_not( set ); >>extern int set_equ( set, set ); >>extern int set_sub( set, set ); >>extern unsigned set_int( set ); >>extern int set_el( unsigned, set ); >>extern int set_nil( set ); >>extern char * set_str( set ); >>extern set set_val( register char * ); >>extern void set_orel( unsigned, set * ); >>extern void set_orin( set *, set ); >>extern void set_rm( unsigned, set ); >>extern void set_clr( set ); >>extern set set_dup( set ); >>extern void set_PDQ( set, register unsigned * ); >>extern unsigned *set_pdq( set ); >>extern unsigned int set_hash( set, register unsigned int ); >>#else >>extern void set_size(); >>extern unsigned int set_deg(); >>extern set set_or(); >>extern set set_and(); >>extern set set_dif(); >>extern set set_of(); >>extern void set_ext(); >>extern set set_not(); >>extern int set_equ(); >>extern int set_sub(); >>extern unsigned set_int(); >>extern int set_el(); >>extern int set_nil(); >>extern char * set_str(); >>extern set set_val(); >>extern void set_orel(); >>extern void set_orin(); >>extern void set_rm(); >>extern void set_clr(); >>extern set set_dup(); >>extern void set_PDQ(); >>extern unsigned *set_pdq(); >>extern unsigned int set_hash(); >>#endif >> >>extern set empty; >EOF_set.h EOF_set.bag cat << \EOF_sym.bag | sed 's/^>//' > sym.bag >cat << \EOF_sym.c | sed 's/^>//' > sym.c >>/* >> * Simple symbol table manager using coalesced chaining to resolve collisions >> * >> * Doubly-linked lists are used for fast removal of entries. >> * >> * 'sym.h' must have a definition for typedef "Sym". Sym must include at >> * minimum the following fields: >> * >> * ... >> * char *symbol; >> * struct ... *next, *prev, **head, *scope; >> * unsigned int hash; >> * ... >> * >> * 'template.h' can be used as a template to create a 'sym.h'. >> * >> * 'head' is &(table[hash(itself)]). >> * The hash table is not resizable at run-time. >> * The scope field is used to link all symbols of a current scope together. >> * Scope() sets the current scope (linked list) to add symbols to. >> * Any number of scopes can be handled. The user passes the address of >> * a pointer to a symbol table >> * entry (INITIALIZED TO NULL first time). >> * >> * Available Functions: >> * >> * zzs_init(s1,s2) -- Create hash table with size s1, string table size s2. >> * zzs_done() -- Free hash and string table created with zzs_init(). >> * zzs_add(key,rec)-- Add 'rec' with key 'key' to the symbol table. >> * zzs_newadd(key) -- create entry; add using 'key' to the symbol table. >> * zzs_get(key) -- Return pointer to last record entered under 'key' >> * Else return NULL >> * zzs_del(p) -- Unlink the entry associated with p. This does >> * NOT free 'p' and DOES NOT remove it from a scope >> * list. If it was a part of your intermediate code >> * tree or another structure. It will still be there. >> * It is only removed from further consideration >> * by the symbol table. >> * zzs_keydel(s) -- Unlink the entry associated with key s. >> * Calls zzs_del(p) to unlink. >> * zzs_scope(sc) -- Specifies that everything added to the symbol >> * table with zzs_add() is added to the list (scope) >> * 'sc'. 'sc' is of 'Sym **sc' type and must be >> * initialized to NULL before trying to add anything >> * to it (passing it to zzs_scope()). Scopes can be >> * switched at any time and merely links a set of >> * symbol table entries. If a NULL pointer is >> * passed, the current scope is returned. >> * zzs_rmscope(sc) -- Remove (zzs_del()) all elements of scope 'sc' >> * from the symbol table. The entries are NOT >> * free()'d. A pointer to the first >> * element in the "scope" is returned. The user >> * can then manipulate the list as he/she chooses >> * (such as freeing them all). NOTE that this >> * function sets your scope pointer to NULL, >> * but returns a pointer to the list for you to use. >> * zzs_stat() -- Print out the symbol table and some relevant stats. >> * zzs_new(key) -- Create a new record with calloc() of type Sym. >> * Add 'key' to the string table and make the new >> * records 'symbol' pointer point to it. >> * zzs_strdup(s) -- Add s to the string table and return a pointer >> * to it. Very fast allocation routine >> * and does not require strlen() nor calloc(). >> * >> * Example: >> * >> * #include >> * #include "sym.h" >> * >> * main() >> * { >> * Sym *scope1=NULL, *scope2=NULL, *a, *p; >> * >> * zzs_init(101, 100); >> * >> * a = zzs_new("Apple"); zzs_add(a->symbol, a); -- No scope >> * zzs_scope( &scope1 ); -- enter scope 1 >> * a = zzs_new("Plum"); zzs_add(a->symbol, a); >> * zzs_scope( &scope2 ); -- enter scope 2 >> * a = zzs_new("Truck"); zzs_add(a->symbol, a); >> * >> * p = zzs_get("Plum"); >> * if ( p == NULL ) fprintf(stderr, "Hmmm...Can't find 'Plum'\n"); >> * >> * p = zzs_rmscope(&scope1) >> * for (; p!=NULL; p=p->scope) {printf("Scope1: %s\n", p->symbol);} >> * p = zzs_rmscope(&scope2) >> * for (; p!=NULL; p=p->scope) {printf("Scope2: %s\n", p->symbol);} >> * } >> * >> * Terence Parr >> * Purdue University >> * February 1990 >> * >> * CHANGES >> * >> * Terence Parr >> * May 1991 >> * Renamed functions to be consistent with ANTLR >> * Made HASH macro >> * Added zzs_keydel() >> * Added zzs_newadd() >> * Fixed up zzs_stat() >> * >> * July 1991 >> * Made symbol table entry save its hash code for fast comparison >> * during searching etc... >> */ >> >>#include >>#ifdef MEMCHK >>#include "trax.h" >>#else >>char *calloc(); >>#endif >>#include "sym.h" >> >>#define StrSame 0 >> >>static Sym **CurScope = NULL; >>static unsigned size = 0; >>static Sym **table=NULL; >>static char *strings; >>static char *strp; >>static int strsize = 0; >> >>void >>zzs_init(sz, strs) >>int sz, strs; >>{ >> if ( sz <= 0 || strs <= 0 ) return; >> table = (Sym **) calloc(sz, sizeof(Sym *)); >> if ( table == NULL ) >> { >> fprintf(stderr, "Cannot allocate table of size %d\n", sz); >> exit(1); >> } >> strings = (char *) calloc(strs, sizeof(char)); >> if ( strings == NULL ) >> { >> fprintf(stderr, "Cannot allocate string table of size %d\n", strs); >> exit(1); >> } >> size = sz; >> strsize = strs; >> strp = strings; >>} >> >>void >>zzs_done() >>{ >> if ( table != NULL ) free( table ); >> if ( strings != NULL ) free( strings ); >>} >> >>void >>zzs_add(key, rec) >>char *key; >>register Sym *rec; >>{ >> register unsigned int h=0; >> register char *p=key; >> extern Sym *Globals; >> >> HASH(p, h); >> rec->hash = h; /* save hash code for fast comp later */ >> h %= size; >> >> if ( CurScope != NULL ) {rec->scope = *CurScope; *CurScope = rec;} >> rec->next = table[h]; /* Add to doubly-linked list */ >> rec->prev = NULL; >> if ( rec->next != NULL ) (rec->next)->prev = rec; >> table[h] = rec; >> rec->head = &(table[h]); >>} >> >>Sym * >>zzs_get(key) >>char *key; >>{ >> register unsigned int h=0; >> register char *p=key; >> register Sym *q; >> >> HASH(p, h); >> >> for (q = table[h%size]; q != NULL; q = q->next) >> { >> if ( q->hash == h ) /* do we even have a chance of matching? */ >> if ( strcmp(key, q->symbol) == StrSame ) return( q ); >> } >> return( NULL ); >>} >> >>/* >> * Unlink p from the symbol table. Hopefully, it's actually in the >> * symbol table. >> * >> * If p is not part of a bucket chain of the symbol table, bad things >> * will happen. >> * >> * Will do nothing if all list pointers are NULL >> */ >>void >>zzs_del(p) >>register Sym *p; >>{ >> if ( p == NULL ) {fprintf(stderr, "zzs_del(NULL)\n"); exit(1);} >> if ( p->prev == NULL ) /* Head of list */ >> { >> register Sym **t = p->head; >> >> if ( t == NULL ) return; /* not part of symbol table */ >> (*t) = p->next; >> if ( (*t) != NULL ) (*t)->prev = NULL; >> } >> else >> { >> (p->prev)->next = p->next; >> if ( p->next != NULL ) (p->next)->prev = p->prev; >> } >> p->next = p->prev = NULL; /* not part of symbol table anymore */ >> p->head = NULL; >>} >> >>void >>zzs_keydel(key) >>char *key; >>{ >> Sym *p = zzs_get(key); >> >> if ( p != NULL ) zzs_del( p ); >>} >> >>/* S c o p e S t u f f */ >> >>/* Set current scope to 'scope'; return current scope if 'scope' == NULL */ >>Sym ** >>zzs_scope(scope) >>Sym **scope; >>{ >> if ( scope == NULL ) return( CurScope ); >> CurScope = scope; >> return( scope ); >>} >> >>/* Remove a scope described by 'scope'. Return pointer to 1st element in scope */ >>Sym * >>zzs_rmscope(scope) >>register Sym **scope; >>{ >> register Sym *p; >> Sym *start; >> >> if ( scope == NULL ) return(NULL); >> start = p = *scope; >> for (; p != NULL; p=p->scope) { zzs_del( p ); } >> *scope = NULL; >> return( start ); >>} >> >>void >>zzs_stat() >>{ >> static unsigned short count[20]; >> unsigned int i,n=0,low=0, hi=0; >> register Sym **p; >> float avg=0.0; >> >> for (i=0; i<20; i++) count[i] = 0; >> for (p=table; p<&(table[size]); p++) >> { >> register Sym *q = *p; >> unsigned int len; >> >> if ( q != NULL && low==0 ) low = p-table; >> len = 0; >> if ( q != NULL ) printf("[%d]", p-table); >> while ( q != NULL ) >> { >> len++; >> n++; >> printf(" %s", q->symbol); >> q = q->next; >> if ( q == NULL ) printf("\n"); >> } >> if ( len>=20 ) printf("zzs_stat: count table too small\n"); >> else count[len]++; >> if ( *p != NULL ) hi = p-table; >> } >> >> printf("Storing %d recs used %d hash positions out of %d\n", >> n, size-count[0], size); >> printf("%f %% utilization\n", >> ((float)(size-count[0]))/((float)size)); >> for (i=0; i<20; i++) >> { >> if ( count[i] != 0 ) >> { >> avg += (((float)(i*count[i]))/((float)n)) * i; >> printf("Buckets of len %d == %d (%f %% of recs)\n", >> i, count[i], 100.0*((float)(i*count[i]))/((float)n)); >> } >> } >> printf("Avg bucket length %f\n", avg); >> printf("Range of hash function: %d..%d\n", low, hi); >>} >> >>/* >> * Given a string, this function allocates and returns a pointer to a >> * symbol table record whose "symbol" pointer is reset to a position >> * in the string table. >> */ >>Sym * >>zzs_new(text) >>char *text; >>{ >> Sym *p; >> char *zzs_strdup(); >> >> if ( (p = (Sym *) calloc(1,sizeof(Sym))) == 0 ) >> { >> fprintf(stderr,"Out of memory\n"); >> exit(1); >> } >> p->symbol = zzs_strdup(text); >> >> return p; >>} >> >>/* create a new symbol table entry and add it to the symbol table */ >>Sym * >>zzs_newadd(text) >>char *text; >>{ >> Sym *p = zzs_new(text); >> if ( p != NULL ) zzs_add(text, p); >> return p; >>} >> >>/* Add a string to the string table and return a pointer to it. >> * Bump the pointer into the string table to next avail position. >> */ >>char * >>zzs_strdup(s) >>register char *s; >>{ >> register char *start=strp; >> >> while ( *s != '\0' ) >> { >> if ( strp >= &(strings[strsize-2]) ) >> { >> fprintf(stderr, "sym: string table overflow (%d chars)\n", strsize); >> exit(-1); >> } >> *strp++ = *s++; >> } >> *strp++ = '\0'; >> >> return( start ); >>} >EOF_sym.c >cat << \EOF_template.h | sed 's/^>//' > template.h >>/* T e m p l a t e F o r S y m b o l T a b l e M a n a g e r */ >> >>/* define some hash function */ >>#ifndef HASH >>#define HASH(p, h) while ( *p != '\0' ) h = (h<<1) + *p++; >>#endif >> >>/* minimum symbol table record */ >>typedef struct _sym { >> char *symbol; >> struct _sym *next, *prev, **head, *scope; >> unsigned int hash; >> } Sym, *SymPtr; >> >>#ifdef __STDC__ >>void zzs_init(int, int); >>void zzs_done(void); >>void zzs_add(char *, Sym *); >>Sym *zzs_get(char *); >>void zzs_del(Sym *); >>void zzs_keydel(char *); >>Sym **zzs_scope(Sym **); >>Sym *zzs_rmscope(Sym **); >>void zzs_stat(void); >>Sym *zzs_new(char *); >>Sym *zzs_newadd(char *); >>char *zzs_strdup(char *); >>#else >>void zzs_init(); >>void zzs_done(); >>void zzs_add(); >>Sym *zzs_get(); >>void zzs_del(); >>void zzs_keydel(); >>Sym **zzs_scope(); >>Sym *zzs_rmscope(); >>void zzs_stat(); >>Sym *zzs_new(); >>Sym *zzs_newadd(); >>char *zzs_strdup(); >>#endif >EOF_template.h EOF_sym.bag cat << \EOF_rexpr.bag | sed 's/^>//' > rexpr.bag >cat << \EOF_makefile | sed 's/^>//' > makefile >>BAG=../../bin/bag >>SRC=test.c rexpr.c >>OBJ=test.o rexpr.o >>CFLAGS = >> >>test: $(OBJ) $(SRC) >> cc -o test $(OBJ) >> >>shar: >> shar makefile test.c rexpr.c > rexpr.shar >> >>archive: >> $(BAG) makefile test.c rexpr.c > rexpr.bag >EOF_makefile >cat << \EOF_test.c | sed 's/^>//' > test.c >>#include >> >>/* >> * test for rexpr(). >> * To make this test: >> * cc -o rexpr test.c rexpr.c >> * Then from command line type: >> * rexpr r string >> * where r is the regular expression that decribes a language >> * and string is the string to verify. >> */ >>main(argc,argv) >>int argc; >>char *argv[]; >>{ >> if ( argc!=3 ) fprintf(stderr,"rexpr: expr s\n"); >> else printf("%d\n", rexpr(argv[1], argv[2])); >>} >EOF_test.c >cat << \EOF_rexpr.c | sed 's/^>//' > rexpr.c >>/* >> * This file contains code for >> * >> * int rexpr(char *expr, char *s); >> * >> * which answers >> * >> * 1 if 's' is in the language described by the regular expression 'expr' >> * 0 if it is not >> * -1 if the regular expression is invalid >> * >> * Language membership is determined by constructing a non-deterministic >> * finite automata (NFA) from the regular expression. A depth- >> * first-search is performed on the NFA (graph) to check for a match of 's'. >> * Each non-epsilon arc consumes one character from 's'. Backtracking is >> * performed to check all possible paths through the NFA. >> * >> * Regular expressions follow the meta-language: >> * >> * ::= { '|' }* >> * >> * ::= { }* >> * >> * ::= {'~'} '[' ']' >> * | '(' ')' >> * | '{' '}' >> * | >> * >> * ::= { '*' | '+' } >> * >> * ::= { }* >> * | { } '-' { } >> * >> * ::= Token[Atom] >> * >> * Notes: >> * ~ means complement the set in [..]. i.e. all characters not listed >> * * means match 0 or more times (can be on expression or atom) >> * + means match 1 or more times (can be on expression or atom) >> * {} optional >> * () grouping >> * [] set of atoms >> * x-y all characters from x to y (found only in [..]) >> * \xx the character with value xx >> * >> * Examples: >> * [a-z]+ >> * match 1 or more lower-case letters (e.g. variable) >> * >> * 0x[0-9A-Fa-f]+ >> * match a hex number with 0x on front (e.g. 0xA1FF) >> * >> * [0-9]+.[0-9]+{e[0-9]+} >> * match a floating point number (e.g. 3.14e21) >> * >> * Code example: >> * if ( rexpr("[a-zA-Z][a-zA-Z0-9]+", str) ) then str is keyword >> * >> * Terence Parr >> * Purdue University >> * April 1991 >> */ >> >>#include >>#include >> >>#define Atom 256 /* token Atom (an impossible char value) */ >>#define Epsilon 257 /* epsilon arc (an impossible char value) */ >> >>typedef struct _a { >> int label; >> struct _a *next; >> struct _n *target; >> struct _a *track; /* track mem allocation */ >> } Arc, *ArcPtr; >> >>typedef struct _n { >> ArcPtr arcs, arctail; >> struct _n *track; >> } Node, *NodePtr; >> >>typedef struct { >> NodePtr left, >> right; >> } Graph, *GraphPtr; >> >>static char *_c; >>static int token, tokchar; >>static NodePtr accept; >>static NodePtr freelist = NULL; >> >>Graph BuildNFA_Aoptional(), >> BuildNFA_Aplus(), >> BuildNFA_Astar(), >> BuildNFA_set(), >> BuildNFA_AorB(), >> BuildNFA_AB(), >> BuildNFA_atom(); >>char *calloc(); >> >>/* >> * return 1 if s in language described by expr >> * 0 if s is not >> * -1 if expr is an invalid regular expression >> */ >>rexpr(expr, s) >>char *expr, *s; >>{ >> NodePtr p,q; >> Graph nfa; >> int result; >> >> fprintf(stderr, "rexpr(%s,%s);\n", expr,s); >> _c = expr; >> next(); >> if ( !regExpr(&nfa) ) return -1; >> accept = nfa.right; >> result = match(nfa.left, s); >> /* free all your memory */ >> p = q = freelist; >> while ( p!=NULL ) { q = p->track; free(p); p = q; } >> return result; >>} >> >>/* >> * do a depth-first-search on the NFA looking for a path from start to >> * accept state labelled with the characters of 's'. >> */ >>match(automaton, s) >>NodePtr automaton; >>char *s; >>{ >> ArcPtr p; >> >> if ( automaton == accept && *s == '\0' ) return 1; /* match */ >> >> for (p=automaton->arcs; p!=NULL; p=p->next) /* try all arcs */ >> { >> if ( p->label == Epsilon ) >> { >> if ( match(p->target, s) ) return 1; >> } >> else if ( p->label == *s ) >> if ( match(p->target, s+1) ) return 1; >> } >> return 0; >>} >> >>/* >> * ::= { '|' }* >> */ >>static >>regExpr(g) >>GraphPtr g; >>{ >> Graph g1, g2; >> >> if ( !andExpr(&g1) ) >> { >> return 0; >> } >> >> while ( token == '|' ) >> { >> next(); >> if ( !andExpr(&g2) ) >> { >> return 1; >> } >> g1 = BuildNFA_AorB(g1, g2); >> } >> >> *g = g1; >> return 1; >>} >> >>/* >> * ::= { }* >> */ >>static >>andExpr(g) >>GraphPtr g; >>{ >> Graph g1, g2; >> >> if ( !expr(&g1) ) >> { >> return 0; >> } >> >> while ( expr(&g2) ) >> { >> g1 = BuildNFA_AB(g1, g2); >> } >> >> *g = g1; >> return 1; >>} >> >>/* >> * ::= {'~'} '[' ']' >> * | '(' ')' >> * | '{' '}' >> * | >> */ >>static >>expr(g) >>GraphPtr g; >>{ >> int complement = 0; >> char s[257]; /* alloc space for string of char in [] */ >> >> if ( token == '~' || token == '[' ) >> { >> if ( token == '~' ) {complement = 1; next();} >> if ( token != '[' ) return 0; >> next(); >> atomList( s, complement ); >> *g = BuildNFA_set( s ); >> if ( token != ']' ) return 0; >> next(); >> repeatSymbol( g ); >> return 1; >> } >> if ( token == '(' ) >> { >> next(); >> regExpr( g ); >> if ( token != ')' ) return 0; >> next(); >> repeatSymbol( g ); >> return 1; >> } >> if ( token == '{' ) >> { >> next(); >> regExpr( g ); >> if ( token != '}' ) return 0; >> next(); >> /* S p e c i a l C a s e O p t i o n a l { } */ >> if ( token != '*' && token != '+' ) >> { >> *g = BuildNFA_Aoptional( *g ); >> } >> repeatSymbol( g ); >> return 1; >> } >> if ( token == Atom ) >> { >> *g = BuildNFA_atom( tokchar ); >> next(); >> repeatSymbol( g ); >> return 1; >> } >> >> return 0; >>} >> >>/* >> * ::= { '*' | '+' } >> */ >>static >>repeatSymbol(g) >>GraphPtr g; >>{ >> switch ( token ) >> { >> case '*' : *g = BuildNFA_Astar( *g ); next(); break; >> case '+' : *g = BuildNFA_Aplus( *g ); next(); break; >> } >>} >> >>/* >> * ::= { }* >> * { } '-' { } >> * >> * a-b is same as ab >> * q-a is same as q >> */ >>static >>atomList(p, complement) >>char *p; >>int complement; >>{ >> static unsigned char set[256]; /* no duplicates */ >> int first, last, i; >> char *s = p; >> >> if ( token != Atom ) return 0; >> >> while ( token == Atom ) >> { >> if ( !set[tokchar] ) *s++ = tokchar; >> set[tokchar] = 1; /* Add atom to set */ >> next(); >> if ( token == '-' ) /* have we found '-' */ >> { >> first = *(s-1); /* Get last char */ >> next(); >> if ( token != Atom ) return 0; >> else >> { >> last = tokchar; >> } >> for (i = first+1; i <= last; i++) >> { >> if ( !set[tokchar] ) *s++ = i; >> set[i] = 1; /* Add atom to set */ >> } >> next(); >> } >> } >> *s = '\0'; >> if ( complement ) >> { >> for (i=0; i<256; i++) set[i] = !set[i]; >> for (i=1,s=p; i<256; i++) if ( set[i] ) *s++ = i; >> *s = '\0'; >> } >> return 1; >>} >> >>/* a somewhat stupid lexical analyzer */ >>static >>next() >>{ >> while ( *_c==' ' || *_c=='\t' || *_c=='\n' ) _c++; >> if ( *_c=='\\' ) >> { >> _c++; >> if ( isdigit(*_c) ) >> { >> int n=0; >> while ( isdigit(*_c) ) >> { >> n = n*10 + (*_c++ - '0'); >> } >> if ( n>255 ) n=255; >> tokchar = n; >> } >> else >> { >> switch (*_c) >> { >> case 'n' : tokchar = '\n'; break; >> case 't' : tokchar = '\t'; break; >> case 'r' : tokchar = '\r'; break; >> default : tokchar = *_c; >> } >> _c++; >> } >> token = Atom; >> } >> else if ( isgraph(*_c) && *_c!='[' && *_c!='(' && *_c!='{' && >> *_c!='-' && *_c!='}' && *_c!=')' && *_c!=']' && >> *_c!='+' && *_c!='*' && *_c!='~' && *_c!='|' ) >> { >> token = Atom; >> tokchar = *_c++; >> } >> else >> { >> token = tokchar = *_c++; >> } >>} >> >>/* N F A B u i l d i n g R o u t i n e s */ >> >>static >>ArcPtr >>newGraphArc() >>{ >> ArcPtr p; >> p = (ArcPtr) calloc(1, sizeof(Arc)); >> if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);} >> if ( freelist != NULL ) p->track = (ArcPtr) freelist; >> freelist = (NodePtr) p; >> return p; >>} >> >>static >>NodePtr >>newNode() >>{ >> NodePtr p; >> p = (NodePtr) calloc(1, sizeof(Node)); >> if ( p==NULL ) {fprintf(stderr,"rexpr: out of memory\n"); exit(-1);} >> if ( freelist != NULL ) p->track = freelist; >> freelist = p; >> return p; >>} >> >>static >>ArcBetweenGraphNodes(i, j, label) >>NodePtr i, j; >>int label; >>{ >> ArcPtr a; >> >> a = newGraphArc(); >> if ( i->arcs == NULL ) i->arctail = i->arcs = a; >> else {(i->arctail)->next = a; i->arctail = a;} >> a->label = label; >> a->target = j; >>} >> >>static Graph >>BuildNFA_atom(label) >>int label; >>{ >> Graph g; >> >> g.left = newNode(); >> g.right = newNode(); >> ArcBetweenGraphNodes(g.left, g.right, label); >> return( g ); >>} >> >>static Graph >>BuildNFA_AB(A, B) >>Graph A, B; >>{ >> Graph g; >> >> ArcBetweenGraphNodes(A.right, B.left, Epsilon); >> g.left = A.left; >> g.right = B.right; >> return( g ); >>} >> >>static Graph >>BuildNFA_AorB(A, B) >>Graph A, B; >>{ >> Graph g; >> >> g.left = newNode(); >> ArcBetweenGraphNodes(g.left, A.left, Epsilon); >> ArcBetweenGraphNodes(g.left, B.left, Epsilon); >> g.right = newNode(); >> ArcBetweenGraphNodes(A.right, g.right, Epsilon); >> ArcBetweenGraphNodes(B.right, g.right, Epsilon); >> return( g ); >>} >> >>static Graph >>BuildNFA_set( s ) >>char *s; >>{ >> Graph g; >> >> if ( s == NULL ) return g; >> >> g.left = newNode(); >> g.right = newNode(); >> while ( *s != '\0' ) >> { >> ArcBetweenGraphNodes(g.left, g.right, *s++); >> } >> return g; >>} >> >>static Graph >>BuildNFA_Astar( A ) >>Graph A; >>{ >> Graph g; >> >> g.left = newNode(); >> g.right = newNode(); >> >> ArcBetweenGraphNodes(g.left, A.left, Epsilon); >> ArcBetweenGraphNodes(g.left, g.right, Epsilon); >> ArcBetweenGraphNodes(A.right, g.right, Epsilon); >> ArcBetweenGraphNodes(A.right, A.left, Epsilon); >> >> return( g ); >>} >> >>static Graph >>BuildNFA_Aplus( A ) >>Graph A; >>{ >> ArcBetweenGraphNodes(A.right, A.left, Epsilon); >> >> return( A ); >>} >> >>static Graph >>BuildNFA_Aoptional( A ) >>Graph A; >>{ >> Graph g; >> >> g.left = newNode(); >> g.right = newNode(); >> >> ArcBetweenGraphNodes(g.left, A.left, Epsilon); >> ArcBetweenGraphNodes(g.left, g.right, Epsilon); >> ArcBetweenGraphNodes(A.right, g.right, Epsilon); >> >> return( g ); >>} >EOF_rexpr.c EOF_rexpr.bag cat << \EOF_pascal.bag | sed 's/^>//' > pascal.bag >cat << \EOF_pascal.g | sed 's/^>//' > pascal.g >>/* >> * File: pascal.g >> * >> * P a s c a l G r a m m a r >> * >> * Some of the grammar could be more readable if it were spread out. However, >> * to show the concise nature of ANTLR, I am squishing it (show off). >> * Theoretically, it would be possible to put the entire grammar into one >> * rule with lots-o-parenthesis and duplicate subrules. >> * >> * This grammar is considered Public Domain and is distributed as is. >> * >> * Terence Parr (c) 1990 >> * Purdue University >> * January 1990 >> * >> * Modified by Will Cohen 12/17/90 >> * >> * scoping is messed up 12/17/90 >> */ >>#header << >> >>#include "sym.h" >>#include "pascal.h" >>extern Sym *CurSym; >> >>>> >> >><< >>Sym *CurSym; >>static int level = 0; >>>> >> >>/* made special tokens for key words to simplify lexical analyser */ >>#token And >>#token Array >>#token Begin >>#token Case >>#token Const >>#token Div >>#token Do >>#token Downto >>#token Else >>#token End >>#token File >>#token For >>#token Forward >>#token Function >>#token Goto >>#token If >>#token In >>#token Label >>#token Mod >>#token Nil >>#token Not >>#token Of >>#token Or >>#token Packed >>#token Procedure >>#token Program >>#token Record >>#token Repeat >>#token Set >>#token Then >>#token To >>#token Type >>#token Until >>#token Var >>#token While >>#token With >> >>/* things to specify identifiers */ >>#token TypeID >>#token UTypeID >>#token VarID >>#token ProcID >>#token ProgID >>#token FuncID >>#token ConstID >> >>/* white space */ >>#token "[\t\ ]" << zzskip(); >> >>#token "[\n\r]" << zzline++; zzskip(); >> >> >>/* signal start of a comment */ >>#token "\{" << zzmode(COMMENT); zzskip();>> >>#token "\(\*" << zzmode(COMMENT); zzskip();>> >> >>/* G r o s s S y n t a x C o n t r o l */ >> >> >>program : <> >> Program nonReserved >> <> printf("program %s level %d:\n\n", $2->symbol, level); >> zzs_scope(&globals); >> >> >> "\(" idList "\)" <> >> ";" >> block "." >> << >> p = zzs_rmscope(&globals); >> printf("global (level %d) symbols:", level); >> for (; p != NULL; p=p->scope) >> printf(" %s", p->symbol); >> printf("\n\n"); >> >> >> "@" >> ; >> >>block : <> >> decl >> ( routine <> )* >> Begin >> slist >> End >> ; >> >>routine : <> >> ( Procedure <> | Function <>) >> nonReserved << $2 = make_special_entry(tok,$2);>> >> <> >> {"\(" parmGroup (";" parmGroup)* "\)"} >> { ":" (TypeID | UTypeID) } >> ";" >> block ";" >> << >> p = zzs_rmscope(&locals); >> printf("subprogram %s level %d:\n", $2->symbol, --level); >> printf("local (level %d) symbols:", level+1); >> for (; p != NULL; p=p->scope) printf(" %s", p->symbol); >> printf("\n\n"); >> >> >> ; >> >>parmGroup : {Var} idList ":" (TypeID | UTypeID) <> ; >> >>slist : label ( ";" label )* ; >> >>label : {UINT ":"} statement ; >> >>statement : (var | FuncID ) ":=" expr >> | ProcID { "\(" expr ("," expr)* "\)" } >> | Begin slist End >> >> | If expr Then statement { Else statement} >> | Case expr Of >> (constant ("," constant)* ":" statement ";")* >> End >> | While expr Do statement >> | Repeat slist Until expr >> | For VarID ":=" expr ( To| Downto ) expr Do statement >> | With var ( "," var )* Do statement >> | Goto UINT >> | /* empty statement */ >> ; >> >> >>/* D e c l a r a t i o n S e c t i o n */ >> >> >>decl : ( LABEL UINT ( "," UINT )* ";")* >> { Const nonReserved "=" constant >> <> >> ";" >> ( nonReserved "=" constant >> <> >> ";" >> )* >> } >> { Type nonReserved "=" type >> <> >> ";" >> ( nonReserved "=" type >> <> >> ";" >> )* >> } >> { Var idList ":" type ";" <> >> ( idList ":" type ";" <> >> )* >> } >> ; >> >>/* tokens than can be redefined in a new scope */ >>nonReserved : UTypeID << $0 = $1; >> >> | VarID << $0 = $1; >> >> | ProcID << $0 = $1; >> >> | ProgID << $0 = $1; >> >> | FuncID << $0 = $1; >> >> | ConstID << $0 = $1; >> >> | WORD << $0 = $1; >> >> ; >> >>simpleType : (TypeID | UTypeID) >> | "\(" wordList <> "\)" >> | constant ".." constant >> ; >> >>type : simpleType >> /* since pointers to types can be defined before actual type*/ >> | "^" (TypeID | nonReserved) >> | {Packed} structType >> ; >> >>structType : Array "\[" simpleType ("," simpleType)* "\]" Of type >> | File Of type >> | Set Of simpleType >> | Record fixedPart {";"} (fixedPart {";"} )* {variantPart} End >> ; >> >>fixedPart : idList ":" type >> ; >> >>variantPart : Case {WORD ":"} >> (TypeID | UTypeID) Of variant {";"} (variant {";"})* >> ; >> >>variant : constant ( "," constant )* ":" >> "\(" fixedPart {";"} (fixedPart {";"})* >> {variantPart} "\)" >> ; >> >>/* Use 'link' field of symbol rec to link elements together into idlist */ >>idList : <> /* Return list of id's */ >> nonReserved << $1->link = list; list = $1; >> >> ( "," nonReserved << $2->link = list; list = $2; >> >> )* >> <<$0 = list;>> >> ; >> >>wordList: <> /* Return list of words */ >> WORD <<$1->link = list; list=$1;>> >> ( "," WORD <<$2->link = list; list=$2;>> >> )* >> <<$0 = list;>> >> ; >> >>constant : {"\+"|"\-"} (ConstID | UINT { "." UINT {"E" {"\+"|"\-"} UINT}}) >> | Nil >> | LITERAL >> ; >> >>uconstant : ConstID >> /* floating point number */ >> | UINT { "." UINT {"E" {"\+"|"\-"} UINT}} >> | Nil >> | LITERAL >> ; >> >> >>/* E x p r e s s i o n S e c t i o n */ >> >> >>expr : simpleExpr (("="|"\<"|"\>"|"\<\>"|"\<="|"\>="| In ) simpleExpr)* ; >> >>simpleExpr : {"\+"|"\-"} term (("\+"|"\-"| Or ) term)* ; >> >>term : factor (("\*"|"/"| Div | Mod | And ) factor)* ; >> >>factor : uconstant >> | var >> | FuncID { "\(" expr ("," expr)* "\)" } >> | "\(" expr "\)" >> | Not factor >> | "\[" {expr {".." expr}} ("," expr {".." expr})* "\]" >> ; >> >>var : VarID ref >> | WORD ref <> >> ; >> >>ref : "\[" expr ("," expr)* "\]" ref >> | "^" ref >> | "." (WORD <>|VarID) ref >> | >> ; >> >>#token LITERAL "' ~[\0-\31']* '" >>#token UINT "[0-9]+" >>#token WORD "[a-zA-Z] [a-zA-Z0-9]*" >> << >> { >> register Sym *p; >> >> p = zzs_get(zzlextext); >> if ( p == NULL ){ >> p = zzs_newadd(zzlextext); >> p->token = WORD; >> }else{ >> zztoken = p->token; >> } >> CurSym = p; >> } >> >> >> >>/* special automaton to skip over comments */ >>#lexclass COMMENT >>/* ends of comments */ >>#token "\*\)" << zzmode(START); zzskip(); >> >>#token "\}" << zzmode(START); zzskip(); >> >> >>#token "[\n\r]" << zzline++; zzskip(); >> >> >>#token "\*" << zzskip(); >> >>#token "~[\*\}\n\r]+" << zzskip(); >> >> >EOF_pascal.g >cat << \EOF_ttree.c | sed 's/^>//' > ttree.c >>/* Code to manage type trees for each type >> * These trees then can be used to determine whether varibles have the >> * same type. >> * >> * Will Cohen >> * 12/18/90 >> */ >> >>#include >>#include "ttree.h" >> >>#define TRUE 1 >>#define FALSE 0 >> >> >>/* returns flag to state two trees compatible types*/ >>int compatible(t1,t2) >>tnode *t1, *t2; >>{ >> int result = TRUE; >> >> return result; >>} >> >>/* returns flag to if a value of t2 can be assigned to type t1 */ >>int acompatible(t1,t2) >>tnode *t1, *t2; >>{ >> int result = TRUE; >> >> return result; >>} >> >> >>/* build tnode */ >>tnode *new_tnode(t,down,right) >>int t; >>tnode *down,*right; >>{ >> register tnode *p; >> >> if ( (p = (tnode *) calloc(1,sizeof(tnode))) == 0 ) >> { >> fprintf(stderr,"Out of memory\n"); >> exit(1); >> } >> p->n_type = t; >> p->down = down; >> p->right = right; >> return p; >>} >> >>/* things to build the simple type trees */ >EOF_ttree.c >cat << \EOF_adebug.c | sed 's/^>//' > adebug.c >>/* a modified aTrax that just keeps the rules applied in a circular buffer >> * it then prints them when an error occurs to get the context that >> * rules was applied in >> * >> * Will Cohen >> * 2/7/90 >> */ >> >>#include >>#include >>#include "sym.h" >>#include "pascal.h" >>#include "dlgdef.h" >>#include "antlr.h" >> >>#define N_RULES 50 /* last N_RULES kept in buffer for analysis */ >>#define LINE_LEN 128 /* max length of line allowed */ >>#define FORMAT "%s(%.128s)\n" /* number here and in LINE_LEN should agree */ >> >>/* circular buffer for rules */ >>char *rules_applied[N_RULES]; >>char *rules_text[N_RULES][LINE_LEN]; >> >>int line_n = 0; >>int valid_lines = 0; >> >>#ifdef OLD >>/* put the trace in the circular buffer */ >>zzTRACE(rule) >>char *rule; >>{ >> /* only need to store the pointer to the rule */ >> rules_applied[line_n] = rule; >> strncpy(rules_text[line_n],LATEXT(1), LINE_LEN); >> line_n = (++line_n) % N_RULES; >> if (valid_lines < N_RULES) ++valid_lines; >>} >> >> >>/* prints out the rules in buffer */ >>print_trax() >>{ >> register i,k; >> >> k = (line_n-valid_lines)%N_RULES; >> /* take care of negative modulii */ >> if (k<0) k += N_RULES; >> for(i = 0; i> fprintf(stderr, FORMAT, rules_applied[k], rules_text[k]); >> k++; >> if (k>= N_RULES) k = 0; >> } >>} >>#endif >EOF_adebug.c >cat << \EOF_pmain.c | sed 's/^>//' > pmain.c >>/* Pascal grammar >> * >> * >> * >> */ >> >>#include >>#ifdef MEMCHK >>#include "trax.h" >>#else >>char *calloc(), *malloc(); >>#endif >> >>#include "stdpccts.h" >> >>#define SymStrTable 10000 >>#define HashSize 10001 >> >>struct _pre { >> char *symbol; >> int token; >>}; >> >>struct _pre predef[] = { >> /* keywords */ >> { "and", And }, >> { "array", Array }, >> { "begin", Begin }, >> { "case", Case }, >> { "const", Const }, >> { "div", Div }, >> { "do", Do }, >> { "downto", Downto }, >> { "else", Else }, >> { "end", End }, >> { "file", File }, >> { "for", For }, >> { "forward", Forward }, >> { "function", Function }, >> { "goto", Goto }, >> { "if", If }, >> { "in", In }, >> { "label", Label }, >> { "mod", Mod }, >> { "nil", Nil }, >> { "not", Not }, >> { "of", Of }, >> { "or", Or }, >> { "packed", Packed }, >> { "procedure", Procedure }, >> { "program", Program }, >> { "record", Record }, >> { "repeat", Repeat }, >> { "set", Set }, >> { "then", Then }, >> { "to", To }, >> { "type", Type }, >> { "until", Until }, >> { "var", Var }, >> { "while", While }, >> { "with", With }, >> >> /* Predefined Constants */ >> { "maxint", ConstID }, >> { "true", ConstID }, >> { "false", ConstID }, >> >> /* Predefined Types */ >> {"real", TypeID}, >> {"boolean", TypeID}, >> {"char", TypeID}, >> {"integer", TypeID}, >> {"text", TypeID}, >> >> /* Predefined Functions */ >> { "odd", FuncID }, >> { "eoln", FuncID }, >> { "eof", FuncID }, >> { "abs", FuncID }, >> { "sqr", FuncID }, >> { "sin", FuncID }, >> { "cos", FuncID }, >> { "arctan", FuncID }, >> { "ln", FuncID }, >> { "exp", FuncID }, >> { "sqrt", FuncID }, >> { "ord", FuncID }, >> { "chr", FuncID }, >> { "pred", FuncID }, >> { "succ", FuncID }, >> { "round", FuncID }, >> { "trunc", FuncID }, >> >> /* Predefined Procedures */ >> { "put", ProcID }, >> { "get", ProcID }, >> { "reset", ProcID }, >> { "rewrite", ProcID }, >> { "new", ProcID }, >> { "dispose", ProcID }, >> { "read", ProcID }, >> { "readln", ProcID }, >> { "write", ProcID }, >> { "writeln", ProcID }, >> { "page", ProcID }, >> >> {NULL, 0} >>}; >> >>main(argc, argv) >>int argc; >>char *argv[]; >>{ >> Sym *p; >> FILE *f; >> >>/* if ( argc==1 ) {fprintf(stderr, "Usage: pas filename\n"); return;} */ >> if ( argc==1 ){ >> f = stdin; >> }else{ >> f = fopen(argv[1], "r"); >> } >> if ( f==NULL ) {fprintf(stderr, "Can't Open '%s'\n", argv[1]); return;} >> >> zzs_init(HashSize, SymStrTable); >> LoadSymTable(); >> >> ANTLR(program(), f); /* Parse program from stdin */ >> /*statsym();*/ >> /*print_trax();*/ /* list out the last rules applied */ >> exit(0); >>} >> >>LoadSymTable() >>{ >> struct _pre *p = &(predef[0]); >> Sym *sym; >> >> while ( p->symbol != NULL ) >> { >> sym = zzs_newadd(p->symbol); >> sym->token = p->token; >> p++; >> } >>} >> >>/* converts a list of entries in symbol table into something else */ >>addlist(list, token, level) >>Sym *list; >>int token, level; >>{ >> register Sym *p, *q; >> >> for (p=list; p!=NULL; p=q) >> { >> q = make_special_entry(token,p); >> q->level = level; >> q = p->link; >> /* unlink things */ >> p->link = NULL; >> } >>} >> >>Sym *make_special_entry(token, p) >>int token; >>Sym *p; >>{ >> if (p){ >> switch(p->token){ >> case UTypeID: >> case VarID: >> case ProcID: >> case ProgID: >> case FuncID: >> case ConstID: >> /* need to make new entry for this scope */ >> p = zzs_newadd(p->symbol); >> case WORD: >> /* in this case can just use the symbol entry already made */ >> p->token = token; >> break; >> default: >> fprintf(stderr,"Tried to redefine reserved word %s\n", >> p->symbol); >> break; >> } >> } >> return p; >>} >EOF_pmain.c >cat << \EOF_pascal.h | sed 's/^>//' > pascal.h >>/* pascal.h header file for the antlr pascal grammar >> * >> * 6/9/91 >> */ >> >>#define TRUE 1 >>#define FALSE 0 >> >>Sym *make_special_entry(); >> >>typedef Sym *Attrib; >>#define zzcr_attr(attr,tok,text) {*(attr) = CurSym;} >> >EOF_pascal.h >cat << \EOF_ttree.h | sed 's/^>//' > ttree.h >>/* Code to manage type trees for each type >> * These trees then can be used to determine whether varibles have the >> * same type. >> * >> * Will Cohen >> * 12/18/90 >> */ >> >>#define tnode struct _tnode_ >>tnode { >> tnode *down,*right; /* everything in child-sibling tree */ >> int n_type; /* indicates what kind of node this is */ >>}; >> >>/* types of tnodes */ >> >> >>/* functions */ >>extern int compatible(/*t1,t2*/); /* returns 0 for incompatible, 1 for */ >> /* compatible */ >>extern int acompatible(/*t1,t2*/); /* returns 1 if can assigment okay */ >> /* t1<-t2 */ >>extern tnode *new_tnode(); /* makes and fills in a tnode */ >EOF_ttree.h >cat << \EOF_sym.h | sed 's/^>//' > sym.h >>/* T e m p l a t e F o r S y m b o l T a b l e M a n a g e r */ >> >>/* define some hash function */ >>#ifndef HASH >>#define HASH(p, h) while ( *p != '\0' ) h = (h<<1) + *p++; >>#endif >> >>/* Pascal symbol table record */ >>typedef struct _sym { >> char *symbol; >> struct _sym *next, *prev, **head, *scope; >> unsigned int hash; >> struct _sym *link; >> double value; /* storage for constants */ >> int token; >> int level; >>} Sym, *SymPtr; >> >>#ifdef __STDC__ >>void zzs_init(int, int); >>void zzs_done(void); >>void zzs_add(char *, Sym *); >>Sym *zzs_get(char *); >>void zzs_del(Sym *); >>void zzs_keydel(char *); >>Sym **zzs_scope(Sym **); >>Sym *zzs_rmscope(Sym **); >>void zzs_stat(void); >>Sym *zzs_new(char *); >>Sym *zzs_newadd(char *); >>char *zzs_strdup(char *); >>#else >>void zzs_init(); >>void zzs_done(); >>void zzs_add(); >>Sym *zzs_get(); >>void zzs_del(); >>void zzs_keydel(); >>Sym **zzs_scope(); >>Sym *zzs_rmscope(); >>void zzs_stat(); >>Sym *zzs_new(); >>Sym *zzs_newadd(); >>char *zzs_strdup(); >>#endif >EOF_sym.h >cat << \EOF_makefile.user | sed 's/^>//' > makefile.user >>GRM =pascal.g >>LEX_FILE =pscan.dlg >>GSRC=pascal.c err.c pscan.c ttree.c adebug.c >>GOBJ=pascal.o err.o pscan.o ttree.o adebug.o >> >>PCCTS_GEN= pascal.c err.c $(LEX_FILE) pscan.c mode.h tokens.h >> >>SRC =$(GSRC) pmain.c sym.c >>OBJ =$(GOBJ) pmain.o sym.o >>INCL = ../../h >>SYM = ../../support/sym >>ANTLR = ../../bin/antlr >>DLG = ../../bin/dlg >> >>CFLAGS=-I. -I$(INCL) >>AFLAGS= -fl $(LEX_FILE) -gh >> >>pascal : $(OBJ) >> $(CC) $(CFLAGS) -o pascal $(OBJ) >> >>pascal.c $(LEX_FILE) : $(GRM) >> $(ANTLR) $(AFLAGS) $(GRM) >> >>mode.h pscan.c : $(LEX_FILE) >> $(DLG) -C2 $(LEX_FILE) pscan.c >> >>pmain.o : pmain.c pascal.h >> >>pascal.o : pascal.c mode.h tokens.h >> >>sym.o : $(SYM)/sym.c >> cc -c -o sym.o $(CFLAGS) $(SYM)/sym.c >> >>err.o : err.c >> >>clean: >> rm $(PCCTS_GEN) *.o >EOF_makefile.user >cat << \EOF_test.p | sed 's/^>//' > test.p >>program convert(output); >> >>type color = (white, red, blue, yellow, purple, green); >> xx = 'a'..'z'; >> duh = array[white..green] of real; >> person = record >> ss : integer; >> sex : (male,female); >> birth : color; >> case ms : color of >> white,red : (mdate:integer); >> blue : (ddate:integer; firstd:integer) >> end; >> >>var a : color; >> b : array [1 ..3,2 ..5,2 ..9] of person; >> c : file of real; >> >>begin >> with b[white,3,3] do begin >> a := red; >> b[white,3,3]^.d[3] := 3.14159 >> end >>end. >EOF_test.p EOF_pascal.bag cat << \EOF_C.bag | sed 's/^>//' > C.bag >cat << \EOF_makefile.user | sed 's/^>//' > makefile.user >>SYM=../../support/sym >>H=../../h >>SRC=scan.c decl.c func.c expr.c err.c main.c $(SYM)/sym.c engl.c >>OBJ=scan.o decl.o func.o expr.o err.o main.o sym.o engl.o >>CFLAGS=-I. -I$(H) >>AFLAGS=-k $(K) -gt -gh >># where are dlg and antlr binaries >>DLG=../../bin/dlg >>ANTLR=../../bin/antlr >>K=2 # tokens of lookahead >> >>proto: $(OBJ) $(SRC) >> cc -o proto $(OBJ) >> >>decl.c func.c expr.c err.c stdpccts.h parser.dlg : decl.g func.g expr.g >> $(ANTLR) $(AFLAGS) decl.g func.g expr.g >> >>main.o engl.o : stdpccts.h >> >>scan.c : parser.dlg >> $(DLG) -C2 parser.dlg scan.c >> >>sym.o : $(SYM)/sym.c >> cc -c -o sym.o $(CFLAGS) $(SYM)/sym.c >EOF_makefile.user >cat << \EOF_README | sed 's/^>//' > README >> >>Quick note: >> >>You must run any code through the C preprocessor (e.g. "cc -E $(CFLAGS) >>file.c") before sending it to the prototype generator. >EOF_README >cat << \EOF_sym.h | sed 's/^>//' > sym.h >> >>#ifndef HASH >>#define HASH(p, h) while ( *p != '\0' ) h = (h<<1) + *p++; >>#endif >> >>typedef struct _sym { >> char *symbol; >> struct _sym *next, *prev, **head, *scope; >> unsigned int hash; >> int token; >> int level; >> char defined; >> struct _ast *type, *init; >> } Sym, *SymPtr; >> >>#ifdef __STDC__ >>void zzs_init(int, int); >>void zzs_done(void); >>void zzs_add(char *, Sym *); >>Sym *zzs_get(char *); >>void zzs_del(Sym *); >>void zzs_keydel(char *); >>Sym **zzs_scope(Sym **); >>Sym *zzs_rmscope(Sym **); >>void zzs_stat(void); >>Sym *zzs_new(char *); >>Sym *zzs_newadd(char *); >>char *zzs_strdup(char *); >>#else >>void zzs_init(); >>void zzs_done(); >>void zzs_add(); >>Sym *zzs_get(); >>void zzs_del(); >>void zzs_keydel(); >>Sym **zzs_scope(); >>Sym *zzs_rmscope(); >>void zzs_stat(); >>Sym *zzs_new(); >>Sym *zzs_newadd(); >>char *zzs_strdup(); >>#endif >EOF_sym.h >cat << \EOF_type.h | sed 's/^>//' > type.h >>/* S y m b o l l e v e l s */ >>#define GLOBAL 1 >>#define PARAMETER 2 >>#define LOCAL 3 >> >>/* T y p e s */ >>#define tNone 0x0000 >>#define tInt 0x0001 >>#define tFloat 0x0002 >>#define tChar 0x0004 >>#define tShort 0x0008 >>#define tLong 0x0010 >>#define tDouble 0x0020 >>#define tVoid 0x0040 >>#define tUnsigned 0x0080 >>#define tEllipsis 0x0100 >>#define tUnion 0x0200 >>#define tStruct 0x0400 >>#define tEnum 0x0800 >>#define tTypeName 0x1000 >>#define tSigned 0x2000 >> >>/* T y p e q u a l i f i e r s */ >>#define cvNone 0x0000 >>#define cvConst 0x0001 >>#define cvVolatile 0x0002 >> >>/* S t o r a g e c l a s s e s */ >>#define scNone 0x0000 >>#define scAuto 0x0001 >>#define scRegister 0x0002 >>#define scStatic 0x0004 >>#define scExtern 0x0008 >>#define scTypedef 0x0010 >> >> >>/* A S T n o d e s */ >> >>/* type-tree nodes */ >>#define BaseTypeQ 1 >>#define PointerQ 2 >>#define ArrayQ 3 >>#define FunctionQ 4 >>#define FieldQ 5 >>#define SymQ 6 >> >>/* expr-tree nodes */ >>#define ENode 10 >> >> >>#define AST_FIELDS int nodeType; \ >> union { \ >> qPointer p; \ >> qArray a; \ >> qFunction f; \ >> qField fi; \ >> qSym s; \ >> ExprNode e; \ >> qBaseType t; \ >> } data; >> >>typedef struct _eNode { >> int token; >> } ExprNode; >> >>typedef struct _eOperator { >> int token; >> } eOperator; >> >>typedef struct _qSym { >> char *name; >> void *init; >> } qSym; >> >>typedef struct _qField { >> char *name; >> } qField; >> >>typedef struct _qPointer { >> int cv; >> } qPointer; >> >>typedef struct _qArray { >> struct _ast *dim; >> } qArray; >> >>/* don't need this right now */ >>typedef struct _qFunction { >> void *code; >> } qFunction; >> >>typedef struct _qBaseType { >> char *name; /* type/struct/union name */ >> int cv; >> int sc; >> int type; >> } qBaseType; >> >>/* how to create a default node */ >>#define zzcr_ast(ast, attr, tok, text) \ >> (ast)->data.e.token = tok; \ >> (ast)->nodeType = ENode; >EOF_type.h >cat << \EOF_proto.h | sed 's/^>//' > proto.h >>#ifdef __STDC__ >>char *strdup(char *); >>struct _ast *zzmk_ast(struct _ast *, int, ...); >>struct _ast *bottom(struct _ast *); >>struct _ast *defineArgs(struct _ast *, Sym **); >>void error(char *); >>void error1(char *, char *); >>void warn(char *); >>void warn1(char *, char *); >>Sym *addsym(int, char *,int , struct _ast *, struct _ast *); >>long strtol(char *, char**, int); >>#else >>char *strdup(); >>struct _ast *zzmk_ast(); >>struct _ast *bottom(); >>struct _ast *defineArgs(); >>void error(); >>void error1(); >>void warn(); >>void warn1(); >>Sym *addsym(); >>long strtol(); >>#endif >> >>extern Sym *Globals; >>extern Sym *Params; >EOF_proto.h >cat << \EOF_decl.g | sed 's/^>//' > decl.g >>/* >> * ANSI C recognizer >> * >> * Gives some error messages for semantics, but this grammar >> * checks mostly syntax. We make no claim that it rigorously follows >> * the ANSI C standard, but it's a good start. >> * >> * Type trees are constructed and maintained in the symbol table. >> * Expression trees are constructed and then thrown away. The >> * user can presumably do something more useful with them. >> * >> * Requires PCCTS Version 1.00 >> * >> * Terence Parr >> * July 1991 >> */ >> >>#header << >> #define D_TextSize 20 >> #include "charbuf.h" >> #include "type.h" >> #include "sym.h" >> #include "proto.h" >>>> >> >>#token "[\ \t]+" << zzskip(); >> >>#token "\n" << zzline++; zzskip(); >> >> >>#token "#line [\ \t]+ [0-9]+ ~[\n]*\n" >> << zzline = atoi(zzlextext+5); zzskip(); >> >>#token "# [\ \t]+ [0-9]+ ~[\n]*\n" >> << zzline = atoi(zzlextext+1); zzskip(); >> >> >>#token "\"" << zzmode(STRINGS); zzmore(); >> >>#token "'" << zzmode(CHARACTERS); zzmore(); >> >> >>/* these tokens are used as node types, but not referenced in grammar */ >>#token Var >>#token Func >>#token FuncCall >>#token Label >>#token PostInc >>#token PostDec >>#token StructPtrRef >>#token StructRef >>#token AggrTag >> >>#lexclass STRINGS >>#token STRING "\"" << zzmode(START); >> >>#token "\\\"" << zzmore(); >> >>#token "\\n" << zzreplchar('\n'); zzmore(); >> >>#token "\\r" << zzreplchar('\r'); zzmore(); >> >>#token "\\t" << zzreplchar('\t'); zzmore(); >> >>#token "\\[1-9][0-9]*" >> << zzreplchar((char)strtol(zzbegexpr,NULL,10)); zzmore(); >> >>#token "\\0[0-7]*" << zzreplchar((char)strtol(zzbegexpr,NULL,8)); zzmore(); >> >>#token "\\0x[0-9]+" << zzreplchar((char)strtol(zzbegexpr,NULL,16)); zzmore(); >> >>#token "\\~[\n\r]" << zzmore(); >> >>#token "[\n\r]" << zzline++; zzmore(); /* print warning about \n in str */>> >>#token "~[\"\n\r\\]+"<< zzmore(); >> >> >>#lexclass CHARACTERS >>#token CHARACTER "'" << zzmode(START); >> >>#token "\\'" << zzmore(); >> >>#token "\\n" << zzreplchar('\n'); zzmore(); >> >>#token "\\r" << zzreplchar('\r'); zzmore(); >> >>#token "\\t" << zzreplchar('\t'); zzmore(); >> >>#token "\\[1-9][0-9]*" >> << zzreplchar((char)strtol(zzbegexpr,NULL,10)); zzmore(); >> >>#token "\\0[0-7]*" << zzreplchar((char)strtol(zzbegexpr,NULL,8)); zzmore(); >> >>#token "\\0x[0-9]+" << zzreplchar((char)strtol(zzbegexpr,NULL,16)); zzmore(); >> >>#token "\\~[\n\r]" << zzmore(); >> >>#token "[\n\r]" << zzline++; zzmore(); /* print warning about \n in str */>> >>#token "~[\'\n\r\\]"<< zzmore(); >> >> >>#lexclass START >> >>#token OCT_NUM "[0][0-7]*" >>#token L_OCT_NUM "[0][0-7]*[Ll]" >>#token INT_NUM "[1-9][0-9]*" >>#token L_INT_NUM "[1-9][0-9]*[Ll]" >>#token HEX_NUM "[0][Xx][0-9A-Fa-f]+" >>#token L_HEX_NUM "[0][Xx][0-9A-Fa-f]+[Ll]" >>#token FNUM "([1-9][0-9]*{.[0-9]*} | {[0]}.[0-9]+) {[Ee]{[\+\-]}[0-9]+}" >>#token PreInc "\+\+" >>#token PreDec "\-\-" >>#token LPAREN "\(" >>#token LBRACK "\[" >>#token SizeOf "sizeof" >> >>globals!: <> zzs_scope(&Globals);>> >> >> ( <<;>> >> <> decl[GLOBAL] >> | <> >> <> >> declarator[base] >> <> t = defineArgs(#1, &Params); >> >> >> func_def[t] >> <> >> <> p = zzs_rmscope(&Params); >> pScope(p, "parameters\n"); >> >> >> )* >> >> <

> pScope(p, "globals\n"); >> ProtoVars(p);>> >> "@" >> ; >> >>/* d e c l -- recognize a declaration or definition. >> * >> * We handle typedefs in a bizarre way. WORD's are converted >> * to TypeName's inside the lexical action for token WORD. So, >> * because of the lookahead, we need to get a TypeName into >> * the symbol table before the lookahead can get a reference >> * to this. e.g. "typedef int I; I i;" We actually add the typedef >> * name to the symbol table when we see its definition in >> * rule declaration and friends. Aggregate tags are handled in a >> * similar fashion by adding them to the symbol table as they >> * are declared. >> * >> * functions definitions always have a FunctionQ node at the root >> * of the declarator since anything in front would make a pointer to >> * a function or whatever. e.g. int *f(); --> () * int --> "function >> * returning pointer to integer." Or, int (*f)() --> * () int --> >> * "pointer to function returning integer." The first is a function >> * symbol, the 2nd is a variable. >> */ >>decl![int level] >> : <> AST *base, *d, *init=NULL, *tr; >> char *w; >> Sym *n=NULL, *p;>> >> ( (sclass[&sc] | typeq[&cv])+ >> ( type[&t] <> >> | aggr[sc,cv] <> >> | enum_def <> >> | <> >> ) >> | type[&t] <> >> | aggr[scNone,cvNone] <> >> | enum_def <> >> ) >> ( declarator[base] <> >> ( { <> "=" initialize <> } >> <nodeType == FunctionQ ) { >> sc |= scExtern; >> bottom(d)->data.t.sc |= scExtern; >> } >> handleSymbol(sc, w, d, init, $level);>> >> ( <> >> "," >> declarator[base] >> { <> "=" initialize <> } >> <> >> <nodeType == FunctionQ ) { >> sc |= scExtern; >> bottom(#2)->data.t.sc |= scExtern; >> } >> handleSymbol(sc, $2.text, #2, init, $level);>> >> )* >> << >> if ( base->data.t.type==tStruct || >> base->data.t.type==tUnion || >> base->data.t.type==tEnum ) >> { >> if ( base->data.t.name != NULL ) >> { >> p = zzs_get(base->data.t.name); >> if ( p!=NULL ) p->level = $level; >> } >> } >> >> >> ";" >> | << >> handleSymbol(sc, w, d, init, $level); >> tr = defineArgs(d, &Params); >> >> >> func_def[tr] >> <> >> <> p = zzs_rmscope(&Params); >> pScope(p, "block\n"); >> >> >> ) >> | ";" >> <> >> <data.t.type==tStruct || >> base->data.t.type==tUnion || >> base->data.t.type==tEnum ) >> { >> p = zzs_get(base->data.t.name); >> if ( p!=NULL ) p->level = $level; >> } >> else >> error("missing declarator"); >> >> >> ) >> ; >> >>sclass![int *sc] >> : "auto" <<*$sc |= scAuto;>> >> | "static" <<*$sc |= scStatic;>> >> | "register" <<*$sc |= scRegister;>> >> | "extern" <<*$sc |= scExtern;>> >> | "typedef" <<*$sc |= scTypedef;>> >> ; >> >>typeq![int *cv] >> : "const" <<*$cv |= cvConst;>> >> | "volatile" <<*$cv |= cvVolatile;>> >> ; >> >>type![int *t] >> : t1[t] <<$type = $1;>> >> ; >> >>t1![int *type] >> : ( "unsigned" <<*$type = tUnsigned;>> >> | "signed" <<*$type = tSigned;>> >> ) >> ( "char" <<*$type |= tChar;>> >> | { "short" <<*$type |= tShort;>> >> | "long" <<*$type |= tLong;>> >> } >> { "int" <<*$type |= tInt;>> >> } >> ) >> | ( "short" <<*$type = tShort;>> >> { "int" <<*$type |= tInt;>> >> } >> | "long" <<*$type = tLong;>> >> { "int" <<*$type |= tInt;>> >> | "float" <<*$type |= tFloat;>> >> | "double" <<*$type |= tDouble;>> >> } >> ) >> | "void" <<*$type = tVoid;>> >> | "char" <<*$type = tChar;>> >> | "int" <<*$type = tInt;>> >> | "float" <<*$type = tFloat;>> >> | "double" <<*$type = tDouble;>> >> | TypeName <<*$type = tTypeName; $t1 = $1;>> >> ; >> >>/* D e c l a r a t o r */ >> >>/* >> * Build a declarator by appending the base to the bottom of the type-tree >> * matched in dcltor1. We pass the storage class to dcltor1 in case >> * we have a typedef on our hands which needs to be added to the symbol >> * table ASAP. >> */ >>declarator![AST *base] >> : dcltor1[bottom($base)] <<#(bottom(#1), $base); >> #0 = (#1==NULL)?$base:#1; >> $declarator = $1;>> >> ; >> >>/* >> * Match *D1 or D2. Build type-trees for PointerQ (pointer qualifier) >> * via: >> * >> * #0 = D1 >> * | >> * v >> * * >> * >> * where D? is dcltor? in this grammar. >> */ >>dcltor1![AST *base] >> : <> >> "\*" >> { "const" <> >> | "volatile" <> >> } <> >> dcltor1[$base] <<#(bottom(#3), t); #0=(#3==NULL)?t:#3; >> $dcltor1 = $3;>> >> | dcltor2[$base] <<#0 = #1; $dcltor1 = $1;>> >> ; >> >>/* >> * For WORD D3 we return the following >> * >> * $$ = WORD recognized. >> * #0 = D3 (array or func modifier) >> * >> * For ( D1 ) we return >> * >> * $$ = WORD recognized in D1. >> * #0 = D1 (put stuff in (..) above [] or ()) >> * | >> * v >> * D3 >> * >> * For instance, (*f)() yields >> * >> * $$ = f >> * #0 = * (pointer to) >> * | >> * v >> * ( ) (a function) >> * >> * If storage class is scTypedef, we need to add it to the symbol table. >> */ >>dcltor2![AST *base] /* pass in storage class for typedefs */ >> : <> >> WORD <data.t.sc&scTypedef ) >> addsym(TypeName,$1.text,0,NULL,NULL); >> >> >> dcltor3 <<#0 = #2; $dcltor2 = $1;>> >> | "\(" dcltor1[$base] "\)" <<$dcltor2 = $2;>> >> dcltor3 <<#(bottom(#2), #4); #0=(#2==NULL)?#4:#2;>> >> ; >> >>/* >> * return #0 = [expr] or = [nodimension] >> * or ( ) --> arg1 --> ... --> argn for a function >> * >> * multiple [1][2][3] yields >> * >> * #0 = [1] (an 1-element array of) >> * | >> * v >> * [2] (2-element arrays of) >> * | >> * v >> * [3] (3-element arrays) >> * >> */ >>dcltor3!: "\[" expr1 "\]" dcltor3 <<#0 = #( #[ArrayQ,#2], #4 );>> >> | "\[" "\]" dcltor3 <<#0 = #( #[ArrayQ,NULL], #3 );>> >> | "\(" args "\)" <<#0 = #(NULL, #[FunctionQ], #2);>> >> | <<#0 = NULL;>> >> ; >> >>/* >> * match a list of arguments. >> * >> * The arguments are siblings of the FunctionQ node in the type >> * tree. e.g. >> * >> * [FunctionQ]-->[arg1]--> ... -->[argn] >> * | | >> * v v >> * [type1] [type1] >> */ >>args! : <> >> arg <> >> ( "," arg <> >> )* >> { "," "..." <> >> } >> <<#0 = t;>> >> | >> ; >> >>arg! : typename <<#0 = #1;>> >> | WORD <<#0 = #[SymQ,$1.text,NULL];>> >> ; >> >>/* >> * match a typename -- (used in type-casting and function prototypes). >> * Type-trees look the same as those for decl. But, a symbol is >> * optional here because they can be used in argument lists. >> */ >>typename!: <> >> ( (typeq[&cv])+ >> { type[&t] <> >> | aggr[scNone,cv] <> >> } >> | type[&t] <> >> | aggr[scNone,cvNone] <> >> ) >> tdecl[base] <> #0=#(tr, #2);>> >> ; >> >>/* A g g r e g a t e s */ >> >>/* >> * match an enum definition; yield following tree: >> * >> * [BaseTypeQ] --> [elem1] --> ... --> [elemn] >> */ >>enum_def!: <> >> "enum" WORD <> >> enum_lst <<#0 = #(NULL, base, #3);>> >> ; >> >>/* >> * match a list of enumeration elements. >> * >> * The symbols are siblings of each other: >> * >> * [elem1] --> ... --> [elemn] >> * >> * If an element has an initialization, store a pointer to it in the >> * AST node. >> */ >>enum_lst!: <> >> "\{" >> WORD >> { "=" expr1 <> >> } <> >> ( "," >> WORD >> { <> >> "=" expr1 <> >> } <> >> )* >> "\}" >> <<#0 = list;>> >> | <<#0 = NULL;>> >> ; >> >>/* >> * Match a struct/union def. >> * Return a tree like this: >> * >> * [BaseTypeQ]-->[fld1]--> ... -->[fldn] >> * | | >> * v v >> * [type1] [type1] >> * >> * BUG: Allows two structs to have same name >> */ >>aggr![int sc, int cv] >> : <> >> ( "struct" <> >> | "union" <> >> ) <> >> ( ( WORD <data.t.name = strdup($1.text);>> >> | TypeName <data.t.name = strdup($1.text);>> >> ) >> ( ag[base] <<#0 = #(NULL, base, #1); >> addsym(AggrTag, base->data.t.name, >> 0, base, NULL); >> >> >> | <<#0 = base;>> >> ) >> | ag[base] <<#0 = #(NULL, base, #1);>> >> ) >> ; >> >>/* >> * match a field list for a struct/union >> * >> * The fields are siblings of each other: >> * >> * [fld1] --> ... --> [fldn] >> * | | >> * v v >> * [type1] [type1] >> * >> */ >>ag![AST *base] >> : <> >> "\{" fdef[$base] <<#0=t=#2;>> >> ( fdef[$base] <<#(NULL, t, #1); t = #1;>> >> )* >> "\}" >> ; >> >>/* >> * Match one field definition; make the following tree >> * >> * [FieldQ] >> * | >> * v >> * [type1] >> */ >>fdef![AST *base] >> : <> >> ( type[&t] <> >> | aggr[scNone,cvNone] <> >> ) >> field[$base] <> >> ( "," field[$base]<> f = #(NULL, f, g);>> >> )* >> ";" >> <<#0 = f;>> >> ; >> >>/* bitfields are recognized, but not handled 'cause not too many people >> * use them >> */ >>field![AST *base] >> : declarator[$base] { ":" expr1 } <<#0=#1; $field = $1;>> >> | ":" expr1 >> ; >> >>/* T y p e N a m e */ >> >>tdecl![AST *base] >> : tdecl1 <<#(bottom(#1), $base); >> #0 = (#1==NULL)?$base:#1; $tdecl=$1;>> >> ; >> >>tdecl1! : <> >> "\*" >> { "const" <> >> | "volatile" <> >> } <> >> tdecl1 <<#(bottom(#3), t); #0=(#3==NULL)?t:#3; >> $tdecl1 = $3;>> >> | tdecl2 <<#0 = #1; $tdecl1 = $1;>> >> ; >> >>tdecl2! : <> >> "\(" tdecl1 "\)" <<$tdecl2 = $2;>> >> tdecl3 <<#(bottom(#2), #4); #0=(#2==NULL)?#4:#2;>> >> | WORD tdecl3 <<$tdecl2 = $1; #0 = #2;>> >> | tdecl3 <<#0 = #1;>> >> ; >> >>tdecl3! : "\[" expr1 "\]" tdecl3<<#0 = #( #[ArrayQ,#2], #4 );>> >> | "\[" "\]" tdecl3<<#0 = #( #[ArrayQ,NULL], #3 );>> >> | "\(" args "\)" <<#0 = #( NULL, #[FunctionQ], #2 );>> >> | >> ; >> >> >>/* I n i t e x p r e s s i o n s */ >> >> >>initialize >> : init2 >> | expr0 >> ; >> >>/* Build an initialization expression-tree of the form: >> * >> * Single-dimensioned array or structure: >> * >> * "{" >> * | >> * v >> * [exp1] --> ... --> [expn] >> * >> * Nested structure or multi-dim array: >> * >> * "{" >> * | >> * v >> * "{" --> ... --> "{" >> * | ... >> * v ... >> * [exp1] --> ... --> [expn] >> */ >>init2 : "\{"^ init3 ( ","! init3 )* {","!} "\}"! >> ; >> >>init3 : init2 >> | expr1 >> ; >EOF_decl.g >cat << \EOF_func.g | sed 's/^>//' > func.g >>/* F u n c t i o n s */ >> >>/* recognize a function definition (after the "func_name(...)"). >> * If old-style arguments are found, a pointer to the list of >> * arguments is passed in. If there are no parameters or if new-style >> * definitions are used, $args is NULL. >> */ >>func_def[AST *args] >> : <> save = zzs_scope(NULL); zzs_scope(&Params);>> >> ( decl[PARAMETER] >> <> >> )* >> <> error("we've already got the parameters, thanks"); >> else checkArgs( args ); >> zzs_scope( save ); >> >> >> block >> ; >> >>block : <> static int level=LOCAL-1;>> >> <> >> >> "\{"^ >> ( decl[level] )* >> ( stat[level] )* >> "\}"! >> >> <<--level; >> p = zzs_rmscope(&locals); /* unlink from sym table */ >> pScope(p, "parameters\n"); >> zzs_scope(saveScope); /* return to old scope */ >> >> >> ; >> >>/* >> * match a statement and yield an expr-tree >> * >> * Label ":" >> * | >> * v >> * WORD >> * >> * expr expr >> * >> * block block >> * >> * if "if" >> * | >> * v >> * expr --> stat --> stat (2nd stat only if else-clause) >> * >> * while "while" >> * | >> * v >> * expr --> stat >> * >> * do "do" >> * | >> * v >> * stat --> expr >> * >> * for "for" >> * | >> * v >> * expr --> expr --> expr -> stat >> * >> * switch "switch" >> * | >> * v >> * expr --> stat >> * >> * case "case" >> * | >> * v >> * expr >> * >> * continue "continue" >> * >> * break "break" >> * >> * return "return" >> * | >> * v >> * expr >> * >> * goto "goto" >> * | >> * v >> * WORD >> * >> * ";" >> */ >>stat[int level] >> : <> >> WORD ":"^ >> <