代码之家  ›  专栏  ›  技术社区  ›  Aftershock

嵌入注释的antlr问题

  •  1
  • Aftershock  · 技术社区  · 14 年前

    我正在尝试在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 回复  |  直到 14 年前
        1
  •  2
  •   Community CDub    8 年前

    好吧,这个错误是因为 nestingBlockCommentCharacters 可以 比赛 +/ (the) ~'/' 两次)。

    nestingBlockComment 作为lexer规则而不是解析器规则。可以通过在lexer类中添加一个小helper方法来实现:

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

    然后在lexer注释规则中,使用 gated semantic predicates 将该helper方法作为谓词中的布尔表达式:

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