ANTLR:如何将令牌和树节点存储在同一个 AST 中?
ANTLR: How to store both tokens and tree nodes in the same AST?
给定以下语法:
statement : START value_list;
value_list : LEFT_PARENTHESIS element += value (COMMA element += value)* RIGHT_PARENTHESIS -> ^(LIST $element+);
value : NUMBER | STRING | value_list;
START : 'START';
LEFT_PARENTHESIS : '(';
RIGHT_PARENTHESIS : ')';
COMMA : ',';
NUMBER : ('0'..'9')+;
STRING : ('a'..'z' | 'A'..'Z')+;
如何在 AST 中存储逗号?换句话说,如果尝试以下操作:
value_list : LEFT_PARENTHESIS element += value (element += COMMA element += value)* RIGHT_PARENTHESIS -> ^(LIST $element+);
...会报如下错误:
error(125): grammar.g:2:75: label element type mismatch with previous definition: token-list!=rule-list
关于如何解决这个问题的任何提示?非常感谢您的帮助!
此致,
TJ.
问题是您可以在 element
列表或标记中添加树节点,但不能同时添加。由于您需要将两者混合在一起,因此列表需要包含树节点并且您必须将令牌元素转换为树节点。
解决方案 1:
如果您想采用通用 element +=
方式,最简单的解决方法可能是使用简单规则将词法分析器标记包装在子树中:
comma: COMMA;
这样,如果您在重写规则中使用 comma
,重写规则将获得带有令牌的 nil
树,而不是直接获取令牌。
解决方案 2:
在不重写树的情况下将括号内包裹在单独的规则中,然后在原始规则中使用重写:
values : value (COMMA value)*;
value_list : LEFT_PARENTHESIS vals = values RIGHT_PARENTHESIS -> ^(LIST $vals);
另一种解决方案是根本不使用标记列表,而是在需要元素时简单地遍历树节点。这是非常简单且最灵活的解决方案。
给定以下语法:
statement : START value_list;
value_list : LEFT_PARENTHESIS element += value (COMMA element += value)* RIGHT_PARENTHESIS -> ^(LIST $element+);
value : NUMBER | STRING | value_list;
START : 'START';
LEFT_PARENTHESIS : '(';
RIGHT_PARENTHESIS : ')';
COMMA : ',';
NUMBER : ('0'..'9')+;
STRING : ('a'..'z' | 'A'..'Z')+;
如何在 AST 中存储逗号?换句话说,如果尝试以下操作:
value_list : LEFT_PARENTHESIS element += value (element += COMMA element += value)* RIGHT_PARENTHESIS -> ^(LIST $element+);
...会报如下错误:
error(125): grammar.g:2:75: label element type mismatch with previous definition: token-list!=rule-list
关于如何解决这个问题的任何提示?非常感谢您的帮助!
此致,
TJ.
问题是您可以在 element
列表或标记中添加树节点,但不能同时添加。由于您需要将两者混合在一起,因此列表需要包含树节点并且您必须将令牌元素转换为树节点。
解决方案 1:
如果您想采用通用 element +=
方式,最简单的解决方法可能是使用简单规则将词法分析器标记包装在子树中:
comma: COMMA;
这样,如果您在重写规则中使用 comma
,重写规则将获得带有令牌的 nil
树,而不是直接获取令牌。
解决方案 2:
在不重写树的情况下将括号内包裹在单独的规则中,然后在原始规则中使用重写:
values : value (COMMA value)*;
value_list : LEFT_PARENTHESIS vals = values RIGHT_PARENTHESIS -> ^(LIST $vals);
另一种解决方案是根本不使用标记列表,而是在需要元素时简单地遍历树节点。这是非常简单且最灵活的解决方案。