使用 LALR 从单词列表中解析可选关键字的语法规则
Grammar rules for parsing optional keywords from list of words with LALR
我有这样的字符串:
- “ABC Some other stuff”(通常开头有一个短字母组合)
- “一些其他的东西”(有时没有什么有趣的)
- “HFG 54 一些其他东西甚至更多”(有时会有一个有趣的数字)
- “HFG 54 ZZ 一些其他东西甚至更多”(有时数字后面有 ZZ)
- “HFG-54 ZZ 一些其他东西甚至更多”(有时会有破折号)
- “ZT SOME OTHER STUFF”(其余部分也可以大写)
- "(ZT) Some other stuff" (括号内可以)
- "68 Some other stuff" (只能有一个数字)
- “一些其他东西 DFG”(可以放在最后)
我制定了一些规则来解析它,并且使用百灵鸟早期解析器它工作正常。现在我想用 Lalr-Parser 尝试一下,但是特殊的词无法识别。
我对大写字母组合和数字感兴趣。我有一个可能的字母组合列表。数字总是两位数。字符串的其余部分可以是任何内容。
我正在使用 lark。
这是我的解析器:
from lark import Lark
tryoutabc = Lark(r"""
start: mat_all_and_restl
?mat_all_and_restl: mat_all restl | restl | restl mat_br
restl: REST*
?mat_all: mat_br| mat_num| num
mat_num: mat_br ("-")? NUM
?num: NUM ("ZZ")?
NUM: /\d{2}/
?mat_br: "("? MAT ")"?
MAT: "ABC"
| "HFG"
| "ZT"
| "DFG"
REST: /([\-])?[A-Za-zÜ]+([\/.][A-Za-zÜ]+)?/
%import common.WS
%ignore WS
""", start='start', parser='lalr') #remove "parser='lalr'" and the results are right
我该如何更改规则才能使 lalr-parser 能够解析它?
尝试一下:
textl = ["ABC SOME OTHER STUFF", "Some other stuff", "HFG 54 Some other stuff and even more",
"HFG 54 ZZ Some other stuff and even more", "HFG-54 Some other stuff and even more", "ZT Some other stuff",
"(ZT) Some other stuff", "Some other stuff DFG", "Some other stuff (DFG)", "68 Some other stuff "]
for text in textl:
print(tryoutabc.parse(text).pretty())
我明白了
start
restl
ABC
SOME
OTHER
STUFF
但我想要
start
ABC
restl
SOME
OTHER
STUFF
对于 "HFG 54 Some other stuff and even more"
我得到一个错误:
HFG 54 Some other stuff and even more
^
Expecting: {'REST'}`
但我想要:
start
mat_num
HFG
54
restl
Some
other
stuff
and
even
more
实际上,字符串更长,看起来像这样“有趣的东西,我已经解析了 ABC 一些其他的东西”,我已经解析了字符串开头的东西,而且效果很好。
从评论来看,这似乎是不可能的,因为我这里没有上下文无关语言,显然 larl 只能使用 cfg 语言。如果有人补充并回答这两个都很快解释的地方,我会很高兴。
问题出在 REST
终端。它可以通过设计解析几乎任何东西,这意味着
start
mat_all_and_restl
ABC
restl
SOME
OTHER
STUFF
和
start
restl
ABC
SOME
OTHER
STUFF
都是第一个例句的有效解释 (ABC SOME OTHER STUFF
)。如果您将 ambiguity='explicit'
传递给 earley 解析器,您可以查看此内容。
此示例适用于 lalr
,因为如果 lalr
只是将所有内容解释为 REST
就没有问题,但它确实会给您错误的结果。
另一方面,有问题的示例 "HFG 54 Some other stuff and even more"
不起作用。它将 HFG
作为 REST
,然后尝试解析它可以解析的 54
,因为它不是 REST
并且它不期望 NUM
正确现在。
如果这是您语法的完整扩展,请使用 earley
,或者为了比 lalr 提供的速度更快,一个(或多个)正则表达式也可以很好地完成这项工作。
(请注意,我说错了:这可能是一个 CFG,只是模棱两可。您可能会继续破解 grammar/the REST
正则表达式以使其工作,但它不会漂亮。)
我有这样的字符串:
- “ABC Some other stuff”(通常开头有一个短字母组合)
- “一些其他的东西”(有时没有什么有趣的)
- “HFG 54 一些其他东西甚至更多”(有时会有一个有趣的数字)
- “HFG 54 ZZ 一些其他东西甚至更多”(有时数字后面有 ZZ)
- “HFG-54 ZZ 一些其他东西甚至更多”(有时会有破折号)
- “ZT SOME OTHER STUFF”(其余部分也可以大写)
- "(ZT) Some other stuff" (括号内可以)
- "68 Some other stuff" (只能有一个数字)
- “一些其他东西 DFG”(可以放在最后)
我制定了一些规则来解析它,并且使用百灵鸟早期解析器它工作正常。现在我想用 Lalr-Parser 尝试一下,但是特殊的词无法识别。 我对大写字母组合和数字感兴趣。我有一个可能的字母组合列表。数字总是两位数。字符串的其余部分可以是任何内容。
我正在使用 lark。 这是我的解析器:
from lark import Lark
tryoutabc = Lark(r"""
start: mat_all_and_restl
?mat_all_and_restl: mat_all restl | restl | restl mat_br
restl: REST*
?mat_all: mat_br| mat_num| num
mat_num: mat_br ("-")? NUM
?num: NUM ("ZZ")?
NUM: /\d{2}/
?mat_br: "("? MAT ")"?
MAT: "ABC"
| "HFG"
| "ZT"
| "DFG"
REST: /([\-])?[A-Za-zÜ]+([\/.][A-Za-zÜ]+)?/
%import common.WS
%ignore WS
""", start='start', parser='lalr') #remove "parser='lalr'" and the results are right
我该如何更改规则才能使 lalr-parser 能够解析它?
尝试一下:
textl = ["ABC SOME OTHER STUFF", "Some other stuff", "HFG 54 Some other stuff and even more",
"HFG 54 ZZ Some other stuff and even more", "HFG-54 Some other stuff and even more", "ZT Some other stuff",
"(ZT) Some other stuff", "Some other stuff DFG", "Some other stuff (DFG)", "68 Some other stuff "]
for text in textl:
print(tryoutabc.parse(text).pretty())
我明白了
start
restl
ABC
SOME
OTHER
STUFF
但我想要
start
ABC
restl
SOME
OTHER
STUFF
对于 "HFG 54 Some other stuff and even more"
我得到一个错误:
HFG 54 Some other stuff and even more
^
Expecting: {'REST'}`
但我想要:
start
mat_num
HFG
54
restl
Some
other
stuff
and
even
more
实际上,字符串更长,看起来像这样“有趣的东西,我已经解析了 ABC 一些其他的东西”,我已经解析了字符串开头的东西,而且效果很好。
从评论来看,这似乎是不可能的,因为我这里没有上下文无关语言,显然 larl 只能使用 cfg 语言。如果有人补充并回答这两个都很快解释的地方,我会很高兴。
问题出在 REST
终端。它可以通过设计解析几乎任何东西,这意味着
start
mat_all_and_restl
ABC
restl
SOME
OTHER
STUFF
和
start
restl
ABC
SOME
OTHER
STUFF
都是第一个例句的有效解释 (ABC SOME OTHER STUFF
)。如果您将 ambiguity='explicit'
传递给 earley 解析器,您可以查看此内容。
此示例适用于 lalr
,因为如果 lalr
只是将所有内容解释为 REST
就没有问题,但它确实会给您错误的结果。
另一方面,有问题的示例 "HFG 54 Some other stuff and even more"
不起作用。它将 HFG
作为 REST
,然后尝试解析它可以解析的 54
,因为它不是 REST
并且它不期望 NUM
正确现在。
如果这是您语法的完整扩展,请使用 earley
,或者为了比 lalr 提供的速度更快,一个(或多个)正则表达式也可以很好地完成这项工作。
(请注意,我说错了:这可能是一个 CFG,只是模棱两可。您可能会继续破解 grammar/the REST
正则表达式以使其工作,但它不会漂亮。)