Я получил эту грамматику синтаксического анализатора , с которой я также хочу использовать что-то похожее на строки-шаблоны Javascript.
parser grammar Test;
options {
tokenVocab = TestLexer;
}
definition: sourceElements? EOF ;
sourceElements: sourceElement+ ;
sourceElement: mapping ;
templateString: '`' TemplateStringCharacter* ('${' variable '}' TemplateStringCharacter*)+ '`' ;
fieldName: varname | ('[' value ']') ;
mapping: fieldName ':' ( '{' sourceElements '}'
| variable ( '{' sourceElements '}' )? '?'?
| value
| array )
;
funParameter: '(' value? (',' value)* ')' ;
array: '[' value? (',' value)* ']';
variable: (varname | '{' value '}' | '[' boolEx ']' | templateString) funParameter? ('.' variable)* ;
value: INT | BOOL | FLOAT | STRING | variable ;
varname: VAR ;
И эта грамматика лексера
lexer grammar TestLexer;
WS : [ \t\r\n\u000C]+ -> skip ;
NEWLINE : [\r\n] ;
BOOL : ('true'|'false') ;
TemplateStringLiteral : TemplateStringCharacter*;
VAR : [$]?[a-zA-Z0-9_]+|[@] ;
INT : '-'?[0-9]+ ;
FLOAT : '-'?[0-9]+'.'[0-9]+ ;
STRING : '"' DoubleStringCharacter* '"' | '\'' SingleStringCharacter* '\'' ;
TEMPSTART : '${' ;
TEMPEND : '}' ;
TemplateStart : '`' -> pushMode(template) ;
/// Comments
MultiLineComment : '/*' .*? '*/' -> channel(HIDDEN) ;
SingleLineComment : '//' ~[\r\n\u2028\u2029]* -> channel(HIDDEN) ;
mode template;
TemplateVariableStart: TEMPSTART -> pushMode(templateVariable);
TemplateStringLiteral : TemplateStringCharacter* ;
TemplateEnd : '`' -> popMode;
mode templateVariable;
WS : [ \t\r\n\u000C]+ -> skip ;
All : [^}]+ ;
TemplateVariableEnd : TEMPEND -> popMode;
fragment DoubleStringCharacter : ~["\r\n] ;
fragment SingleStringCharacter : ~['\r\n] ;
fragment TemplateStringCharacter : ~[`] ;
fragment DecimalDigit : [0-9] ;
Когда я ввожу это:
test: {
abc: `Hello World`
}
Дерево синтаксического анализа выглядит так:
(definition
(sourceElements
(sourceElement
(statement
(mapping
(fieldName
(varname test)
) : {
(sourceElements
(sourceElement
(statement mapping)
)
(sourceElement
(statement
(mapping abc : `)
)
)
(sourceElement
(statement mapping)
)
(sourceElement
(statement
(mapping Hello)
)
)
(sourceElement
(statement
(mapping World `)
)
)
)
}
)
)
)
)
<EOF>
)
И я получаю сообщение об ошибке: строка 2: 8 нет приемлемой альтернативыпри вводе 'abc: `Hello'
Я не понимаю, почему можно даже сопоставить что-то вроде пустого mapping или mapping наподобие" World "`" потому что отображение должно иметь ":" в середине.И почему правило templateString не соответствует всему "Hello World" от обратной галочки до обратной галочки?
РЕДАКТИРОВАТЬ:
Заметив, что Lexer не был регенерирован, когда я подумал, что я получил ошибки вроде: "не могу создать неявный токен для строкового литерала в некомбинированная грамматика: ']' ".Поэтому мне пришлось перенести все неявные объявления в грамматику лексера.Поэтому я изменил код так:
parser grammar Test;
options {
tokenVocab = TestLexer;
}
definition: sourceElements? EOF ;
sourceElements: sourceElement+ ;
sourceElement: mapping ;
templateString: OpenBackTick TemplateStringLiteral* (TemplateVariableStart variable CloseBrace TemplateStringLiteral*)+ CloseBackTick ;
fieldName: varname | OpenBracket value CloseBracket ;
mapping: fieldName Colon (
OpenBrace sourceElements CloseBrace
| variable ( OpenBrace sourceElements CloseBrace )? IF?
| value
| array
)
;
funParameter: OpenParen value? (Comma value)* CloseParen ;
array: OpenBracket value? (Comma value)* CloseBracket;
variable: (varname | OpenBrace value CloseBrace | templateString) funParameter? (Dot variable)* ;
value: INT | BOOL | FLOAT | STRING | variable ;
varname: VAR ;
И грамматика лексера :
lexer grammar TestLexer;
OpenBracket: '[';
CloseBracket: ']';
OpenParen: '(';
CloseParen: ')';
OpenBrace: '{' ;
CloseBrace: '}' ;
IF: '?' ;
AND: 'AND' ;
OR: 'OR';
LessThan: '<';
MoreThan: '>';
LessThanEquals: '<=';
GreaterThanEquals: '>=';
Equals: '=';
NotEquals: '!=';
IN: 'IN';
NOT: '!';
Colon: ':';
Dot: '.' ;
Comma: ',' ;
OpenBackTick : '`' -> pushMode(template) ;
WS : [ \t\r\n\u000C]+ -> skip ;
NEWLINE : [\r\n] ;
BOOL : ('true'|'false') ;
VAR : [$]?[a-zA-Z0-9_]+|[@] ;
INT : '-'?[0-9]+ ;
FLOAT : '-'?[0-9]+'.'[0-9]+ ;
STRING : '"' DoubleStringCharacter* '"' | '\'' SingleStringCharacter* '\'' ;
/// Comments
MultiLineComment : '/*' .*? '*/' -> channel(HIDDEN) ;
SingleLineComment : '//' ~[\r\n\u2028\u2029]* -> channel(HIDDEN) ;
mode template;
TemplateVariableStart: '${' -> pushMode(templateVariable);
CloseBackTick : '`' -> popMode;
TemplateStringLiteral: TemplateStringCharacter ;
mode templateVariable;
WHS : [ \t\r\n\u000C]+ -> skip ;
All : [^}]+ ;
TemplateVariableEnd : CloseBrace -> popMode;
fragment DoubleStringCharacter : ~["\r\n] ;
fragment SingleStringCharacter : ~['\r\n] ;
fragment TemplateStringCharacter : ~[`] ;
fragment DecimalDigit : [0-9] ;
Теперь я получаю сообщение об ошибке: строка 1: 0 не соответствуетinput 'test' Ожидается {, '?', '[', VAR} Что странно, потому что 'test' должен соответствовать VAR .Есть идеи, почему это происходит?