Что сейчас происходит
При тестировании вашего примера с вашей текущей грамматикой, отображающей сгенерированные токены, лексер дает следующее:
[@0,0:0='`',<'`'>,1:0]
[@1,1:4='Some',<VAR>,1:1]
[@2,6:9='text',<VAR>,1:6]
[@3,11:12='${',<'${'>,1:11]
[@4,13:20='variable',<VAR>,1:13]
[@5,21:21='.',<'.'>,1:21]
[@6,22:25='name',<VAR>,1:22]
[@7,26:26='}',<'}'>,1:26]
... shortened ...
[@26,85:84='<EOF>',<EOF>,2:0]
Это говорит вам о том, что Some
, которым вы намеревались быть TemplateStringLiteral*
, на самом деле было лексировано как VAR
. Почему это происходит?
Как упоминалось в этом ответе, antlr использует максимально возможное совпадение для создания токена. Поскольку ваше TemplateStringLiteral
правило соответствует только одиночным символам, а ваше VAR
правило соответствует бесконечному количеству символов, лексер, очевидно, использует последний для сопоставления Some
.
Что бы вы могли попробовать (спойлер: не сработает)
Вы можете попробовать изменить правило следующим образом:
TemplateStringLiteral: ('\\`' | ~'`')+ ;
так что он захватывает более одного символа и поэтому будет предпочтительнее. Это связано с двумя причинами, по которым это не работает:
Как бы лексический анализатор мог сопоставить что-либо с правилом VAR
?
Правило TemplateStringLiteral
теперь также соответствует ${
, что запрещает правильное распознавание начала фрагмента шаблона.
Как добиться того, чего на самом деле хочешь
Может быть другое решение, но оно работает:
Файл MartinCup.g4:
parser grammar MartinCup;
options { tokenVocab=MartinCupLexer; }
templateString
: BackTick TemplateStringLiteral* (template TemplateStringLiteral*)+ BackTick
;
template
: TemplateStart variable TemplateEnd
;
variable
: varname funParameter? (Dot variable)*
;
varname
: VAR
;
funParameter
: OpenPar variable? (Comma variable)* ClosedPar
;
Файл MartinCupLexer.g4:
lexer grammar MartinCupLexer;
BackTick : '`' ;
TemplateStart
: '${' -> pushMode(templateMode)
;
TemplateStringLiteral
: '\\`'
| ~'`'
;
mode templateMode;
VAR
: [$]?[a-zA-Z0-9_]+
| [$]
;
OpenPar : '(' ;
ClosedPar : ')' ;
Comma : ',' ;
Dot : '.' ;
TemplateEnd
: '}' -> popMode;
В этой грамматике используются режимы
Причина этого та же, что и выше, Some
переведено в VAR
.
person
AplusKminus
schedule
18.04.2019