Это мой первый раз, когда я пишу парсер, используя грамматику и генератор парсера. Я хочу, чтобы разобрать какой - то формат 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
не было правильно указано.
Я думаю, вы должны изменить свои приоритеты. "Locus_info.4" является самым точным правилом, поэтому он должен быть первым в приоритете.
DECIMAL.2: INTEGER "." INTEGER //# Will be matched before INTEGER