C语言 从中间/底部规则中最上面的规则中获取值



我正在做我自己的小语言,我试图让有块,但我非常困在如何跟踪当前块上(因为我需要知道变量是在哪个中创建的等等)。

我的语法文件看起来像这样(为了简单起见,它不是整个代码):

%{
    struct Node *nodest = NULL;
    struct Node *currentblock = NULL;
%}
%start source
%%
source
    : stmts { nodest = block($1); currentblock = nodest; }
    ;
stmts
    : stmt
    | stmts stmt
    ;
stmt
    : expr_stmt
    | iter_stmt
    | select_stmt
    | comp_stmt
    ;
expr_stmt
    : ';'
    | expr ';'
    ;
expr
    : binary_expr
    | assign_expr
    | call_expr
    | decl_expr
    | init_expr
    | VAR_IDENT
    | INTEGER
    | '(' expr ')'
    ;
comp_stmt
    : '{' '}'
    | '{' stmts '}' { $$ = block($2); currentblock = $$; }
    ;
decl_expr
    : type VAR_IDENT  { $$ = declaration($1, $2, currentblock) }
    ;
/* ... */
type
    : TYPE_INT
    ;

显然,这是行不通的,因为nodest(作为保存所有其他节点的块节点)实际上在创建 AST 的最后被赋予了一些值,因此它在其余时间都是 NULL,所以currentblock不能像在 decl_expr 中使用,因为它当时是 NULL。

所以我的问题是:我怎样才能在代码中稍后获取nodest的值(指向它指向的位置或其他什么)?

或者,如果真的不可能,你能给我一些关于如何做到这一点的笔记/提示吗?

规则中的操作代码在规则减少时执行,因此,如果您希望在流程的早期执行操作,则需要将它们放在较早减少的规则上。 yacc 和 bison 都允许您引入匿名 epsilon 规则,只需在规则的右侧前面放置一个额外的操作即可。 因此,您可以执行以下操作:

source: { $$ = currentblock = nodest = empty_block(); } stmts
        { $$ = add_to_block($1, $2); }
comp_stmt:
    '{' { $$ = currentblock = empty_block(); } stmts '}'
    { $$ = add_to_block($2, $3); }
;

请注意,当你像这样早期创建块时,你必须将它们创建为空(因为你还没有解析任何进入块的内容),然后稍后向它们添加内容。 在解析当前块时将每个 stmt 添加到当前块可能更有意义(在这种情况下,您需要确保当前块确实是当前块而不是最后一个块:

source: { currentblock = nodest = empty_block(); } stmts ;
stmts: /* empty*/
     | stmts stmt { add_to_block(currentblock, $2; }
comp_stmt:
    '{' { $$ = currentblock; currentblock = empty_block(); } stmts '}'
    { $$ = currentblock; currentblock = $2 }
;

最新更新