我正在尝试通过Jison为JavaScript ChucK生成一个JavaScript解析器,并且已经开始了一个良好的开端,除了生成的解析器无法处理的语言含糊不清。最初的ChucK编译器是由Bison生成的,必须能以某种方式解决这些歧义。
出于这个问题的目的,我已经将问题简化为解释性语法,该语法只呈现一个模糊性。作为参考,我已经提供了gist所有涉及的文件(包括生成的parser)。项目结构如下:
generate
)。Type var => out;
。语法本身如下:
grammar = {
Program: [
['ProgramSection', '$$ = new yy.Program($1);']
],
ProgramSection: [
['Expression SEMICOLON', '$$ = new yy.ExpressionStatement($1);']
],
Expression: [
['DeclExpression', '$$ = $1;'],
['Expression OP DeclExpression', '$$ = new yy.ExpFromBinary($1, $2, $3);']
],
DeclExpression: [
['TypeDecl VarDeclList', '$$ = new yy.DeclExp($1, $2, 0);'],
['PrimaryExpression', '$$ = $1;']
],
VarDeclList: [
['VarDecl', '$$ = new yy.VarDeclList($1);']
],
VarDecl: [
['ID', '$$ = new yy.VarDecl($1);']
],
TypeDecl: [
['ID', '$$ = new yy.TypeDecl(new yy.IdList($1), 0);']
],
PrimaryExpression: [
['ID', '$$ = new yy.ExpFromId($1);']
]
};
不明确的是,非终端DeclExpression可以匹配TypeDecl VarDeclList
或PrimaryExpression
。这使得Jison发出以下警告:
States with conflicts:
State 7
TypeDecl -> ID . #lookaheads= ID SEMICOLON OP
PrimaryExpression -> ID . #lookaheads= ID SEMICOLON OP
生成的解析器无法解析测试代码(Type var => out;
),如下所示:
Error: Parse error on line 1: Unexpected 'SEMICOLON'
根据我的理解,它是=>
运算符之后解析器尝试与规则TypeDecl VarDeclList
匹配的部分。
那么,我怎样才能生成一个能够处理这种歧义的解析器呢?
答案 0 :(得分:1)
您的语法不能与LALR(1)解析器一起使用的原因是因为DeclExpression
和TypeDecl
上的PrimaryExpression
状态的LALR(1)解析器不明确} 状态。
让我试着解释一下。如错误消息所述,解析器检测到TypeDecl
和PrimaryExpression
上的冲突。两者都有ID作为标记,但由于LALR(1)解析器只能在前面看一个标记,这意味着解析器在DeclExpression
状态时不知道该做什么。另一方面,SLR有一种动态的外观,可以牺牲一些记忆来解决冲突。
如果你想让它在LALR(1)解析器上工作,只需将你的DeclExpression
规则重构为ID VarDeclList | ID
,这样解析器就不必看起来像一个头为了找到正确的规则。
答案 1 :(得分:0)
我发现通过选择'slr'(SLR)或'lr'(LR1)解析器类型,我可以为这个(简化的)语法生成一个函数解析器:
// Generate SLR parser, since default LALR has conflicts
exports.generate = new Parser(parserConfig, {type: "slr"}).generate;
我仍然想知道为什么默认值(LALR(1))不起作用,因为这应该是Bison生成的。