gen.c
来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 1,279 行 · 第 1/3 页
C
1,279 行
case PRED_OP :
if ( t->down->token != Action )
{
define_labels_in_block(t->down);
}
break;
case OPT :
define_labels_in_block(t->down);
break;
case BLOCK :
define_labels_in_block(t);
break;
}
}
/* 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.
June '93; changed so that empty lines are left alone so that
line information is correct for the compiler/debuggers.
*/
void
#ifdef __USE_PROTOS
dumpAction( char *s, FILE *output, int tabs, int file, int line, int final_newline )
#else
dumpAction( s, output, tabs, file, line, final_newline )
char *s;
FILE *output;
int tabs;
int file;
int line;
int final_newline;
#endif
{
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]);
}*/
PastWhiteSpace( s );
/* don't print a tab if first non-white char is a # (preprocessor command) */
if ( *s!='#' ) {TAB;}
inDQuote = inSQuote = 0;
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);
s++;
while (*s == '\n') {
putc('\n', output);
s++;
}
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);
}
char *
#ifdef __USE_PROTOS
find_predicate( AST *t )
#else
find_predicate( t )
AST *t;
#endif
{
if ( t==NULL ) return NULL;
if ( t->token == Action )
{
if ( t->right!=NULL && t->right->token==PRED_OP && t->right->down->token!=BLOCK )
{
return t->right->down->action;
}
}
else if ( t->token == PRED_OP && t->down->token!=BLOCK )
{
return t->down->action;
}
return NULL;
}
/* Given a pointer to a tree pattern element (Token, BLOCK, etc...),
* generate an expression that predicts when that path would match.
*/
set
#ifdef __USE_PROTOS
gen_prediction_expr( AST *alt, GLA *t )
#else
gen_prediction_expr( alt, t )
AST *alt;
GLA *t;
#endif
{
char *sempred;
set a, rs;
int tok, first=1, num_on_line=0;
require(alt==NULL||alt->token==ALT,
"gen_prediction_expr: AST node is invalid");
a = Lookahead(t);
rs = set_dup(a);
/* if this production is a guess block, then test return value of setjmp() */
/* MR21 Problem reported by Peter Keller
THM: Sor doesn't see predicate because of intervening action.
*/
if (alt != NULL) {
AST* cursor;
for (cursor = alt->down;
cursor != NULL && Action == cursor->token;
cursor = cursor->right) {
/* nothing */
}
if (cursor != NULL &&
cursor->token == PRED_OP &&
cursor->down->token == BLOCK) {
fprintf(output," !_gv &&");
}
}
#if 0
/* The old code which was replaced */
if ( alt!=NULL && alt->down!=NULL && alt->down->token==PRED_OP &&
alt->down->down->token==BLOCK ) fprintf(output, " !_gv &&");
#endif
/* handle end of input first */
if ( set_el(end_of_input, a) )
{
fprintf(output, " _t==NULL");
set_rm(end_of_input, a);
if ( !set_nil(a) ) fprintf(output, " ||");
}
else if ( set_el(wild_card, a) )
{
fprintf(output, " _t!=NULL");
if ( alt!=NULL ) {
sempred = find_predicate(alt->down);
if ( sempred!=NULL ) fprintf(output, " && (%s)", sempred);
}
set_free(a);
return rs;
}
else
{
fprintf(output, " _t!=NULL");
if ( !set_nil(a) ) fprintf(output, " &&");
}
if ( set_nil(a) ) { set_free(a); return rs; }
fprintf(output, " (");
while ( !set_nil(a) )
{
tok = set_int(a);
set_rm(tok, a);
if ( first ) first = 0;
else fprintf(output, "||");
if ( num_on_line>=2 ) {num_on_line=0; fprintf(output,"\n"); TAB;}
else num_on_line++;
if ( tok==wild_card ) fprintf(output, "_t!=NULL");
else if ( token_dict[tok]==0 )
{
if ( GenCPP )
fprintf(output, "_t->type()==UNDEFINED_TOKEN");
else
fprintf(output, "_t->token==UNDEFINED_TOKEN");
}
else
{
if ( GenCPP )
fprintf(output, "_t->type()==%s", token_dict[tok]);
else
fprintf(output, "_t->token==%s", token_dict[tok]);
}
}
fprintf(output, ")");
if ( alt!=NULL ) {
sempred = find_predicate(alt->down);
if ( sempred!=NULL ) fprintf(output, " && (%s)", sempred);
}
set_free(a);
return rs;
}
/* Find all return types/parameters that require structs and def
* all rules with ret types.
*/
void
#ifdef __USE_PROTOS
GenRulePrototypes( FILE *f, int tabs )
#else
GenRulePrototypes( f, tabs )
FILE *f;
int tabs;
#endif
{
AST *p;
SymEntry *s;
for (p=rules; p!=NULL; p=p->right)
{
int i;
s = (SymEntry *) hash_get(symbols, p->text);
require(s!=NULL, "GenRulePrototypes: sym tab broken");
for (i=1; i<=tabs; i++) fprintf(f, "\t");
GenRulePrototype(f, p, s, 1);
}
}
void
#ifdef __USE_PROTOS
GenRulePrototype(FILE *f, AST *p, SymEntry *s, int decl_not_def)
#else
GenRulePrototype(f, p, s, decl_not_def)
FILE *f;
SymEntry *s;
AST *p;
int decl_not_def;
#endif
{
require(s!=NULL&&s->definition!=NULL, "GenRulePrototype: no def for rule");
if ( GenCPP )
{
if ( s->rt != NULL )
DumpType(s->rt, f, FileStr[s->definition->file], s->definition->line);
else fprintf(f, "void");
if ( decl_not_def )
fprintf(f, " %s(SORASTBase **_root%s",
p->text,
transform?", SORASTBase **_result":"");
else
fprintf(f, " %s::%s(SORASTBase **_root%s",
CurClassName,
p->text,
transform?", SORASTBase **_result":"");
if ( s->args != NULL ) fprintf(f, ",%s", s->args);
fprintf(f, ")");
if ( decl_not_def ) fprintf(f, ";");
fprintf(f, "\n");
return;
}
if ( decl_not_def ) fprintf(f, "extern ");
if ( GenAnsiProtos && GenKRProtos ) fprintf(f, "\n#ifdef __USE_PROTOS\n");
if ( GenAnsiProtos )
{
if ( s->rt != NULL )
DumpType(s->rt, f, FileStr[s->definition->file], s->definition->line);
else fprintf(f, "void");
fprintf(f, " %s%s(STreeParser *_parser, SORAST **_root%s",
Prefix,
p->text,
transform?", SORAST **_result":"");
if ( s->args != NULL ) fprintf(f, ",%s", s->args);
fprintf(f, ")");
if ( decl_not_def ) fprintf(f, ";");
fprintf(f, "\n");
}
if ( GenAnsiProtos && GenKRProtos ) fprintf(f, "#else\n");
if ( GenKRProtos )
{
if ( s->rt != NULL )
DumpType(s->rt, f, FileStr[s->definition->file], s->definition->line);
else fprintf(f, "void");
if ( decl_not_def) fprintf(f, " %s%s();\n", Prefix, p->text);
else
{
fprintf(f, " %s%s(_parser, _root%s",
Prefix, p->text,transform?", _result":"");
if ( s->args!=NULL ) fprintf(f, ",");
DumpListOfParmNames(s->args, f);
fprintf(f, ")\n");
fprintf(f, "STreeParser *_parser;\n");
fprintf(f, "SORAST **_root%s;\n", transform?", **_result":"");
DumpOldStyleParms(s->args, f);
}
}
if ( GenAnsiProtos && GenKRProtos ) fprintf(f, "#endif\n");
}
/*
* For each referenced token, generate a #define in a file defined in
* 'def_token_file'.
*/
void
#ifdef __USE_PROTOS
gen_tokens_file( void )
#else
gen_tokens_file( )
#endif
{
FILE *f;
ListNode *p;
if ( def_token_file==NULL ) return;
f = fopen(def_token_file, "w");
if ( f==NULL )
{
errNoFL(eMsg1("cannot write token definition file %s", def_token_file));
return;
}
#ifdef SPECIAL_FOPEN
special_fopen_actions(def_token_file);
#endif
gen_info_hdr(f);
fprintf(f, "\n");
for (p = token_list->next; p!=NULL; p=p->next)
{
SymEntry *t = (SymEntry *) p->elem;
fprintf(f, "#define %s %d\n", t->str, t->token_type);
}
fclose(f);
}
AST *
#ifdef __USE_PROTOS
first_guess_block(AST *q)
#else
first_guess_block(q)
AST *q;
#endif
{
require(q!=NULL&&q->token==ALT, "first_guess_block: non-ALT ptr");
if ( q->down!=NULL )
{
if ( (q->down->token==PRED_OP && q->down->down!=NULL &&
q->down->down->token==BLOCK) )
{
return q->down;
}
else if (q->down->token==Action && q->down->right!=NULL &&
q->down->right->token==PRED_OP && q->down->right->down!=NULL &&
q->down->right->down->token==BLOCK)
{
return q->down->right;
}
else return NULL;
}
return NULL;
}
void
#ifdef __USE_PROTOS
code_for_guess_block( AST *t, int *guess_block_in_prev_alt )
#else
code_for_guess_block( t, guess_block_in_prev_alt )
AST *t;
int *guess_block_in_prev_alt;
#endif
{
if ( found_guess_block )
{
/* if previous alt had a guess block, check to turn it off */
if ( *guess_block_in_prev_alt )
{
TAB;
if ( GenCPP ) fprintf(output, "if ( guessing ) _GUESS_DONE;\n");
else fprintf(output, "if ( _parser->guessing ) _GUESS_DONE;\n");
}
/* if current alt has a guess block... */
if ( first_guess_block(t)!=NULL )
{
TAB;
fprintf(output, "_GUESS;\n");
*guess_block_in_prev_alt = 1;
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?