如何强制在规则中对非终结符号使用相同的产生式?

问题描述 投票:0回答:1

假设我有一个 ANTLR 语法:

program = word (' ' word)*
  ;

word = 'dog' | 'cat' | 'bird'
  ;

据我了解,它将匹配上面的任何单词序列,例如“狗狗猫”,“狗猫鸟猫”等。但是如果我只想匹配相同值的重复,例如“dogdog”、“catcatcatcat”、“birdbirdbird”等等。如何修改上面的语法来做到这一点?

换句话说,我希望“program”的规则中非终结符号“word”的重复出现始终匹配相同的产生式规则,而不是为“word”指定的任何数量的规则,但不必明确在“程序”的规则中列出它们中的每一个(例如,如果“单词”有大量的替代方案),这意味着我想避免这样的事情:

program:
    'dog' (' ' 'dog')*
  | 'cat' (' ' 'cat')*
  | 'bird' (' ' 'bird')*
  ...
  ;

我认为在正则表达式中,这是使用反向引用(例如“”)来实现的,ANTLR语法是否有等效的方法,或者其他方法?

parsing antlr antlr4 context-free-grammar
1个回答
0
投票

正如 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'
 ;

然后在解析之后,检查侦听器是否相同,如果不同,则可能会抛出错误。

    

© www.soinside.com 2019 - 2024. All rights reserved.