使用LALR从单词列表中解析可选关键字的语法规则



我有这样的字符串:

  • "ABC其他一些东西;(通常开头有一个短字母组合(
  • "一些其他的东西";(有时没有什么有趣的(
  • "HFG54一些其它的东西;(有时会有一个有趣的数字(
  • "HFG54ZZ一些其他的东西,甚至更多";(有时数字后面有ZZ(
  • "HFG-54ZZ一些其他的东西,甚至更多";(有时还有破折号(
  • "ZT一些其他的东西";(其余部分也可以大写(
  • "(ZT(一些其他的东西";(零件可以放在括号中(
  • "68其他一些东西";(只能有一个数字(
  • "一些其它的东西DFG";(可以在末尾(

我制定了一些规则来解析它,使用larks Early解析器可以很好地工作。现在我想用LalrParser试试,但后来特殊的单词无法识别。我对大写字母组合和数字感兴趣。我有一张可能的字母组合表。数字总是两位数。绳子的其余部分可以是任何东西。

我在用百灵鸟。这是我的解析器:

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解析器来解析它?

尝试一下:

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,只是不明确。你可能会继续破解语法/REST正则表达式以使其工作,但它不会很漂亮。(

最新更新