Правильно установить приоритеты между правилами и терминалами в грамматике для жаворонка
Я впервые пишу парсер с использованием грамматики и генератора парсеров. Я хочу проанализировать какой-то формат asn.1 с помощью модуля Lark Python.
Вот пример данных, которые я пытаюсь проанализировать:
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
когда я запускаю make синтаксический анализатор для вышеуказанной грамматики и запускаю ее на фрагменте текста выше:
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
Правило не было правильно указано.
1 ответ
Я думаю, что вы должны изменить свои приоритеты. "Locus_info.4" является наиболее точным правилом, поэтому оно должно быть первым по приоритету.