云雀解析器语法适用于Earley,但不适用于LALR

时间:2019-05-23 11:55:37

标签: python parsing lark-parser

考虑对Python Lark parser进行以下简单测试:

GRAMMAR = '''
start: container*

container: string ":" "{" (container | attribute | attribute_value)* "}"
attribute: attribute_name "=" (attribute_value | container)
attribute_value: string ":" _value ("," _value)*
_value: number | string

attribute_name: /[A-Za-z_][A-Za-z_#0-9]*/

string: /[A-Za-z_#0-9]+/
number: /[0-9]+/

    %import common.WS
    %ignore WS
'''

data = '''outer : {
 inner : {
 }
}'''

parser = Lark(GRAMMAR, parser='lalr')
parser.parse(data)

此方法适用于parser='earley',但不适用于parser='lalr'。我不明白为什么。错误消息是:

  

意外字符:在第2行第12行没有为'{'定义终端      

内部:{

这只是MWE。我的实际语法也遇到同样的问题。

1 个答案:

答案 0 :(得分:1)

LALR失败的原因是,其前瞻性为1(与Earley不同,后者具有无限前瞻性),并且在dt.Columns.Add("Column",GetType("Etc"))attribute_name之间感到困惑。一旦它与另一个(在本例中为string)匹配,就不可能回溯并匹配另一个规则。

如果为attribute_name终端使用较低的优先级,则它将起作用。例如:

attribute_name

但是,推荐的做法是,如果可能的话,对两者都使用相同的终端,以便解析器可以代替词法分析器为您做思考。解析完成后,您可以根据需要添加额外的验证。

两种方法(更改优先级或合并终端)都可以解决您的问题。