我得到了这个解析器语法,我还想用它来使用类似于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语法
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>
)
我不明白,为什么甚至可以匹配一些像空映射或像“world`”这样的映射,因为映射需要在中间有一个“:”。并且为什么规则模板字符串不匹配整个“Hello World”从一个滴答到另一个滴答?
编辑:
当我注意到Lexer没有被重新生成时,我得到了这样的错误:“不能为string literal innon-combined grammark:']'创建隐式标记”。所以我不得不将所有隐式声明移到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] ;
默认模式下有两个lexer规则可以匹配backtick:btick
和templatestart
。templatestart
将切换到template
模式,但btick
不会。因为btick
在语法中是第一位的,所以它具有优先级。这意味着当lexer看到一个backtick时,它将生成一个btick
令牌,而不切换模式。
要解决这个问题,每个模式应该只有一个lexer规则与一个backtick匹配,并且该规则应该改变模式。
我不明白,为什么甚至可以匹配一些像空映射或像“world`”这样的映射,因为映射需要在中间有一个“:”。
当输入包含语法错误时,生成的解析树可能包含实际上也无效的构造。当您的输入解析没有错误时,您将得到一个有意义的树。
我正在重新学习一些基本的Antlr,并尝试编写一个生成todo项的语法: 我遇到的问题是,有三个lexer规则特别“不匹配”,这取决于它们使用的上下文: 以下是我的完整语法以求清晰: 旁白:我知道还有其他奇怪的地方,比如一个事件的名称只能是一个单词,但我是在一次处理一个问题。
我有一个antlr语法,它有多个与同一个单词匹配的词法规则。在词法分析过程中无法解决这个问题,但通过语法,它就变得毫不含糊了。 示例: 输入:<代码>1英寸(米) 单词“in”与lexer规则和匹配。 如何在保持语法文件可读性的同时解决此问题?
现在我得到了:错误。 我知道我的输入被AND和TERM lexer规则匹配,但我希望能够指定TERM是除与AND规则匹配的内容之外的任何内容。
查看文档,ANTLR2过去有一种叫做谓词法的东西,下面的例子是这样的(灵感来自Pascal): 在我看来,这实际上是规则开头的一个积极的前瞻性断言:如果前瞻性与匹配,那么第一个规则将被应用(并与该输入的部分匹配),依此类推。 我还没有在ANTLR4中找到这样的东西。2到3迁移指南似乎没有提到这一点,而3到4更改文档指出: ANTLR3和4之间最大的区别是ANTLR4接受您给出的任何语法,除非该语法
我需要以下令牌: 允许的字符包括大写、小写、数字、空格和连字符 长度不固定(长度必须至少为两个字符) 标记必须至少包含一个空格或连字符 令牌必须以大写、小写、数字、空格或连字符开头和结尾(不能以空格开头或结尾) 下面语法中的ANTLR lexer规则“alphanumericspacehyphen”除了一个情况外几乎都起作用。使用解析器规则“sic”进行测试,以下输入将解析(不带引号): 以下输入