Вы можете использовать следующую рекурсивную функцию:
import re
def rec_fn(asn, key):
def build_definitions(mapping, key, sequence_only=False):
if not sequence_only and (key,) in mapping:
key = (key,)
is_choice = True
else:
is_choice = False
if isinstance(mapping[key], dict):
definitions = {}
for variable, definition in mapping[key].items():
if definition in mapping or (definition,) in mapping:
definitions[variable] = build_definitions(mapping, definition, sequence_only=is_choice)
else:
definitions[variable] = definition
return definitions
else:
return mapping[key]
mapping = {}
for name, type, definition in re.findall(r'([A-Za-z-]+)\s*::=\s*(SEQUENCE|CHOICE|ENUMERATED)\s*{(.*?)}(?=\s*(?:[A-Za-z-]+\s*::=\s*(?:SEQUENCE|CHOICE|ENUMERATED)|END)\b)', asn, flags=re.DOTALL):
if type in ('SEQUENCE', 'CHOICE'):
for definitions in re.sub(r'{[^}]*}', '', definition).split(','):
definitions = re.sub(r'\bSET OF\b|\(.*\).*', '', definitions).strip().split(maxsplit=1)
if definitions:
mapping.setdefault(name if type == 'SEQUENCE' else (name,), {})[definitions[0]] = definitions[1]
elif type == 'ENUMERATED':
mapping[name] = re.findall(r'[A-Za-z-]+', definition)
return build_definitions(mapping, key)
, чтобы с (обратите внимание, что лучше использовать тройные кавычки для многострочного строкового литерала):
ee='''
Module-order DEFINITIONS AUTOMATIC TAGS ::=
BEGIN
Order ::= SEQUENCE {
header Order-header
}
Order-header ::= SEQUENCE {
reference NumericString (SIZE (12)),
date NumericString (SIZE (8)) -- MMDDYYYY --
}END
seq_list=['Order','Order-header']
condition='Order ::= SEQUENCE {
header Order-header
}'''
rec_fn(ee, 'Order')
вернет:
{'header': {'reference': 'NumericString', 'date': 'NumericString'}}