这是我第一次使用语法和解析器生成器编写解析器。我想使用云雀python 模块解析某种 asn.1 格式。
这是我尝试解析的数据示例:
text = """
start_thing {
literal {
length 100,
fuzz lim unk,
seq-data gap {
type fragment,
linkage linked,
linkage-evidence {
{
type unspecified
}
}
}
},
loc int {
from 0,
to 1093,
strand plus,
id gi 384632836
}
}
"""
该结构可以包含各种节点,并且我无法提前确切知道我应该期望什么标签或标签组合。但是,我希望能够解析一些结构,例如“loc int {...}”部分。
这是我尝试过的语法,我使用数字来定义优先级:
grammar = """\
thing: "start_thing" node
strand_info.5: "strand plus"
| "strand minus"
locus_info.4: "loc int" "{" "from" INT "," "to" INT "," strand_info "," "id gi" INT "}"
nodes.1: node?
| node ("," node)*
node.1: locus_info
| TAGS? INT -> intinfo
| TAGS? "{" nodes "}" -> subnodes
| TAGS -> onlytags
TAGS.2: TAGWORD (WS TAGWORD)*
TAGWORD.3: ("_"|LETTER)("_"|"-"|LETTER|DIGIT)*
%import common.WS
%import common.LETTER
%import common.DIGIT
%import common.INT
%ignore WS
"""
我认为优先级(以附加数字的形式)足以让“loc int”事物优先于更通用的节点类型被识别,但这部分似乎被解析为 asubnodes
而不是locus_info
当我运行时上述语法的解析器并在上面的一段文本上运行它:
parser = Lark(grammar, start="thing", ambiguity="explicit")
parsed = parser.parse(text)
print(parsed.pretty())
我获得以下内容:
thing
subnodes
nodes
subnodes
literal
nodes
intinfo
length
100
onlytags fuzz lim unk
subnodes
seq-data gap
nodes
onlytags type fragment
onlytags linkage linked
subnodes
linkage-evidence
nodes
subnodes
nodes
onlytags type unspecified
subnodes
loc int
nodes
intinfo
from
0
intinfo
to
1093
onlytags strand plus
intinfo
id gi
384632836
我究竟做错了什么?
注意:我看过一个相关的问题(使用 Lark 的语法优先级),但我看不到如何将其答案应用于我的问题。我不认为我可以完全消除我的语法歧义(真实数据中有太多可能的情况),而且我不明白该ambiguity="explicit"
选项应该做什么。
编辑:颠倒优先级
我尝试颠倒优先级,如下所示:
grammar = """\
thing: "start_thing" node
strand_info.1: "strand plus"
| "strand minus"
locus_info.2: "loc int" "{" "from" INT "," "to" INT "," strand_info "," "id gi" INT "}"
nodes.5: node?
| node ("," node)*
node.5: locus_info
| TAGS? INT -> intinfo
| TAGS? "{" nodes "}" -> subnodes
| TAGS -> onlytags
TAGS.4: TAGWORD (WS TAGWORD)*
TAGWORD.3: ("_"|LETTER)("_"|"-"|LETTER|DIGIT)*
%import common.WS
%import common.LETTER
%import common.DIGIT
%import common.INT
%ignore WS
"""
parser = Lark(grammar, start="thing", ambiguity="explicit")
parsed = parser.parse(text)
print(parsed.pretty())
但是,输出完全相同。就像这些优先级被忽略,或者实际上没有歧义,因为我的locus_info
规则没有正确指定。