假设我有一个 ANTLR 语法:
program = word (' ' word)*
;
word = 'dog' | 'cat' | 'bird'
;
据我了解,它将匹配上面的任何单词序列,例如“狗狗猫”,“狗猫鸟猫”等。但是如果我只想匹配相同值的重复,例如“dogdog”、“catcatcatcat”、“birdbirdbird”等等。如何修改上面的语法来做到这一点?
换句话说,我希望“program”的规则中非终结符号“word”的重复出现始终匹配相同的产生式规则,而不是为“word”指定的任何数量的规则,但不必明确在“程序”的规则中列出它们中的每一个(例如,如果“单词”有大量的替代方案),这意味着我想避免这样的事情:
program:
'dog' (' ' 'dog')*
| 'cat' (' ' 'cat')*
| 'bird' (' ' 'bird')*
...
;
我认为在正则表达式中,这是使用反向引用(例如“”)来实现的,ANTLR语法是否有等效的方法,或者其他方法?
正如 kaby76 所提到的:在解析器规则中处理此问题意味着引入谓词,这意味着将目标特定代码添加到语法中(通常不建议这样做)。可能看起来像这样(使用 Java 目标):
grammar P;
@parser::members {
boolean sameTokenAhead() {
Token previous = _input.LT(-1);
Token next = _input.LT(1);
return previous.getType() == next.getType();
}
}
parse
: repeated_words* EOF
;
repeated_words
: word ( {sameTokenAhead()}? . )*
;
word
: DOG
| CAT
| BIRD
;
请注意,在上面的示例中,词法分析器会丢弃空格。
另一种可能性是从这些重复的单词创建单个标记:
DOG
: 'dog' (' ' 'dog')*
;
或者只匹配您在问题中提到的一个或多个单词:
program
: word (' ' word)*
;
word
: 'dog' | 'cat' | 'bird'
;
然后在解析之后,检查侦听器是否相同,如果不同,则可能会抛出错误。