📄 gen.c
字号:
/* * gen.c * * Generate C code (ANSI, K&R, 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.33 * Terence Parr * Parr Research Corporation * with Purdue University and AHPCRC, University of Minnesota * 1989-1998 */#include <stdio.h>#include <ctype.h>#include "set.h"#include "syn.h"#include "hash.h"#include "generic.h"#include "dlgdef.h"#define NumExprPerLine 4static int on1line=0;static set tokensRefdInBlock;extern char *PRED_AND_LIST;extern char *PRED_OR_LIST; /* 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. */#ifdef __cplusplusvoid (*C_Trans[NumNodeTypes+1])(...) = { NULL, NULL, /* See next table.Junctions have many types */ (void (*)(...)) genRuleRef, (void (*)(...)) genToken, (void (*)(...)) genAction };#elsevoid (*C_Trans[NumNodeTypes+1])() = { NULL, NULL, /* See next table.Junctions have many types */ genRuleRef, genToken, genAction };#endif/* C_JTrans[Junction type] == pointer to function that knows how to translate that * kind of junction node. */#ifdef __cplusplusvoid (*C_JTrans[NumJuncTypes+1])(...) = { NULL, (void (*)(...)) genSubBlk, (void (*)(...)) genOptBlk, (void (*)(...)) genLoopBlk, (void (*)(...)) genEndBlk, (void (*)(...)) genRule, (void (*)(...)) genJunction, (void (*)(...)) genEndRule, (void (*)(...)) genPlusBlk, (void (*)(...)) genLoopBegin };#elsevoid (*C_JTrans[NumJuncTypes+1])() = { NULL, genSubBlk, genOptBlk, genLoopBlk, genEndBlk, genRule, genJunction, genEndRule, genPlusBlk, genLoopBegin };#endif#define PastWhiteSpace(s) while (*(s) == ' ' || *(s) == '\t') {s++;}static int tabs = 0;/* MR6 Got tired of text running off page when using standard tab stops */#define TAB { int i; \ if (TabWidth==0) { \ for (i=0; i<tabs; i++) fputc('\t', output); \ } else { \ for (i=0; i<tabs*TabWidth; i++) fputc(' ',output); \ }; \ }static void#ifdef __USE_PROTOStab( void )#elsetab( )#endifTAB#ifdef __USE_PROTOSstatic char *tokenFollowSet(TokNode *);static ActionNode *findImmedAction( Node * );static void dumpRetValAssign(char *, char *);static void dumpAfterActions(FILE *output);static set ComputeErrorSet(Junction *, int);static void makeErrorClause(Junction *, set, int);static void DumpFuncHeader( Junction *, RuleEntry * );static int has_guess_block_as_first_item(Junction *);static int genExprSets(set *, int);static void genExprTree( Tree *t, int k );static void genExprTreeOriginal( Tree *t, int k ); /* MR10 */static char * findOuterHandlerLabel(ExceptionGroup *eg); /* MR7 */static void OutLineInfo(FILE *file,int line,char *fileName); /* MR14 */#elsestatic char *tokenFollowSet();static ActionNode *findImmedAction();static void dumpRetValAssign();static void dumpAfterActions();static set ComputeErrorSet();static void makeErrorClause();static void DumpFuncHeader();static int has_guess_block_as_first_item();static int genExprSets();static void genExprTree();static void genExprTreeOriginal(); /* MR10 */static char * findOuterHandlerLabel(); /* MR7 */static void OutLineInfo(); /* MR14 */#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 gen7(s,a,b,c,d,e,f,g) {tab(); fprintf(output, s,a,b,c,d,e,f,g);}#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);}#define _gen6(s,a,b,c,d,e,f){fprintf(output, s,a,b,c,d,e,f);}#define _gen7(s,a,b,c,d,e,f,g){fprintf(output, s,a,b,c,d,e,f,g);}/* MR11 a convenient place to set a break point */void MR_break() { return;}/* MR10 genTraceOut(Junction *) */#ifdef __STDC__static void genTraceOut(Junction *q)#elsestatic void genTraceOut(q) Junction *q;#endif{ if ( TraceGen ) if ( GenCC ) {gen1("zzTRACEOUT(\"%s\");\n", q->rname);} else gen1("zzTRACEOUT((ANTLRChar *)\"%s\");\n", q->rname);}static void#ifdef __USE_PROTOSwarn_about_using_gk_option(void)#elsewarn_about_using_gk_option()#endif{ static int warned_already=0; if ( !DemandLookahead || warned_already ) return; warned_already = 1; warnNoFL("-gk option could cause trouble for <<...>>? predicates");}void#ifdef __USE_PROTOSfreeBlkFsets( Junction *q )#elsefreeBlkFsets( q )Junction *q;#endif{ int i; Junction *alt; require(q!=NULL, "freeBlkFsets: invalid node"); for (alt=q; alt != NULL; alt= (Junction *) alt->p2 ) { for (i=1; i<=CLL_k; i++) set_free(alt->fset[i]); }}/* * Generate a local variable allocation for each token references * in this block. */static void#ifdef __USE_PROTOSgenTokenPointers( Junction *q )#elsegenTokenPointers( q )Junction *q;#endif{ /* Rule refs are counted and can be referenced, but their * value is not set to anything useful ever. * * The ptrs are to be named _tij where i is the current level * and j is the element number within an alternative. */ int first=1, t=0; set a; tokensRefdInBlock = q->tokrefs; if ( set_deg(q->tokrefs) == 0 ) return; a = set_dup(q->tokrefs); gen("ANTLRTokenPtr "); for (; !set_nil(a); set_rm(t, a)) { t = set_int(a); if ( first ) first = 0; else _gen(","); if ( !DontCopyTokens ) _gen2("_tv%d%d,", BlkLevel, t); _gen2("_t%d%d", BlkLevel, t); if ( !DontCopyTokens ) {_gen2("= &_tv%d%d", BlkLevel, t);} else _gen("=NULL"); } _gen(";\n"); set_free(a);}static int#ifdef __USE_PROTOShasDefaultException(ExceptionGroup *eg)#elsehasDefaultException(eg)ExceptionGroup *eg;#endif{ ListNode *q; for (q = eg->handlers->next; q!=NULL; q=q->next) { ExceptionHandler *eh = (ExceptionHandler *)q->elem; if ( strcmp("default", eh->signalname)==0 ) { return 1; } } return 0;}static void#ifdef __USE_PROTOSdumpException(ExceptionGroup *eg, int no_default_case)#elsedumpException(eg, no_default_case)ExceptionGroup *eg;int no_default_case;#endif{ char *outerLabel; /* MR7 */ int nullOuterLabel=0; /* MR7 */ int altHandler=0; /* MR7 */ int ruleHandler=0; /* MR7 */ int namedHandler=0; /* MR7 */ outerLabel=findOuterHandlerLabel(eg); /* MR7 */ if (*outerLabel=='\0') nullOuterLabel=1; /* MR7 */ if (eg->label != NULL) { /* MR7 */ namedHandler=1; /* MR7 */ } else if (eg->forRule) { /* MR7 */ ruleHandler=1; /* MR7 */ } else { /* MR7 */ altHandler=1; /* MR7 */ }; /* MR7 */#if 0** if (! eg->used) { /* MR7 */** warnFL("exception group never used", /* MR7 */** FileStr[eg->altstart->file],eg->altstart->line); /* MR7 */** }; /* MR7 */#endif if (namedHandler) { /* MR7 */ gen1("switch ( _signal ) { /* [%s] */\n",eg->label); /* MR7 */ } else { /* MR7 */ gen("switch ( _signal ) {\n"); /* MR7 */ gen("case NoSignal: break; /* MR7 */\n"); /* MR7 */ }; /* MR7 */ { ListNode *q; for (q = eg->handlers->next; q!=NULL; q=q->next) { ExceptionHandler *eh = (ExceptionHandler *)q->elem; if ( strcmp("default", eh->signalname)==0 ) { gen("default :\n"); tabs++; dumpAction(eh->action, output, tabs, -1, 1, 1); gen("_signal=NoSignal; /* MR7 */\n"); /* MR7 */ gen("break; /* MR7 */\n"); /* MR7 */ tabs--; gen("}\n"); /* copied from later code in dumpException MR7 */ if (namedHandler) { /* MR7 */ gen("if (_signal != NoSignal)"); /* MR7 */ _gen1(" goto %s_handler; /* MR7 */\n",outerLabel);/* MR7 */ } else if (altHandler) { /* MR7 */ gen1("goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */ }; return; } gen1("case %s :\n", eh->signalname); tabs++; if ( eh->action != NULL ) { dumpAction(eh->action, output, tabs, -1, 1, 1); gen("break; /* MR7 */\n"); /* MR7 */ } tabs--; } } if ( no_default_case ) return; gen("default :\n"); tabs++; /* MR7 */ gen("break; /* MR7 */\n"); /* MR7 */ tabs--; /* MR7 */ tabs++;/***** gen("*_retsignal = _signal;\n"); *****/ tabs--; gen("}\n"); if (namedHandler) { /* MR7 */ gen("if (_signal != NoSignal)"); /* MR7 */ _gen1(" goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */ } else if (altHandler) { /* MR7 */ gen1("goto %s_handler; /* MR7 */\n",outerLabel); /* MR7 */ };}static void#ifdef __USE_PROTOSdumpExceptions(ListNode *list)#elsedumpExceptions(list)ListNode *list;#endif{ ListNode *p; for (p = list->next; p!=NULL; p=p->next) { ExceptionGroup *eg = (ExceptionGroup *) p->elem; _gen2("%s%s_handler:\n", eg->label==NULL?"":eg->label, eg->altID==NULL?"":eg->altID); if ( eg->altID!=NULL ) dumpException(eg, 0); else { /* This must be the rule exception handler */ dumpException(eg, 1); if ( !hasDefaultException(eg) ) { gen("default :\n"); tabs++; gen("zzdflthandlers(_signal,_retsignal);\n"); tabs--; gen("}\n"); } } }}/* For each element label that is found in a rule, generate a unique * Attribute (and AST pointer if GenAST) variable. */void#ifdef __USE_PROTOSgenElementLabels(ListNode *list)#elsegenElementLabels(list)ListNode *list;#endif{ int first=1; ListNode *p; if ( GenCC ) {gen("ANTLRTokenPtr");} else {gen("Attrib");} for (p = list->next; p!=NULL; p=p->next) { char *ep = (char *)p->elem; if ( first ) first = 0; else _gen(","); if ( GenCC ) {_gen1(" %s=NULL",ep);} else {_gen1(" %s",ep);} } _gen(";\n"); if ( !GenAST ) return; first = 1; gen("AST"); for (p = list->next; p!=NULL; p=p->next) { char *ep = (char *)p->elem; if ( first ) first = 0; else _gen(","); _gen1(" *%s_ast=NULL",ep); } _gen(";\n");}/* * Generate a local variable allocation for each token or rule reference * in this block. */static void#ifdef __USE_PROTOSgenASTPointers( Junction *q )#elsegenASTPointers( q )Junction *q;#endif{ int first=1, t; set a; a = set_or(q->tokrefs, q->rulerefs); if ( set_deg(a) > 0 ) { gen("AST "); for (; !set_nil(a); set_rm(t, a)) { t = set_int(a); if ( first ) first = 0; else _gen(","); _gen2("*_ast%d%d=NULL", BlkLevel, t); } set_free(a); } _gen(";\n");}static void#ifdef __USE_PROTOSBLOCK_Head( void )#elseBLOCK_Head( )#endif{ gen("{\n"); tabs++; if ( !GenCC ) gen1("zzBLOCK(zztasp%d);\n", BlkLevel);}static void#ifdef __USE_PROTOSBLOCK_Tail( void )#elseBLOCK_Tail( )#endif{
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -