У меня есть грамматика TatSu, где я анализирую арифметику c выражения типа SignalGroup {ABUS='A3 + A2 + A1 + A0';}.
Соответствующая грамматика:
#--------------------------------------------- SIGNAL GROUPS BLOCK -----------------------------------------------------
signal_groups_block::SignalGroups
=
'SignalGroups' ~ [id:identifier] '{' ~ objs:{signal_group | annotation | udb} '}'
;
signal_group::SignalGroup
=
id:identifier '=' expr:signal_reference_expr ( ';' |
('{' ~ attr:{signal_statement | annotation |udb} '}') )
;
signal_reference_expr
=
signal_name_array_opt
| "'" ~ exprs:signal_reference_expr_items "'"
;
signal_reference_expr_items
=
left:signal_reference_expr_items op:'+' ~ right:signal_reference_expr_item
| left:signal_reference_expr_items op:'-' ~ right:signal_reference_expr_item
| left:signal_reference_expr_item
;
signal_reference_expr_item
=
'(' ~ @:signal_reference_expr_items ')'
| signal_name_array_opt
;
signal_name_array_opt
=
id:identifier ['[' ~ msb:integer ['..' ~ lsb:integer] ']']
;
Выход AST:
{
"objs": [
{
"__class__": "SignalGroup",
"expr": {
"exprs": {
"left": {
"left": {
"left": {
"left": {
"id": "A3",
"lsb": null,
"msb": null
},
"op": null,
"right": null
},
"op": "+",
"right": {
"id": "A2",
"lsb": null,
"msb": null
}
},
"op": "+",
"right": {
"id": "A1",
"lsb": null,
"msb": null
}
},
"op": "+",
"right": {
"id": "A0",
"lsb": null,
"msb": null
}
}
},
"attr": null,
"id": "ABUS"
}
],
"id": null
}
Я хотел бы сделать несколько проверок semanti c для этого правила. То есть проверьте, чтобы сигналы A3-A0 были объявлены в каком-то другом (сигнальном) блоке. Если не объявлено, поднять ошибку. Я сохранил таблицу имен (символов) всех сигналов для поиска при анализе другого (сигнального) блока. Я хотел бы знать, как лучше всего обходить такой AST в коде действия semanti c, поскольку он может быть очень глубоким, если мое выражение содержит, скажем, 200 сигналов (то есть A0 + A1 + .. A199). Прямо сейчас у меня есть только функция заглушки, вот так:
class STILSemantics(ModelBuilderSemantics):
....
def signal_groups_block(self, ast, node):
"""Signal groups block."""
log.info('Parse %s block', node)
print('got here')
from tatsu.util import asjsons
print(asjsons(ast))
# TODO: HOW TO WALK THE AST HERE????
return ast
Я проверил TatSu do c и есть раздел на Walking Models
, но кажется, что это только ПОСЛЕ полная модель АСТ построена. Может я не прав. Есть ли способ эффективно пройти AST блока signal_groups_block внутри правила проверки c семанти, пока строится вся модель (верхнего уровня)?
Ссылка: https://tatsu.readthedocs.io/en/stable/models.html#walking -модели