0

我正在制作一个应用程序,以使没有经验的人更容易理解和用户友好的编写(PEG)解析器。是的,它以前已经做过,但它对我来说是一个很好的关于 GUI 的学习经验。

使其平易近人的部分原因是用户不必担心他们的语法必须匹配整个文本,他们应该能够在没有所有“样板”的情况下提取有意义的数据。

如何做到这一点?请看下面我的回答。或者提供你自己的。

4

1 回答 1

1

这让我难过了一个晚上的大部分时间,并且无法在网上找到答案,所以我想分享一下。

我使用简约库的 MRE。它之所以有效,是因为 match 将匹配任何顶级用户定义的表达式,并且有一个匹配其他任何内容的回退,遗憾的是一次只能匹配一个字符。

from parsimonious.grammar import Grammar

grammar = Grammar("""
root = (match / any)*
match = foo / bar # must include all top level user defined rules, but not their children (if any)
any = ~"."
foo = "foo expression" # user defined
bar = "bar expression" # user defined
""")

print(grammar.match("1 foo expression 2 bar expression 3"))

并且打印出来是正确的。

<Node called "root" matching "1 foo expression 2 bar expression 3">
    <Node matching "1">
        <RegexNode called "any" matching "1">
    <Node matching " ">
        <RegexNode called "any" matching " ">
    <Node matching "foo expression">
        <Node called "match" matching "foo expression">
            <Node called "foo" matching "foo expression">
    <Node matching " ">
        <RegexNode called "any" matching " ">
    <Node matching "2">
        <RegexNode called "any" matching "2">
    <Node matching " ">
        <RegexNode called "any" matching " ">
    <Node matching "bar expression">
        <Node called "match" matching "bar expression">
            <Node called "bar" matching "bar expression">
    <Node matching " ">
        <RegexNode called "any" matching " ">
    <Node matching "3">
        <RegexNode called "any" matching "3">

老实说,我觉得这不是很优雅,尤其是单个字符如何匹配“any”和“root”(如果它们在一起或完全省略,我会更喜欢),但这是我能做的最好的事情,如果它对任何重要的人都有用!


Parsimonious 自述文件中有这样的例子。

my_grammar = Grammar(r"""
    styled_text = bold_text / italic_text
    bold_text   = "((" text "))"
    italic_text = "''" text "''"
    text        = ~"[A-Z 0-9]*"i
    """)

对我来说,这表明有一种方法可以在我不知道的更大的文本体(包含既不是粗体也不是斜体的文本)上使用它。除了在文档的每个位置上使用可选的“pos”(位置)参数进行解析/匹配之外,这也不优雅。

我从自述文件中看不到如何,如果有人知道“正确”的方式,请分享。

于 2021-03-03T20:47:25.393 回答