Правильно установить приоритеты между правилами и терминалами в грамматике для жаворонка

1

Это мой первый раз, когда я пишу парсер, используя грамматику и генератор парсера. Я хочу, чтобы разобрать какой - то формат 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

Что я делаю неправильно?

Примечание. Я видел связанный вопрос (Приоритет в грамматике с использованием 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 не было правильно указано.

Теги:
lark-parser

1 ответ

1

Я думаю, вы должны изменить свои приоритеты. "Locus_info.4" является самым точным правилом, поэтому он должен быть первым в приоритете.

  • 0
    Я подумал, что чем выше число, тем выше приоритет, основываясь на примере, приведенном в документации: github.com/lark-parser/lark/wiki/Grammar-Reference DECIMAL.2: INTEGER "." INTEGER //# Will be matched before INTEGER
  • 0
    Да, но в этом примере нет других приоритетов. И в официальной документации lark написано "rule.n: ... Правило с приоритетом n" ( github.com/lark-parser/lark/blob/master/docs/… ), поэтому для меня это должно быть red "rule.1: ... имеет первый приоритет. Возможно, я неправильно его интерпретирую. Вы пытались изменить его? Мне не удалось протестировать ваш код, чтобы увидеть, работает ли он
Показать ещё 5 комментариев

Ещё вопросы

Сообщество Overcoder
Наверх
Меню