Tatsu:如何 validate/process 像语义动作中的算术表达式
Tatsu: How to validate/process arithmetic like expressions in semantic actions
我有一个 TatSu 语法,我在其中解析像 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
}
我想对此规则进行一些语义验证。也就是说,检查信号 A3-A0 是否已在其他某个(信号)块中声明。如果未声明,则引发错误。在解析另一个(信号)块时,我保留了所有用于查找的信号的命名(符号)table。我想知道在语义动作代码中到达 'walk' 这样的 AST 的最佳路径是什么,因为如果我的表达式包含 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 文档,其中有一节是关于 Walking Models
的,但似乎只是 AFTER 构建了一个完整的模型 AST。也许我错了。在构建整个(顶级)模型时,有没有一种方法可以在语义验证规则中有效地遍历 signal_groups_block 的 AST?
参考:https://tatsu.readthedocs.io/en/stable/models.html#walking-models
要在解析期间检查预定义的标识符,您需要 Symbol Table。
您将符号添加到定义它们的语法从句的语义中的 table,并参考使用它们的语法从句的语义中的符号 table。
因为 TatSu 保留了源输入的完整信息,所以在 解析后 使用 walker 检查这些语义可能更容易。报告的错误可以精确到行和列号,用户通常不介意先报告语法错误,然后再报告语义错误,因为 TatSu 解析器通常在第一个错误时停止(Tatsu 中支持解析恢复,但它没有记录)。
符号table在解析阶段是必需的仅在令牌可能或可能不是关键字,这取决于上下文(是的,PEG 可以通过帮助语义操作处理一些上下文敏感的情况)。
我有一个 TatSu 语法,我在其中解析像 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
}
我想对此规则进行一些语义验证。也就是说,检查信号 A3-A0 是否已在其他某个(信号)块中声明。如果未声明,则引发错误。在解析另一个(信号)块时,我保留了所有用于查找的信号的命名(符号)table。我想知道在语义动作代码中到达 'walk' 这样的 AST 的最佳路径是什么,因为如果我的表达式包含 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 文档,其中有一节是关于 Walking Models
的,但似乎只是 AFTER 构建了一个完整的模型 AST。也许我错了。在构建整个(顶级)模型时,有没有一种方法可以在语义验证规则中有效地遍历 signal_groups_block 的 AST?
参考:https://tatsu.readthedocs.io/en/stable/models.html#walking-models
要在解析期间检查预定义的标识符,您需要 Symbol Table。
您将符号添加到定义它们的语法从句的语义中的 table,并参考使用它们的语法从句的语义中的符号 table。
因为 TatSu 保留了源输入的完整信息,所以在 解析后 使用 walker 检查这些语义可能更容易。报告的错误可以精确到行和列号,用户通常不介意先报告语法错误,然后再报告语义错误,因为 TatSu 解析器通常在第一个错误时停止(Tatsu 中支持解析恢复,但它没有记录)。
符号table在解析阶段是必需的仅在令牌可能或可能不是关键字,这取决于上下文(是的,PEG 可以通过帮助语义操作处理一些上下文敏感的情况)。