📄 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-2001
*/
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "pcctscfg.h"
#include "set.h"
#include "syn.h"
#include "hash.h"
#include "generic.h"
#include "dlgdef.h"
#define NumExprPerLine 4
static int on1line=0;
static set tokensRefdInBlock;
/* 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 __cplusplus
void (*C_Trans[NumNodeTypes+1])(...) = {
NULL,
NULL, /* See next table.
Junctions have many types */
(void (*)(...)) genRuleRef,
(void (*)(...)) genToken,
(void (*)(...)) genAction
};
#else
void (*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 __cplusplus
void (*C_JTrans[NumJuncTypes+1])(...) = {
NULL,
(void (*)(...)) genSubBlk,
(void (*)(...)) genOptBlk,
(void (*)(...)) genLoopBlk,
(void (*)(...)) genEndBlk,
(void (*)(...)) genRule,
(void (*)(...)) genJunction,
(void (*)(...)) genEndRule,
(void (*)(...)) genPlusBlk,
(void (*)(...)) genLoopBegin
};
#else
void (*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_PROTOS
tab( void )
#else
tab( )
#endif
TAB
#ifdef __USE_PROTOS
static char *tokenFollowSet(TokNode *);
static ActionNode *findImmedAction( Node * );
static void dumpRetValAssign(char *, char *, RuleRefNode *); /* MR30 */
static void dumpAfterActions(FILE *output);
static set ComputeErrorSet(Junction *, int, int);
static void makeErrorClause(Junction *, set, int, 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 */
#else
static 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 */
#ifdef __USE_PROTOS
void MR_break(void)
#else
void MR_break()
#endif
{
return;
}
/* MR10 genTraceOut(Junction *) */
#ifdef __USE_PROTOS
static void genTraceOut(Junction *q)
#else
static 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_PROTOS
warn_about_using_gk_option(void)
#else
warn_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_PROTOS
freeBlkFsets( Junction *q )
#else
freeBlkFsets( 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_PROTOS
genTokenPointers( Junction *q )
#else
genTokenPointers( 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_PROTOS
hasDefaultException(ExceptionGroup *eg)
#else
hasDefaultException(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_PROTOS
dumpException(ExceptionGroup *eg, int no_default_case)
#else
dumpException(eg, no_default_case)
ExceptionGroup *eg;
int no_default_case;
#endif
{
char *outerLabel; /* MR7 */
int altHandler=0; /* MR7 */
int namedHandler=0; /* MR7 */
outerLabel=findOuterHandlerLabel(eg); /* MR7 */
if (eg->label != NULL) { /* MR7 */
namedHandler=1; /* MR7 */
} else if (eg->forRule) { /* MR7 */
/* nothing */ /* MR20 */
} 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_PROTOS
dumpExceptions(ListNode *list)
#else
dumpExceptions(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_PROTOS
genElementLabels(ListNode *list)
#else
genElementLabels(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_PROTOS
genASTPointers( Junction *q )
#else
genASTPointers( 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);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -