1

我正在尝试在 D 中实现嵌套注释。

nestingBlockComment
 : '/+' (options {greedy=false;} :nestingBlockCommentCharacters)* '+/' {$channel=HIDDEN;}; // line 58

  nestingBlockCommentCharacters
   :  (nestingBlockComment| '/'~'+' | ~'/' ) ; //line 61

对我来说,这应该是合乎逻辑的......

This is the error message I get:
[21:06:34] warning(200): d.g:58:64: Decision can match input such as "'+/'" using multiple alternatives: 1, 2
As a result, alternative(s) 1 were disabled for that input
[21:06:34] warning(200): d.g:61:7: Decision can match input such as "'/+'" using multiple alternatives: 1, 3
As a result, alternative(s) 3 were disabled for that input

有人可以向我解释这些错误消息和修复吗?

谢谢。

4

1 回答 1

2

AFAIK,错误是因为nestingBlockCommentCharacters 可以匹配+/~'/'两次)。

就个人而言,我会保留nestingBlockComment作为词法分析器规则而不是解析器规则。您可以通过在 lexer 类中添加一个小辅助方法来做到这一点:

public boolean openOrCloseCommentAhead() {
  // return true iff '/+' or '+/' is ahead in the character stream
}

然后在词法分析器注释规则中,使用带有该辅助方法的门控语义谓词作为谓词内的布尔表达式:

// match nested comments
Comment
  :  '/+' (Comment | {!openOrCloseCommentAhead()}?=> Any)* '+/'
  ;

// match any character
Any
  :  .
  ;

一个小演示语法:

grammar DComments;

@lexer::members {
  public boolean openOrCloseCommentAhead() {
    return (input.LA(1) == '+' && input.LA(2) == '/') ||
           (input.LA(1) == '/' && input.LA(2) == '+');
  }
}

parse
  :  token+ EOF
  ;

token
  :  Comment {System.out.println("comment :: "+$Comment.text);}
  |  Any
  ;

Comment
  :  '/+' (Comment | {!openOrCloseCommentAhead()}?=> Any)* '+/'
  ;

Any
  :  .
  ;

和一个主要的类来测试它:

import org.antlr.runtime.*;

public class Main {
    public static void main(String[] args) throws Exception {
        ANTLRStringStream in = new ANTLRStringStream(
            "foo /+ comment /+ and +/ comment +/ bar /+ comment +/ baz");
        DCommentsLexer lexer = new DCommentsLexer(in);
        CommonTokenStream tokens = new CommonTokenStream(lexer);
        DCommentsParser parser = new DCommentsParser(tokens);
        parser.parse();
    }
}

然后是以下命令:

java -cp antlr-3.2.jar org.antlr.Tool DComments.g
javac -cp antlr-3.2.jar *.java
java -cp .:antlr-3.2.jar 主要

(对于 Windows,最后一个命令是java -cp .;antlr-3.2.jar Main:)

产生以下输出:

评论 :: /+ 评论 /+ 和 +/ 评论 +/
评论 :: /+ 评论 +/
于 2010-07-18T20:10:21.237 回答