📄 gen.c
字号:
if ( (e=g=set_pdq(fset[k])) == NULL ) fatal_internal("genExpr: cannot allocate IF expr pdq set"); for (; *e!=nil; e++) { if ( !firstTime ) _gen(" || ") else { _gen("("); firstTime = 0; } on1line++; if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } _gen1("LA(%d)==",k); if ( TokenString(*e) == NULL ) _gen1("%d", *e) else _gen1("%s", TokenString(*e)); } free( (char *)g ); _gen(")"); if ( k>max_k ) max_k = k; if ( k == CLL_k ) break; k++; if ( k <= limit && !set_nil(fset[k]) ) { firstTime=1; _gen(" && "); } /* MR11 */ on1line++; if ( on1line > NumExprPerLine ) { on1line=0; _gen("\n"); } } 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#ifdef __USE_PROTOSgenBlk( Junction *q, int jtype, int *max_k, int *need_right_curly )#elsegenBlk( q, jtype, max_k, need_right_curly )Junction *q;int jtype;int *max_k;int *need_right_curly;#endif{ set f; Junction *alt; int a_guess_in_block = 0; require(q!=NULL, "genBlk: invalid node"); require(q->ntype == nJunction, "genBlk: not junction"); *need_right_curly=0; if ( q->p2 == NULL ) /* only one alternative? Then don't need if */ { if (first_item_is_guess_block((Junction *)q->p1)!=NULL ) { if (jtype != aLoopBlk && jtype != aOptBlk && jtype != aPlusBlk) { warnFL("(...)? as only alternative of block is unnecessary", FileStr[q->file], q->line); }; gen("zzGUESS\n"); /* guess anyway to make output code consistent *//* MR10 disable */ /**** gen("if ( !zzrv )\n"); ****//* MR10 */ gen("if ( !zzrv ) {\n"); tabs++; (*need_right_curly)++; }; 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 */ } } }/* MR10 */ if (alt->p2 == NULL &&/* MR10 */ ( q->jtype == aSubBlk || q->jtype == RuleBlk) ) {/* MR10 */ if (first_item_is_guess_block(alt)) {/* MR10 */ warnFL("(...)? as last alternative of block is unnecessary",/* MR10 */ FileStr[alt->file],alt->line);/* MR10 */ };/* MR10 */ }; if ( alt != q ) gen("else ") else { if ( DemandLookahead ) if ( !GenCC ) {gen1("LOOK(%d);\n", *max_k);} else gen1("look(%d);\n", *max_k); } if ( alt!=q ) { _gen("{\n"); tabs++; (*need_right_curly)++; /* code to restore state if a prev alt didn't follow guess */ if ( a_guess_in_block ) gen("if ( !zzrv ) zzGUESS_DONE;\n"); } if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) { a_guess_in_block = 1; gen("zzGUESS\n"); } gen("if ( "); if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) _gen("!zzrv && "); genExpr(alt); _gen(" ) "); _gen("{\n"); tabs++; TRANS(alt->p1); --tabs; gen("}\n");/* MR10 */ if (alt->p2 == NULL) {/* MR10 */ if (first_item_is_guess_block(alt)) {/* MR10 */ gen("/* MR10 */ else {\n");/* MR10 */ tabs++;/* MR10 */ (*need_right_curly)++;/* MR10 */ /* code to restore state if a prev alt didn't follow guess *//* MR10 */ gen("/* MR10 */ if ( !zzrv ) zzGUESS_DONE;\n");/* MR10 */ gen("/* MR10 */ if (0) {} /* last alternative of block is guess block */\n");/* MR10 */ };/* MR10 */ }; } return f;}static int#ifdef __USE_PROTOShas_guess_block_as_first_item( Junction *q )#elsehas_guess_block_as_first_item( q )Junction *q;#endif{ Junction *alt; for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) { if ( first_item_is_guess_block((Junction *)alt->p1)!=NULL ) return 1; } return 0;}static int#ifdef __USE_PROTOShas_guess_block_as_last_item( Junction *q )#elsehas_guess_block_as_last_item( q )Junction *q;#endif{ Junction *alt; if (q == NULL) return 0; for (alt=q; alt->p2 != NULL && !( (Junction *) alt->p2)->ignore; alt= (Junction *) alt->p2 ) {}; return first_item_is_guess_block( (Junction *) alt->p1) != NULL;}/* return NULL if 1st item of alt is NOT (...)? block; else return ptr to aSubBlk node * of (...)?; This function ignores actions and predicates. */Junction *#ifdef __USE_PROTOSfirst_item_is_guess_block( Junction *q )#elsefirst_item_is_guess_block( q )Junction *q;#endif{ /* MR14 Couldnt' find aSubBlock which was a guess block when it lay behind aLoopBlk. The aLoopBlk only appear in conjunction with aLoopBegin, but the routine didn't know that. I think. */ while ( q!=NULL && ( q->ntype==nAction ) || ( q->ntype==nJunction && (q->jtype==Generic || q->jtype == aLoopBlk )) ) { if ( q->ntype==nJunction ) q = (Junction *)q->p1; else q = (Junction *) ((ActionNode *)q)->next; } if ( q==NULL ) return NULL; if ( q->ntype!=nJunction ) return NULL; if ( q->jtype!=aSubBlk ) return NULL; if ( !q->guess ) return NULL; return q;}/* MR1 *//* MR1 10-Apr-97 MR1 Routine to stringize failed semantic predicates msgs *//* MR1 */#define STRINGIZEBUFSIZE 1024static char stringizeBuf[STRINGIZEBUFSIZE];char *#ifdef __USE_PROTOSstringize(char * s)#elsestringize(s)char *s;#endif{ char *p; char *stop; p=stringizeBuf; stop=&stringizeBuf[1015]; if (s != 0) { while (*s != 0) { if (p >= stop) { goto stringizeStop; } else if (*s == '\n') { *p++='\\'; *p++='n'; *p++='\\'; *p++=*s++; } else if (*s == '\\') { *p++=*s; *p++=*s++; } else if (*s == '\"') { *p++='\\'; *p++=*s++; while (*s != 0) { if (p >= stop) { goto stringizeStop; } else if (*s == '\n') { *p++='\\'; *p++=*s++; } else if (*s == '\\') { *p++=*s++; *p++=*s++; } else if (*s == '\"') { *p++='\\'; *p++=*s++; break; } else { *p++=*s++; }; }; } else if (*s == '\'') { *p++=*s++; while (*s != 0) { if (p >= stop) { goto stringizeStop; } else if (*s == '\'') { *p++=*s++; break; } else if (*s == '\\') { *p++=*s++; *p++=*s++; } else if (*s == '\"') { *p++='\\'; *p++=*s++; break; } else { *p++=*s++; }; }; } else { *p++=*s++; }; }; }; goto stringizeExit;stringizeStop: *p++='.'; *p++='.'; *p++='.'; stringizeExit: *p=0; return stringizeBuf;}#ifdef __STDC__int isNullAction(char *s)#elseint isNullAction(s) char *s;#endif{ char *p; for (p=s; *p != '\0' ; p++) { if (*p != ';' && *p !=' ') return 0; }; return 1;}/* MR1 *//* MR1 End of Routine to stringize code for failed predicates msgs *//* MR1 *//* Generate an action. Don't if action is NULL which means that it was already * handled as an init action. */void#ifdef __USE_PROTOSgenAction( ActionNode *p )#elsegenAction( p )ActionNode *p;#endif{ require(p!=NULL, "genAction: invalid node and/or rule"); require(p->ntype==nAction, "genAction: not action"); if ( !p->done ) /* MR10 */ /* MR11 */ { if ( p->is_predicate) { if ( p->guardpred != NULL ) { Predicate *guardDup=predicate_dup(p->guardpred); /* MR10 */ gen("if (!"); guardDup=genPredTreeMain(guardDup, (Node *)p); predicate_free(guardDup); }/* MR10 */ else if (p->ampersandPred != NULL) {/* MR10 */ gen("if (!");/* MR10 */ p->ampersandPred=genPredTreeMain(p->ampersandPred, (Node *)p);/* MR10 */ } else { gen("if (!("); /* make sure that '#line n' is on front of line */ if ( GenLineInfo && p->file != -1 ) _gen("\n"); dumpPredAction(p,p->action, output, 0, p->file, p->line, 0); _gen(")"); } if ( p->pred_fail != NULL ) { _gen(")\n"); tabs++;/* MR1 *//* MR1 10-Apr-97 MR1 Put {...} envelope around failed semantic predicates *//* MR1 */ gen1("{%s};\n", p->pred_fail); /* MR1 */ tabs--; }/* MR1 *//* MR1 10-Apr-97 MR1 Properly stringize failed semantic predicates *//* MR1 */ else _gen1(") {zzfailed_pred(\"%s\");}\n", /* MR1 */ stringize(p->action)); /* MR1 */ } else /* not a predicate */ { if (! isNullAction(p->action) && !p->noHoist) { if ( FoundGuessBlk ) { if ( GenCC ) { gen("if ( !guessing ) {\n"); } else { gen("zzNON_GUESS_MODE {\n"); }; }; dumpAction(p->action, output, tabs, p->file, p->line, 1); if ( FoundGuessBlk ) gen("}\n"); }; } } 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#ifdef __USE_PROTOSgenRuleRef( RuleRefNode *p )#elsegenRuleRef( p )RuleRefNode *p;#endif{ Junction *q; char *handler_id = ""; RuleEntry *r, *r2; char *parm = "", *exsig = ""; int genRuleRef_emittedGuessGuard=0; /* MR10 */ require(p!=NULL, "genRuleRef: invalid node and/or rule"); require(p->ntype==nRuleRef, "genRuleRef: not rule reference"); if ( p->altstart!=NULL && p->altstart->exception_label!=NULL ) handler_id = p->altstart->exception_label; r = (RuleEntry *) hash_get(Rname, p->text); if ( r == NULL ) { warnFL( eMsg1("rule %s not defined", p->text), FileStr[p->file], p->line ); return; }/* MR8 5-Aug-97 Reported by S.Bochnak@microtool.com.pl *//* Don't do assign when no return values declared *//* Move definition of q up and use it to guard p->assign */ q = RulePtr[r->rulenum]; /* find definition of ref'd rule */ /* MR8 */ r2 = (RuleEntry *) hash_get(Rname, p->rname); if ( r2 == NULL ) {warnNoFL("Rule hash table is screwed up beyond belief"); return;} OutLineInfo(output,p->line,FileStr[p->file]); if ( GenCC && GenAST ) { gen("_ast = NULL;\n"); } if ( FoundGuessBlk && p->assign!=NULL && q->ret != NULL ) { /* MR8 */ if ( GenCC ) { gen("if ( !guessing ) {\n"); } else { gen("zzNON_GUESS_MODE {\n"); }; tabs++; /* MR11 */ genRuleRef_emittedGuessGuard=1; /* MR11 */ }; if ( FoundException ) exsig = "&_signal"; tab(); if ( GenAST ) { if ( GenCC ) {/**** if ( r2->noAST || p->astnode==ASTexclude )****/ {/**** _gen("_ast = NULL;\n");****/ parm = "&_ast"; }/*** we always want to set just a pointer now, then set correctpointer after else { _gen("_astp =(_tail==NULL)?(&_sibling):(&(_tail->_right));\n"); parm = "_astp"; }****/ } else { if ( r2->noAST || p->astnode==ASTexclude ) { _gen("_ast = NULL; "); parm = "&_ast"; } else parm = "zzSTR"; } if ( p->assign!=NULL && q->ret!=NULL ) /* MR8 */ { if ( !HasComma(p->assign) ) {_gen1("%s = ",p->assign);} else _gen1("{ struct _rv%d _trv; _trv = ", r->rulenum); } if ( FoundException ) { _gen5("%s%s(%s,&_signal%s%s); ", RulePrefix, p->text, parm, (p->parms!=NULL)?",":"", (p->parms!=NULL)?p->parms:""); if ( p->ex_group!=NULL ) { _gen("\n"); gen("if (_signal) {\n"); tabs++; dumpException(p->ex_group, 0); tabs--; gen("}"); } else { _gen1("if (_signal) goto %s_handler;", handler_id); } } else { _gen5("%s%s(%s%s%s);", RulePrefix, p->text, parm, (p->parms!=NULL)?",":"", (p->parms!=NULL)?p->parms:""); } if ( GenCC && (r2->noAST || p->astnode==ASTexclude) ) { /* rule has a ! or element does */ /* still need to assign to #i so we can play with it */ _gen("\n"); gen2("_ast%d%d = (AST *)_ast;", BlkLevel-1, p->elnum); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -