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);

Другое решение состоит в том, чтобы вообще не использовать список токенов и просто перебирать узлы дерева, когда вам нужны элементы. Это абсолютно тривиальное и самое гибкое решение.

Другие вопросы по тегам