考虑一下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'
无效。我不明白为什么。错误消息是:
UnexpectedCharacters: No terminal defined for '{' at line 2 col 12
inner : {
这只是一个中景。我的实际语法也有同样的问题。你知道吗
LALR失败的原因是它的lookahead为1(不像Earley,它有无限的lookahead),并且它在
attribute_name
和string
之间混淆了。一旦它匹配了另一个规则(在本例中是attribute_name
),它就不可能回溯并匹配不同的规则。你知道吗如果您对属性名称终端使用较低的优先级,它将起作用。例如:
但建议的做法是,如果可能的话,对两者使用相同的终端,这样解析器就可以替您思考,而不是lexer。如果需要,可以在解析完成后添加额外的验证。你知道吗
这两种方法(更改优先级或合并终端)都可以解决您的问题。你知道吗
相关问题 更多 >
编程相关推荐