Jison:当if-else和for语句结合在一起时,语法冲突



我想用jison为JavaScript语言的一个子集制作一个解析器,但我遇到了一些问题。

起初,我对非终端stmt有这样的定义,它很有效:

stmt
    : FOR LPAREN varlist_decl SEMICOLON expr SEMICOLON expr RPAREN stmt
        {$$ = ['for ('].concat($3, ['; '], $5, ['; '], $7, [') '], $9)}
    | varlist_decl 
        {$$ = $1}
    | expr
        {$$ = $1}
    | LBRACE stmts RBRACE
        {$$ = ['{', 0, 1].concat($2, [0, -1, '}'])}
    ;

之后,我在stmt中添加了以下规则:

    : IF LPAREN expr RPAREN stmt
        {$$ = ['if ('].concat($3, [') '], $5)}
    | IF LPAREN expr RPAREN stmt ELSE stmt
        {$$ = ['if ('].concat($3, [') '], $5, [0, 'else '], $7)}

这种语法含糊不清,而且会出现冲突。因此,我遵循以下模式来解决悬而未决的其他歧义:

stmt
    : IF LPAREN expr RPAREN stmt
    | IF LPAREN expr RPAREN stmt ELSE stmt
    | other_stmt
    ;

必须将其转化为:stmt:closed_stmt|非闭合stmt;

closed_stmt
    : IF LPAREN expr RPAREN closed_stmt ELSE closed_stmt
    | other_stmt
    ;
non_closed_stmt
    : IF LPAREN expr RPAREN stmt
    | IF LPAREN expr RPAREN closed_stmt ELSE non_closed_stmt
    ;

这是我语法的当前部分:

stmt
    : closed_stmt
        {$$ = $1}
    | non_closed_stmt
        {$$ = $1}
    ;
closed_stmt
    : IF LPAREN expr RPAREN closed_stmt ELSE closed_stmt
        {$$ = ['if ('].concat($3, [') '], $5, [0, 'else '], $7)}
    | FOR LPAREN varlist_decl SEMICOLON expr SEMICOLON expr RPAREN stmt
        {$$ = ['for ('].concat($3, ['; '], $5, ['; '], $7, [') '], $9)}
    | varlist_decl 
        {$$ = $1}
    | expr
        {$$ = $1}
    | LBRACE stmts RBRACE
        {$$ = ['{', 0, 1].concat($2, [0, -1, '}'])}
    ;
non_closed_stmt
    : IF LPAREN expr RPAREN stmt
        {$$ = ['if ('].concat($3, [') '], $5)}
    | IF LPAREN expr RPAREN closed_stmt ELSE non_closed_stmt
        {$$ = ['if ('].concat($3, [') '], $5, [0, 'else '], $7)}
    ;

并且这部分仅在我评论CCD_ 3规则时起作用。

你是怎么修的?

这是我的完整代码库:https://github.com/xgbuils/if-for-grammar-issue

您需要for语句的闭合和非闭合形式;它不能仅仅以CCD_ 5结束。因此,在closed_stmt规则中放置了一个以closed_stmt结尾的闭合形式,并在non_closed_stmt规则中放置一个以non_closed_stmt结尾的非闭合形式。

那是因为

for (x=0;x<3;++x) if (x==2) do_something();

和一样不关闭

if (x==2) do_something();

在其将吸收随后的CCD_ 10令牌的意义上。if语句的封闭性不会通过在其前面加一个(或多个)for标头来改变。

相关内容

  • 没有找到相关文章

最新更新