Bison 在递归规则中组合相似的构造

Bison 在递归规则中组合相似的构造,bison,jison,Bison,Jison,这适用于Jison中的解析器,但我想Bison也是如此 我有一个对表达式有定义的规则 expr : NUMBER -> { type: "number", value: $1 } | "(" expr ")" -> $2 | expr "+" expr -> { type: "+", left: $1, right: $3 } | expr "-" expr -> { type: "-", left: $1, right: $3 }

这适用于Jison中的解析器,但我想Bison也是如此

我有一个对表达式有定义的规则

expr
    : NUMBER -> { type: "number", value: $1 }
    | "(" expr ")" -> $2
    | expr "+" expr -> { type: "+", left: $1, right: $3 }
    | expr "-" expr -> { type: "-", left: $1, right: $3 }
    | expr "*" expr -> { type: "*", left: $1, right: $3 }
    | expr "/" expr -> { type: "/", left: $1, right: $3 }
    ;
在相同的语法中,我还有一个“过滤器表达式”规则,它也支持“参数”

这是可行的,但当我添加操作符时,我必须更改这两个定义。有没有一种方法可以将语法中“expr”和“filterExpr”的公共部分结合起来?

Javascript本身(正式的ECMAScript,由ECMA-262定义)使用BNF的扩展来描述,该扩展允许使用布尔限定符(“标准语言中的参数”)来扩充规则。这正是您想要的效果,它明显简化了该语言复杂语法的表示。有关BNF扩展的完整说明,请参见本标准的附录;总之,参数可以从左侧传递到右侧的非端子,也可以为RHS端子显式设置或取消设置;此外,它们可以用于根据参数的存在或不存在来过滤可能的产品。(本文末尾有一个例子。)

这种特殊的BNF扩展不会给BNF增加任何发电能力;它的所有用途都可以通过简单地列举可能性来机械地消除。遗憾的是,据我所知,没有实现这种形式的语法生成器(尽管某些Javascript实现可能包含自定义解析器生成器)

出于您的目的,可以很容易地预处理jison语法以实现非常类似的东西。实际上,预处理bison语法文件相对容易,但使用jison更容易,因为您可以通过编程方式计算语法并将其作为JSON对象传递给jison。此功能没有很好的文档记录,但jison手册包含足够的示例,应该直接使用。例如,请参见


正如所承诺的,下面是ECMA-262语法的一个摘录,它展示了这个BNF扩展的使用:

IdentifierReference
可以使用两个可能的布尔限定符(
Yield
Await
)限定,从而产生四种可能性。它可以始终是一个
标识符
;仅当未使用
yield
属性限定时,它可以是关键字
yield
,或者仅当未使用
wait
限定时,它可以是关键字
wait

IdentifierReference[Yield, Await]:
    Identifier
    [~Yield]yield
    [~Await]await
yield
表达式仅允许在
AssignmentExpression
的变体中使用
yield
限定:

AssignmentExpression[In, Yield, Await]:
    ConditionalExpression[?In, ?Yield, ?Await]
    [+Yield]YieldExpression[?In, ?Await]

上述复杂性的很大一部分是因为坚持向后兼容:因为为早期JS版本编写的程序可能使用了
yield
await
作为变量名,这些关键字只保留在早期版本中不可用的语法上下文中。(这太简单了,但细节远远超出了这个问题的范围。)

长话短说,简单的Jison是不可能的,需要对语法进行自定义预处理吗?@rveerd:是的,就是这样。但是对于bison来说,定制的预处理可能足够简单,值得一试。
IdentifierReference: Identfier | yield | await
IdentifierReference_Yield: Identifier | await
IdentifierReference_Await: Identifier | yield
IdentifierReference_Yield_Await: Identifier
Expression[In, Yield, Await]:
    AssignmentExpression[?In, ?Yield, ?Await]
    Expression[?In, ?Yield, ?Await] , AssignmentExpression[?In, ?Yield, ?Await]
AssignmentExpression[In, Yield, Await]:
    ConditionalExpression[?In, ?Yield, ?Await]
    [+Yield]YieldExpression[?In, ?Await]
GeneratorMethod[Yield, Await]:
    * PropertyName[?Yield, ?Await] ( UniqueFormalParameters[+Yield, ~Await] ) { GeneratorBody }

GeneratorBody:
    FunctionBody[+Yield, ~Await]