gen.c
来自「SRI international 发布的OAA框架软件」· C语言 代码 · 共 1,279 行 · 第 1/3 页
C
1,279 行
/* Error if (...)? with only one alt */
for (u = q->down; u!=NULL; u=u->right ) {num_alts++;}
g = first_guess_block(q->down);
if ( num_alts==1 && g!=NULL )
{
warnFL("(...)? predicate in block with one alternative; will generate bad code",
FileStr[g->file], g->line);
}
t = t->down; /* move down to first alt */
while ( t!=NULL && t->token == ALT )
{
require(start_state!=NULL, "gen_block: invalid GLA for block");
if ( t!=q->down ) {
TAB;
fprintf(output, "else {\n");
need_right_curly++;
}
code_for_guess_block(t, &guess_block_in_prev_alt);
TAB;
fprintf(output, "if (");
/* To prevent/detect infinite recursion, ensure 'visited' flag is set
* on node starting this alt
*/
start_state->visited = 1;
start_state->lookahead = gen_prediction_expr(t, start_state->p1);
start_state->visited = 0;
fprintf(output, " ) {\n");
tabs++;
gen_alt(t);
tabs--; TAB;
fprintf(output, "}\n");
t = t->right; /* move to next alt in AST */
start_state = start_state->p2; /* move to next alt in GLA */
}
switch ( block_type ) {
case OPT :
case CLOSURE :
follow = q->start_state->p2;
break;
case POS_CLOSURE :
follow = q->start_state->next;
}
if ( block_type == OPT || block_type == CLOSURE || block_type == POS_CLOSURE )
{
TAB;
fprintf(output, "else {\n");
need_right_curly++;
TAB;
fprintf(output, "if (");
/* what follows the block? */
q->start_state->visited = 1;
q->start_state->lookahead = gen_prediction_expr(NULL, follow);
q->start_state->visited = 0;
fprintf(output, " ) {\n");
if ( block_type != OPT )
{
tabs++; TAB;
fprintf(output, "_done = 1;\n");
tabs--;
}
TAB;
fprintf(output, "}\n");
}
/* Generate error clause */
TAB;
fprintf(output, "else {\n");
/* generate the _GUESS_FAIL even if no (..)? found because calling
* routine may be using STreeTest()
*/
tabs++;
TAB;
if ( GenCPP ) fprintf(output, "if ( guessing ) _GUESS_FAIL;\n");
else fprintf(output, "if ( _parser->guessing ) _GUESS_FAIL;\n");
TAB;
if ( GenCPP ) fprintf(output, "no_viable_alt(\"%s\", _t);\n", current_rule);
else fprintf(output, "no_viable_alt(_parser, \"%s\", _t);\n", current_rule);
tabs--;
TAB;
fprintf(output, "}\n");
if ( transform ) { TAB; fprintf(output, " _tresult = _r;\n"); }
for (;need_right_curly>0; need_right_curly--)
{
TAB;
fprintf(output, "}\n");
}
switch ( block_type ) {
case BLOCK :
break;
case CLOSURE :
tabs--;
TAB; fprintf(output, "}\n");
/* if ( transform ) fprintf(output, " _tresult = _r;\n"); */
TAB; fprintf(output, "}\n");
break;
case POS_CLOSURE :
tabs--;
TAB;
fprintf(output, "} while ( !_done );\n");
/* if ( transform ) { TAB; fprintf(output, " _tresult = _r;\n"); } */
TAB;
fprintf(output, "}\n");
break;
case PRED_OP :
TAB;
fprintf(output, "_RESTORE;\n");
/* if ( transform ) { TAB; fprintf(output, " _tresult = _r;\n"); } */
TAB; fprintf(output, "}\n");
TAB; fprintf(output, "_GUESS_DONE;\n");
break;
}
test_block_consistency(q, block_type);
}
void
#ifdef __USE_PROTOS
gen_alt( AST *t )
#else
gen_alt( t )
AST *t;
#endif
{
require(t!=NULL && t->token==ALT, "gen_alt: invalid alt");
t = t->down;
if ( t==NULL ) return;
if ( t->token==Action ) t->init_action = 1;
gen_tree_pattern(t);
/* find last element of alternative to see if it's a simple token */
while ( t->right!=NULL ) { t = t->right; }
if ( t->down==NULL && (t->token == Token || t->token == WILD) )
{ TAB; go_right(1); }
}
void
#ifdef __USE_PROTOS
gen_tree_pattern( AST *t )
#else
gen_tree_pattern( t )
AST *t;
#endif
{
while ( t != NULL )
{
/* could be root of a tree, check it */
if ( t->down != NULL && (t->token==Token||t->token==WILD) ) {
TAB;
fprintf(output, "{_SAVE; TREE_CONSTR_PTRS;\n");
}
gen_element(t);
if ( t->down != NULL ) {
if ( t->token == Token || t->token==WILD )
{
gen_tree_pattern(t->down); /* only token/wildcard can be root of tree */
TAB;
fprintf(output, "_RESTORE;");
if ( transform ) fprintf(output, " _tresult = _r;");
fprintf(output, "\n");
TAB; fprintf(output, "}\n");
/* link in result of #(...) */
if ( transform && !whichRule->no_copy ) {
TAB; fprintf(output, "_mkchild(&_r,&_s,&_e,_tresult);\n");
}
TAB; go_right(1);
}
}
t = t->right;
}
}
void
#ifdef __USE_PROTOS
gen_element( AST *t )
#else
gen_element( t )
AST *t;
#endif
{
char *res;
require(t!=NULL, "gen_element: NULL tree pointer");
switch ( t->token )
{
case Token :
TAB;
if ( t->upper_range!=0 )
fprintf(output, "_MATCHRANGE(%s,%s);",
t->text, token_dict[t->upper_range]);
else fprintf(output, "_MATCH(%s);", t->text);
fprintf(output, "\n");
/* Make copy of token if transform && (copy or (labeled&&!copy)) */
if ( transform && (t->label[0]!='\0'||!t->no_copy) ) {
TAB;
if ( GenCPP )
fprintf(output, "_tresult=_t->shallowCopy();\n");
else
fprintf(output, "_tresult=ast_dup_node(_t);\n");
}
if ( transform && !t->no_copy ) {
if ( t->is_root )
fprintf(output, " _mkroot(&_r,&_s,&_e,_tresult);\n");
else
fprintf(output, " _mkchild(&_r,&_s,&_e,_tresult);\n");
}
/* Do Label if any */
if ( transform ) { /* label is output, label_in is input */
if ( t->label[0]!='\0' )
{
TAB;
fprintf(output,
"%s=(SORAST *)_tresult; %s_in=(SORAST *)_t;\n",
t->label,t->label);
}
} else {
if ( t->label[0]!='\0' )
{ TAB; fprintf(output, "%s=(SORAST *)_t;\n", t->label); }
}
/* Move tree parser pointer */
if ( t->down != NULL ) { TAB; go_down(1); }
else if ( t->right != NULL ) { TAB; go_right(1); }
break;
case WILD :
TAB;
fprintf(output, "_WILDCARD;");
/* Make copy of token or tree if transform */
if ( transform ) {
TAB;
if ( GenCPP )
fprintf(output, "_tresult=_t->deepCopy();");
else
fprintf(output, "_tresult=ast_dup(_t);");
/* wildcard can't be root, must be child */
if ( !t->no_copy ) {
if ( t->is_root )
fprintf(output, " _mkroot(&_r,&_s,&_e,_tresult);");
else
fprintf(output, " _mkchild(&_r,&_s,&_e,_tresult);");
}
}
fprintf(output, "\n");
if ( transform ) {
if ( t->label[0]!='\0' )
{
TAB;
fprintf(output,
"%s=(SORAST *)_tresult; %s_in=(SORAST *)_t;\n",
t->label,t->label);
}
} else {
if ( t->label[0]!='\0' )
{ TAB; fprintf(output, "%s=(SORAST *)_t;\n", t->label); }
}
if ( t->down != NULL ) { TAB; go_down(1); }
else if ( t->right != NULL ) { TAB; go_right(1); }
break;
case NonTerm :
TAB;
/* For nontransform mode, do labels first */
if (t->label[0]!='\0')
fprintf(output, "%s=(SORAST *)_t; ", t->label);
if ( t->out ) {
if ( t->in ) fprintf(output, "%s=", t->down->right->text);
else fprintf(output, "%s=", t->down->text);
}
fprintf(output, "%s%s", Prefix, t->text);
if ( transform ) res = ", &_tresult"; else res = "";
if ( GenCPP ) {
if ( t->in ) fprintf(output, "(&_t%s, %s);",
res, t->down->text);
else fprintf(output, "(&_t%s);", res);
}
else {
if ( t->in ) fprintf(output, "(_parser, &_t%s, %s);",
res, t->down->text);
else fprintf(output, "(_parser, &_t%s);", res);
}
fprintf(output, "\n");
if (transform && t->label[0]!='\0')
{
TAB;
fprintf(output, "%s=(SORAST *)_tresult;\n", t->label);
}
/* Link in result of rule */
if ( transform&&!t->no_copy ) {
TAB;
fprintf(output, "_mkchild(&_r,&_s,&_e,_tresult);\n");
}
break;
case Action :
if ( !t->init_action && found_guess_block ) {
TAB;
if ( GenCPP ) fprintf(output, "if ( !guessing ) {\n");
else fprintf(output, "if ( !_parser->guessing ) {\n");
}
dumpAction(t->action, output, tabs, 0, 0, 1);
if ( !t->init_action && found_guess_block ) {TAB; fprintf(output, "}\n");}
break;
case CLOSURE :
gen_block(t->down, CLOSURE);
break;
case POS_CLOSURE :
gen_block(t->down, POS_CLOSURE);
break;
case OPT :
gen_block(t->down, OPT);
break;
case BLOCK :
gen_block(t, BLOCK);
break;
case PRED_OP :
require(t->up!=NULL, "define_labels_in_element: GLA is broken");
if ( t->up->down==t ) {
if ( t->down->token == BLOCK ) gen_block(t->down, PRED_OP);
}
else if ( t->up->down->token==Action && t->up->down->right==t ) {
if ( t->down->token == BLOCK ) gen_block(t->down, PRED_OP);
}
else {
warnFL("predicate not at beginning of alternative; ignored",
FileStr[t->file], t->line);
}
break;
default :
fatal(eMsgd("invalid elemental node type: %d", t->token));
}
}
/* walk the block of a rule and define all labels to be "SORAST *label_i" */
void
#ifdef __USE_PROTOS
define_labels_in_block( AST *t )
#else
define_labels_in_block( t )
AST *t;
#endif
{
require(t!=NULL, "define_labels_in_block: NULL tree pointer");
require(t->token==BLOCK, "define_labels_in_block: invalid block");
t = t->down;
while ( t!=NULL )
{
define_labels_in_alt(t);
t = t->right;
}
}
void
#ifdef __USE_PROTOS
define_labels_in_alt( AST *t )
#else
define_labels_in_alt( t )
AST *t;
#endif
{
require(t!=NULL, "define_labels_in_alt: NULL tree pointer");
require(t->token==ALT, "gen_alt: invalid alt");
define_labels_in_tree(t->down);
}
void
#ifdef __USE_PROTOS
define_labels_in_tree( AST *t )
#else
define_labels_in_tree( t )
AST *t;
#endif
{
while ( t != NULL )
{
define_labels_in_element(t);
/* could be root of a tree, check it */
if ( t->down != NULL ) {
if ( t->token == Token || t->token==WILD )
{
define_labels_in_tree(t->down);
}
}
t = t->right;
}
}
void
#ifdef __USE_PROTOS
define_labels_in_element( AST *t )
#else
define_labels_in_element( t )
AST *t;
#endif
{
require(t!=NULL, "define_labels_in_element: NULL tree pointer");
switch ( t->token )
{
case Token :
case WILD :
case NonTerm :
if ( t->label[0]!='\0' ) {
SymEntry *s;
s = (SymEntry *) hash_get(symbols, t->label);
require(s!=NULL, "define_labels_in_element: sym tab broken");
if ( s->token==LABEL && !s->defined ) {
s->defined = 1;
TAB;
fprintf(output, "SORAST *%s=NULL", t->label);
if ( transform ) fprintf(output, ",*%s_in=NULL", t->label);
fprintf(output, ";\n");
/* track which ones we define so that we can undefine
* them for the next rule
*/
list_add(&labels_for_func, (void *)s);
}
}
break;
case Action :
break;
case CLOSURE :
case POS_CLOSURE :
define_labels_in_block(t->down);
break;
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?