我想使用 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)}
该语法有二义性并且出现冲突。所以我遵循这些模式来解决悬空的 else 歧义:
stmt
: IF LPAREN expr RPAREN stmt
| IF LPAREN expr RPAREN stmt ELSE stmt
| other_stmt
;
它必须转换为: 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)}
;
这部分仅在我注释 for-statement
规则时才起作用。
如何解决这个问题?
这是我的完整代码存储库:https://github.com/xgbuils/if-for-grammar-issue
最佳答案
您需要 for
语句的封闭式和非封闭式;它不能只是以 stmt
结尾。因此,您可以在 lined_stmt
规则中放置一个以 lined_stmt
结尾的封闭形式,并在 non_angled_stmt 规则中放置一个以
规则。non_angled_stmt
结尾的非封闭形式。
那是因为
for (x=0;x<3;++x) if (x==2) do_something();
与非闭合一样
if (x==2) do_something();
从某种意义上说,它将吸收后面的else
标记。 if
语句的封闭性不会因在其前面添加一个(或多个)for
header 而改变。
关于javascript - Jison:if-else 和 for 语句 ara 组合时的语法冲突,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26026881/