在百灵鸟的语法中正确设置规则和终端之间的优先级

时间:2018-06-19 12:31:39

标签: python lark-parser

这是我第一次使用语法和解析器生成器编写解析器。我想使用lark 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”事物比一般的节点类型具有更高的优先级,但是这部分似乎被解析为subnodes相反,当我运行上述语法时,将其作为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

我在做什么错了?

注意:我已经看到一个相关的问题(Priority in grammar using 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规则而忽略了那些优先级,或者实际上没有歧义。

1 个答案:

答案 0 :(得分:1)

我认为您应该更改优先级。 “ locus_info.4”是最精确的规则,因此必须优先。