0

我有这样的字串:

  • “ABC Some other stuff”(通常开头有一个短字母组合)
  • “一些其他的东西”(有时没有什么有趣的)
  • “HFG 54 Some other stuff and even more”(有时有一个有趣的数字)
  • “HFG 54 ZZ Some other stuff and even more”(有时在数字后面有 ZZ)
  • “HFG-54 ZZ 一些其他的东西,甚至更多”(有时会有破折号)
  • “ZT SOME OTHER STUFF”(其余部分也可以大写)
  • "(ZT) Some other stuff" (部分可以在括号中)
  • “68 Some other stuff”(只能是数字)
  • “其他一些东西 DFG”(可以在最后)

我制定了一些规则来解析它,并且使用 larks Early-parser 可以正常工作。现在我想用 Lalr-Parser 试一试,但特殊词无法识别。我对大写字母组合和数字感兴趣。我有一个可能的字母组合列表。数字总是两位数。字符串的其余部分可以是任何东西。

我正在使用云雀。这是我的解析器:

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 语言。如果有人添加并回答快速解释这两者的地方,我会很高兴。

4

1 回答 1

1

问题是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"不起作用。它需要HFGas REST,然后尝试解析54它可以解析的内容,因为它不是REST并且它现在不期望 a NUM


如果这是您语法的完整扩展,使用earley,或者甚至比 lalr 提供的速度更快,一个(或多个)正则表达式也可以很好地完成这项工作。

(注意,我说错了:这可能是一个 CFG,只是模棱两可。你可能会继续破解语法/REST正则表达式以使其工作,但它不会很漂亮。)

于 2020-12-17T10:09:25.783 回答