Lark 解析器无法解析字符,即使它们是在规则的正则表达式中定义的
Lark parser can't parse characters, even though they are defined in regex of rule
我正在尝试编写一个 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
规则。
当我输入 "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)
但我什至不了解这些规则,因为正如我所说,它甚至不会解析。
我不太清楚为什么正则表达式不起作用。我在其他部分使用了这些类型的规则,它们工作得很好,只是这个没有。
如果可以的话,我建议在终端中使用字符串文字;尽管它们不会完全匹配 RFC,但它们肯定可以在现有的百灵鸟解析器实现中工作。 (你的例子对我来说也失败了,但使用下面的方法。不确定我是否理解为什么的基础。)
DOUBLE_QUOTED_STRING : /"[^"]*"/
引用自the lark src。
你是如何定义语法的?如果您在代码中内联定义反斜杠(相对于从文件读取),您可能需要转义 \
反斜杠。
Lark 的正则表达式解析器似乎混淆了 [
和 ]
分别作为 \x5b
和 \x5d
的引用,以及 q
字母根本不匹配正则表达式。将 \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'>
我现在 reported the issue 致 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
规则。
当我输入 "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)
但我什至不了解这些规则,因为正如我所说,它甚至不会解析。
我不太清楚为什么正则表达式不起作用。我在其他部分使用了这些类型的规则,它们工作得很好,只是这个没有。
如果可以的话,我建议在终端中使用字符串文字;尽管它们不会完全匹配 RFC,但它们肯定可以在现有的百灵鸟解析器实现中工作。 (你的例子对我来说也失败了,但使用下面的方法。不确定我是否理解为什么的基础。)
DOUBLE_QUOTED_STRING : /"[^"]*"/
引用自the lark src。
你是如何定义语法的?如果您在代码中内联定义反斜杠(相对于从文件读取),您可能需要转义 \
反斜杠。
Lark 的正则表达式解析器似乎混淆了 [
和 ]
分别作为 \x5b
和 \x5d
的引用,以及 q
字母根本不匹配正则表达式。将 \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'>
我现在 reported the issue 致 Lark 的维护者。