嵌入式注释的antlr问题

时间:2010-07-18 19:15:32

标签: antlr antlr3

我正在尝试在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

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

感谢。

1 个答案:

答案 0 :(得分:2)

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

就个人而言,我会将nestingBlockComment保留为词法分析器规则而不是解析器规则。您可以通过在词法分析器类中添加一个小助手方法来实现:

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

然后在词法分析器注释规则中,使用带有帮助器方法的gated semantic predicates作为谓词中的布尔表达式:

// 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 Main

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

产生以下输出:

comment :: /+ comment /+ and +/ comment +/
comment :: /+ comment +/