Python 云雀解析器可以';t解析字符,即使它们是在规则的正则表达式中定义的

Python 云雀解析器可以';t解析字符,即使它们是在规则的正则表达式中定义的,python,regex,lark-parser,Python,Regex,Lark Parser,我正在尝试编写一个SMTP解析器,并从中获取了一些引用字符串的信息。因此,我有以下语法(去掉所有有效的部分,重点放在不起作用的部分): 解析器的唯一start是命令-规则 当我输入“quoted_string”时,我希望它被解析为: command -> quoted_string -> qcontentsmtp -> qtextsmtp 如您所见,qtextmtp包含字母数字字符,编码为正则表达式,如rfc中所示。但是,当我尝试解析它时,我得到以下消息: input = '

我正在尝试编写一个SMTP解析器,并从中获取了一些引用字符串的信息。因此,我有以下语法(去掉所有有效的部分,重点放在不起作用的部分):

解析器的唯一
start
命令
-规则

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

command -> quoted_string -> qcontentsmtp -> qtextsmtp
如您所见,
qtextmtp
包含字母数字字符,编码为正则表达式,如rfc中所示。但是,当我尝试解析它时,我得到以下消息:

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

"quoted_string"
 ^
当我只输入
时,它会按预期工作

当我更改规则
qtextmtp
并将正则表达式交换为
“a”
,并使输入为
““a”
时,它也可以工作

我在transformer中将所有规则定义为函数,非常基本,如下所示:

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)
但我甚至不了解这些规则,因为正如我所说,它甚至不会解析


我不太清楚为什么正则表达式不起作用。我在其他部分使用这些类型的规则,它们工作得很好,但在这个部分就不行了。

如果可以的话,我建议在终端中使用字符串文字;尽管它们不能完全匹配RFC,但它们肯定可以在现有的lark解析器实现中工作。(你的例子对我来说也是失败的,但使用下面的方法是可行的。我不确定我是否理解其中的原因。)

引用自


你如何定义你的语法?如果在代码中内联定义反斜杠(而不是从文件中读取),则可能需要避开反斜杠。

看起来Lark的regexp解析器与分别引用
[
]
\x5b
\x5d
相混淆,而且
q
字母与regexp不匹配。将
\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'>
重新编译(r'[\x23-\x5b\x5d-\x7e]')。匹配('q')
现在,我要向百灵鸟的维护者致意。

工作得很好!谢谢你报道这个问题。正如你所说的,我确实希望十六进制代码被转义,我100%支持这是一个可用性问题的观点。谢谢你的回答。正如我在问题中所说的,我真的希望我的lark解析器尽可能地匹配RFC。我已经改变了一些部分,我真的想保持在最低限度。然而,事实证明,在这种情况下这样做并不一定是可能的。请退房
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"'))
>>> re.compile(r'[\x23-\x5b\x5d-\x7e]').match('q')
<re.Match object; span=(0, 1), match='q'>