我正在尝试将为未知工具开发的现有语法移植到Antlr。 语法中有一个用例,其中有两个标记,如TEXT和TEXT_WITHOUT_A 语法中的一些规则应该只允许没有a的文本,但其余的则可以使用文本。
我最初的尝试产生了以下语法,但问题是,当txt实际上是它的超集时,Antlr匹配更具体的语法规则(txtwa)。如果我输入类似'sometextwth'的不包含a的内容,Antlr不遵循文本规则(txt)预期的输入是txt,提供的输入匹配是,但Antlr指出输入匹配txtwa,即使在语法的那一点上没有预料到,选择不使用txt。
/*------------------------------------------------------------------
* PARSER RULES
*------------------------------------------------------------------*/
expr : ( txt)* ;
txt : TEXT ;
txtwa : LETTERS_MINUS_A;
term : factor ( (MULT | DIV) factor)*;
factor : NUMBER;
/*------------------------------------------------------------------
* LEXER RULES
*------------------------------------------------------------------*/
NUMBER : (DIGIT)+ ;
WHITESPACE : ( '\t' | ' ' | '\r' | '\n' | '\u000C')+ {$channel = HIDDEN;} ;
fragment LETTER_MINUS_A : ('b'..'z' | 'B'..'Z');
fragment LETTER : ('a'..'z' | 'A'..'Z');
fragment DIGIT : '0'..'9' ;
LETTERS_MINUS_A
: LETTER_MINUS_A (LETTER_MINUS_A)*;
TEXT : LETTER (LETTER)* ;
我想自由地使用txt而不必做(txt | txtwa),它的工作原理顺便说一句。 我在这里缺少什么?
答案 0 :(得分:1)
你必须意识到词法分析器没有考虑解析器在特定时间需要的内容:它只是试图从上到下构建一个通过词法分析器规则的令牌。
由于您在LETTERS_MINUS_A
之前定义了TEXT
,因此始终会创建LETTERS_MINUS_A
而不是TEXT
,而'a'
只会包含'A'
和LETTERS_MINUS_A
1}}的。
这就是ANTLR的工作原理。
你可以做的只是抛弃txt
: TEXT
;
txtwa
: TEXT
{
if($TEXT.text.contains("a") || $TEXT.text.contains("A")) {
throw new Exception("Eeek, I saw an `[aA]`!");
}
}
;
规则并执行以下操作:
{{1}}