2012-01-01 41 views
1

我正试图将为未知工具开发的现有语法移植到Antlr。 在语法中有一个用例,其中有两个标记,例如TEXT和TEXT_WITHOUT_A 语法中的某些规则应该只允许没有a的文本,但剩下的就可以使用文本。如何处理令牌时,其中一个是另一个Antlr的子集?

我最初的尝试产生了下面的语法,但问题是,当txt实际上是它的一个超集时,Antlr匹配更具体的语法规则(txtwa)。如果我输入一些不包含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),它工作顺便说一句。 我在这里错过了什么?

回答

1

您必须认识到,词法分析器没有考虑到解析器在特定时间需要的内容:它只是试图构建一个从上到下贯穿词法分析器规则的令牌。

因为你TEXT之前定义LETTERS_MINUS_ALETTERS_MINUS_A将始终创建代替TEXT,这只会包含'a'的和'A'的。

这就是ANTLR的工作原理。

什么你可以做的仅仅是丢掉LETTERS_MINUS_A规则,做这样的事情:

txt 
: TEXT 
; 

txtwa 
: TEXT 
    { 
    if($TEXT.text.contains("a") || $TEXT.text.contains("A")) { 
     throw new Exception("Eeek, I saw an `[aA]`!"); 
    } 
    } 
; 
+1

我在TXT和txtwa都对自己使用的原语法部分。我只需要txt和txtwa,其中txtwa只比txt少一个字母。我必须使用两者。 – mahonya 2012-01-01 21:55:28

+0

@sarikan,我的建议仍然使用文本和textwa规则...... – 2012-01-01 22:19:51

+1

您给出了正确的答案,只是我没有看到您使用解析器规则部分。谢谢,这真的很有帮助。 – mahonya 2012-01-01 22:37:05

相关问题