Если добавить правило:
parse
: (t=. {System.out.printf("type=\%-20s text='\%s'\n", tokenNames[$t.type], $t.text);})* EOF
;
, который просто сопоставляет ноль или более токенов и печатает тип и текст этих токенов, вы увидите, что лексер не может справиться с вводом , keyword
из вашего примера:
keywords=[keyword(arg='name', value=Str(s='UGA')), keyword(arg='rank', value=Str(s='2'))]
^^^^^^^^^
Так что в одном из ваших правил парсера нет проблем, но на лексическом уровне все идет не так, как надо.
Я советую вам удалить все буквальные токены из вашего парсера и создать для них правило лексера. Затем добавьте одно правило parse
, как я писал выше, с помощью которого вы можете проверить лексер, чтобы увидеть, созданы ли правильные токены. После того, как будут созданы правильные токены, напишите правила парсера.
Я почти уверен, что проблема в том, что у вас нет токена ', keyword'
и что, когда лексер "видит" ', k'
, он пытается создать токен ', kwargs'
, который не работает, конечно. Поэтому я также рекомендую вам не включать запятые и пробелы в свои токены, но пусть они будут собственными токенами.
Кроме того, вы не хотите иметь правило переписывания, подобное этому:
stmtlist: ((', '?) stmt)* -> stmt*
;
, который потенциально не может ничего соответствовать. Если это произойдет, ANTLR сгенерирует исключение при создании AST. Всегда позволяйте правилу перезаписи создавать что-то :
...
tokens {
...
STMTLST;
...
}
...
stmtlist: ((', '?) stmt)* -> ^(STMTLST stmt*)
;