我正在Bison中为一种语言编写解析器,该语言具有以下结构:
identifier
arguments
] expression
。 identifier
arguments
] expression
[expression
,expression
] - 与Python类似。 arguments
是逗号分隔的表达式列表,也可以为空。以上所有内容也都是表达式。
我的问题是,我不确定如何解析[method [other_method]]
和[someString[idx1, idx2].toInt]
,或者是否可以使用LALR(1)解析器完成此操作。
更准确地说,让我们采用以下示例:[a[b]]
(使用方法a
的结果调用方法b
。当它到达状态[a
时。 [b]]
(前瞻是第二个[
),它不知道是否将a
(已经减少到identifier
)减少到expression
因为a[b,c]
之类的内容可能会跟随(它本身可以缩减为expression
并继续使用上面的第二个结构)或保留identifier
(并转移它),因为arguments
列表{ {1}}将会跟随(例如,在这种情况下为[b]
)。
这种转移/减少冲突是由于我表达这种语法的方式还是不可能用LALR(1)解析器解析所有这些结构?
而且,更一般的问题是,如何证明某种语言不能被特定类型的解析器解析?
答案 0 :(得分:2)
假设您的语法是明确的(您描述的部分似乎是),那么您最好的选择是指定%glr-parser
。由于在大多数情况下,只需几个令牌就会强制执行正确的解析,因此开销不应太明显,并且优点是您不需要使语法或AST的构造复杂化。
一个缺点是,野牛无法验证语法是否明确 - 通常,这是不可能的 - 并且不容易证明。如果事实证明某些输入是不明确的,那么GLR解析器将产生错误,因此一个好的测试套件很重要。
证明语言不是LR(1)会很棘手,我怀疑它是不可能的,因为语言可能是可识别的与LALR(1)解析器。 (但是不可能在没有看到整个语法的情况下告诉。)但是解析(在CS理论之外)需要创建一个正确的解析树才能有用,并且产生LR语法所需的那种修改也将修改AST ,需要一个解析后的修正。
之间的优先级差异难以创建正确的AST弹簧a[b[c],d]
和
[a[b[c],d]]
在第一个(子集)的情况下,b
绑定到其参数列表[c]
,并且逗号的优先级较低;最后,b[c]
和d
是切片的兄弟姐妹。在第二种情况(方法调用)中,逗号是参数列表的一部分,并且绑定比方法应用程序更紧密; b
,[c]
和d
是方法应用程序中的兄弟姐妹。但是你无法决定解析树的形状,直到任意长的输入(因为d
可以是任何表达式)。
由于“优先级”不能正式定义,所以有点手动,并且有一些黑客可以调整树。由于LR属性不是真正可组合的,因此可以提供更严格的分析。但无论如何,GLR解析器可能是最简单和最强大的解决方案。
未来参考的一个小问题:CFG不仅仅是一种编程工具;它们还有助于清楚地传达有关语法。 Nirmally,如果你想描述你的语言,你最好使用一个明确的CFG,而不是试图非正式地描述。当然,有意义的非终端名称会有所帮助,而且一些例子从未受到伤害,但语法的本质在于正式描述和省略,这使得其他人更难以“有所帮助”。