我想用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 : closed_stmt | non_closed_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规则时才起作用。
你怎么解决它呢?
发布于 2014-09-25 13:25:29
您需要闭合和非闭合形式的for语句;它不能仅以stmt结尾。因此,在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();在某种意义上,它将吸收下面的else令牌。在if语句前面加上一个(或多个) for头不会改变该语句的封闭性。
https://stackoverflow.com/questions/26026881
复制相似问题