首页 > 解决方案 > Lark 解析器无法解析字符,即使它们是在规则的正则表达式中定义的

问题描述

我正在尝试编写一个 SMTP 解析器,并从rfc获取一些引用字符串的信息。所以我有以下语法(取出所有有效的部分,专注于无效的部分):

quoted_string  : /[\x22]/ qcontentsmtp* /[\x22]/
qcontentsmtp   : qtextsmtp | quoted_pairsmtp
quoted_pairsmtp  : /[\x5C\x5C]/ /[\x20-\x7E]/
qtextsmtp      : /[\x20-\x21|\x23-\x5B|\x5D-\x7E]/

command : [ quoted_string ]

start解析器的唯一规则是command-rule。

当我输入时"quoted_string",我希望它被解析为:

command -> quoted_string -> qcontentsmtp -> qtextsmtp

如您所见,qtextsmtp包含字母数字字符,编码为正则表达式,如 rfc. 但是,当我尝试解析它时,我收到以下消息:

input = '"quoted_string"'
....
####### Parsing Failed
No terminal defined for 'q' at line 1 col 2

"quoted_string"
 ^

当我输入时,""它按预期工作。

当我更改规则qtextsmtp并交换正则表达式"a"并使输入成为'"a"'它也可以工作。

我将所有规则定义为转换器中的函数,非常基本,如下所示:

class StringsTransformer(Transformer):
# externals
def quoted_string(self, args):
    return "".join(args)

# internals
def qcontentsmtp(self, args):
    return "".join(args)

def quoted_pairsmtp(self, args):
    return "".join(args)

def qtextsmtp(self, args):
    return "".join(args)

但我什至没有达到这些规则,因为正如我所说,它甚至不会解析。

我不太确定为什么正则表达式不起作用。我在其他部分使用这些类型的规则,它们工作得很好,只是这个没有。

标签: pythonregexlark-parser

解决方案


看起来 Lark 的正则表达式解析器分别与和 as 的引用混淆了,并且字母[根本]不匹配正则表达式。用和替换后,语法会解析提供的输入,如以下程序所示:\x5b\x5dq\x5b\[\x5d\]

import lark

grammar = r"""
quoted_string  : /[\x22]/ qcontentsmtp* /[\x22]/
qcontentsmtp   : qtextsmtp | quoted_pairsmtp
quoted_pairsmtp  : /[\x5C\x5C]/ /[\x20-\x7E]/
qtextsmtp      : /[\x20-\x21\x23-\[\]-\x7E]/

command : [ quoted_string ]
"""

parser = lark.Lark(grammar, start='command')

print(parser.parse('"quoted_string"'))

(请注意,这|在字符集中是多余的,它被解释为只是要匹配的另一个字符。)

这不是 Python 正则表达式的一般限制,它完全能够以十六进制接受[]转义:

>>> re.compile(r'[\x23-\x5b\x5d-\x7e]').match('q')
<re.Match object; span=(0, 1), match='q'>

我现在已经向 Lark 的维护者报告了这个问题。


推荐阅读