2010-07-18 5 views
1

Je suis en train de mettre en œuvre un commentaire imbriqué dans D.Un problème antlr avec des commentaires intégrés

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

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

Pour moi, il serait logique que cela devrait fonctionner ...

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 

Quelqu'un pourrait-il expliquer ces messages d'erreur à moi et le correctif?

Merci.

Répondre

2

AFAIK, l'erreur est parce que nestingBlockCommentCharacterspeut match de +/ (deux fois ~'/').

Personnellement, je garderais le nestingBlockComment comme une règle de lexer au lieu d'une règle d'analyseur. Vous pouvez le faire en ajoutant un peu helper dans la classe lexer:

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

puis dans un lexer commentaire règle, utilisez un gated semantic predicates avec cette méthode d'aide comme l'expression booléenne dans le prédicat:

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

// match any character 
Any 
    : . 
    ; 

une petite démo-grammaire:

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 
    : . 
    ; 

et une classe principale pour le tester:

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(); 
    } 
} 

Ensuite, les commandes suivantes:

 
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 

(pour Windows, la dernière commande est: java -cp .;antlr-3.2.jar Main)

produire la sortie suivante:

 
comment :: /+ comment /+ and +/ comment +/ 
comment :: /+ comment +/ 
Questions connexes