ANTLR: Как хранить токены и узлы дерева в одном 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')+;
Как можно хранить COMMA в 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.
2 ответа
Проблема в том, что вы можете добавить узлы дерева в element
список или токены, а не оба одновременно. Поскольку вам нужно смешать их вместе, список должен содержать узлы дерева, и вам придется преобразовывать элементы токена в узлы дерева.
Решение 1:
Если вы хотите пойти общий element +=
Кстати, самое простое исправление, вероятно, заключается в том, чтобы поместить токен лексера в поддерево, используя простое правило:
comma: COMMA;
Таким образом, если вы используете comma
в вашем правиле с переписать, правило перезаписи получит nil
дерево с токеном вместо получения токена напрямую.
Решение 2:
Оберните внутренние скобки в отдельное правило, не переписывая дерево, а затем используйте его в исходном правиле с перезаписью:
values : value (COMMA value)*;
value_list : LEFT_PARENTHESIS vals = values RIGHT_PARENTHESIS -> ^(LIST $vals);
Другое решение состоит в том, чтобы вообще не использовать список токенов и просто перебирать узлы дерева, когда вам нужны элементы. Это абсолютно тривиальное и самое гибкое решение.