Lark如何描述一系列可选的token
Lark how to describe a series of optional tokens
我正在解析一个格式可以包括的文件:
INT32 price min 10 max 100 alertIfSold ;
min、max 和 alertIfSold 标记都是可选的,可以以任何顺序出现。即
INT32 price max 100 alertIfSold ;
INT32 price max 100 min 10 alertIfSold ;
INT32 price alertIfSold ;
INT32 price;
都是有效的例子。
下面是我正在测试的语法的简单版本。
运行 python test.py 生成此错误:
lark.common.ParseError: Infinite recursion detected! (rule
<__anon_star_1 : __anon_star_1>)
我试过使用其他语法规则表达相同的可选标记,结果相似(无限递归)。
表达可选参数的正确语法是什么?
#test.py
from lark import lark
simplified_grammar = """
start: line+
line: TYPE CNAME [MIN MAX ALERT]* ";" -> foo
TYPE: "INT32" | "INT64"
MIN: "min" /[0-9]+/
MAX: "max" /[0-9]+/
ALERT: "alertIfSold"
%import common.CNAME
%import common.WS
%ignore WS
"""
sample = """
INT32 price max 100 alertIfSold ;
INT32 price max 100 min 10 alertIfSold ;
INT32 price alertIfSold ;
INT32 price;
"""
parser = lark.Lark(simplified_grammar)
def main():
parse_tree = parser.parse(sample)
if __name__ == '__main__':
main()
你想要:
line: TYPE CNAME (MIN | MAX | ALERT)* ";" -> foo
(注意:()
而不是 []
。)
在lark的EBNF语法中,[item]
表示"an optional item
",item*
表示"any number (possibly zero) of item
"。所以 [item]*
意味着 "any number (possibly zero) of either item
or nothing"。但是 "any number of nothing" 是无限歧义的;你不知道一个空字符串中有多少个空值。
由于您实际上并不打算要求子句严格连续出现,您可能一直在考虑
line: TYPE CNAME ([MIN] [MAX] [ALERT])* ";" -> foo
那样会更准确,但也会产生相同的错误消息。通常,您不能在可空子模式上使用 Kleene 星号。一些 EBNF 生成器将通过从重复集中删除 ε 来纠正这一点(然后将重复作为一个整体作为可选),但百灵鸟不是其中之一。在这种情况下,修复是微不足道的,但在其他情况下更令人讨厌。
作为正则表达式,(a* b*)*
、(a? b?)*
和 (a|b)*
在识别同一种语言的意义上是等价的。但是正则表达式是出了名的歧义,解析器通常更喜欢无歧义的语法,或者最坏的情况是有限歧义的语法。只有最后一个正则表达式属于该类别,它是您通常应该喜欢的形式。
我正在解析一个格式可以包括的文件:
INT32 price min 10 max 100 alertIfSold ;
min、max 和 alertIfSold 标记都是可选的,可以以任何顺序出现。即
INT32 price max 100 alertIfSold ;
INT32 price max 100 min 10 alertIfSold ;
INT32 price alertIfSold ;
INT32 price;
都是有效的例子。
下面是我正在测试的语法的简单版本。 运行 python test.py 生成此错误:
lark.common.ParseError: Infinite recursion detected! (rule <__anon_star_1 : __anon_star_1>)
我试过使用其他语法规则表达相同的可选标记,结果相似(无限递归)。
表达可选参数的正确语法是什么?
#test.py
from lark import lark
simplified_grammar = """
start: line+
line: TYPE CNAME [MIN MAX ALERT]* ";" -> foo
TYPE: "INT32" | "INT64"
MIN: "min" /[0-9]+/
MAX: "max" /[0-9]+/
ALERT: "alertIfSold"
%import common.CNAME
%import common.WS
%ignore WS
"""
sample = """
INT32 price max 100 alertIfSold ;
INT32 price max 100 min 10 alertIfSold ;
INT32 price alertIfSold ;
INT32 price;
"""
parser = lark.Lark(simplified_grammar)
def main():
parse_tree = parser.parse(sample)
if __name__ == '__main__':
main()
你想要:
line: TYPE CNAME (MIN | MAX | ALERT)* ";" -> foo
(注意:()
而不是 []
。)
在lark的EBNF语法中,[item]
表示"an optional item
",item*
表示"any number (possibly zero) of item
"。所以 [item]*
意味着 "any number (possibly zero) of either item
or nothing"。但是 "any number of nothing" 是无限歧义的;你不知道一个空字符串中有多少个空值。
由于您实际上并不打算要求子句严格连续出现,您可能一直在考虑
line: TYPE CNAME ([MIN] [MAX] [ALERT])* ";" -> foo
那样会更准确,但也会产生相同的错误消息。通常,您不能在可空子模式上使用 Kleene 星号。一些 EBNF 生成器将通过从重复集中删除 ε 来纠正这一点(然后将重复作为一个整体作为可选),但百灵鸟不是其中之一。在这种情况下,修复是微不足道的,但在其他情况下更令人讨厌。
作为正则表达式,(a* b*)*
、(a? b?)*
和 (a|b)*
在识别同一种语言的意义上是等价的。但是正则表达式是出了名的歧义,解析器通常更喜欢无歧义的语法,或者最坏的情况是有限歧义的语法。只有最后一个正则表达式属于该类别,它是您通常应该喜欢的形式。