2017-06-13 3 views
2

J'ai la production suivante:Comment dire à ANTLR de préférer une alternative à l'autre?

expression 
    : primary # stubLabel 
    | expression '.' Identifier # stubLabel 
    | expression '.' 'this' # stubLabel 
    | expression '.' 'new' nonWildcardTypeArguments? innerCreator # stubLabel 
    | expression '.' 'super' superSuffix # stubLabel 
    | expression '.' explicitGenericInvocation # stubLabel 
    | expression '[' expression ']' # stubLabel 
    | Identifier arguments # namedMethodInvocation 
    | expression '.' Identifier arguments # namedMethodInvocation 
    | expression arguments # unnamedMethodInvocation 
    | // Lots of other patterns... 
    ; 

Je souhaite faire l'analyseur essayer les modèles namedMethodInvocation avant d'essayer unnamedMethodInvocation. Cela ne se produit pas automatiquement car ANTLR essaie de choisir l'alternative avec la correspondance la plus longue, au lieu d'utiliser une première politique de correspondance. Comment puis-je le forcer à le faire?

éditer: Désolé, j'ai oublié de publier le lien vers le fichier de grammaire ci-dessus. Here c'est.

+0

Veuillez indiquer la règle de production «primaire». – saka1029

+0

@ saka1029 Je suis tellement désolé, j'ai négligé de lier le fichier de grammaire complète dans mon message! Le fichier de grammaire peut être trouvé [ici] (https://github.com/antlr/grammars-v4/blob/master/java/Java.g4#L540). La règle de production «primaire» est [ici] (https://github.com/antlr/grammars-v4/blob/master/java/Java.g4#L540). –

+0

Dans les règles d'analyseur, les alts sont testés un par un, de haut en bas (comme écrit dans la grammaire) et le premier correspondant gagne. La commande des alts est une affaire en soi, car elle détermine un certain nombre de choses (par exemple, la précédence). –

Répondre

0

Essayez de déplacer namedMethodInvocation à primary règle de production (avant Identifier) comme ceci.

primary 
    : '(' expression ')' 
    | 'this' 
    | 'super' 
    | literal 
    | Identifier arguments // namedMethodInvocation 
    | Identifier 
    | typeType '.' 'class' 
    | 'void' '.' 'class' 
    | nonWildcardTypeArguments (explicitGenericInvocationSuffix | 'this' arguments) 
    ; 

Ou déplacer primary au dernier expression.

expression 
    : expression '.' Identifier 
    ..... 
    | Identifier arguments // namedMethodInvocation 
    | expression arguments // unnamedMethodInvocation 
    ..... 
    | primary 
    ; 

Ou insérer une nouvelle règle primaryOrNamedMethodInvocation.

expression 
    : primaryOrNamedMethodInvocation 
    | expression '.' Identifier 
    ..... 
    ; 

primaryOrNamedMethodInvocation 
    : Identifier arguments // namedMethodInvocation 
    | primary 
    ; 
+0

saka1029, je ne veux pas faire cela parce que ça n'a aucun sens que 'namedMethodInvocation' soit un primaire. 'namedMethodInvocation' est supposé correspondre à une expression comme' foo.bar() ', qui est trop complexe pour être un primaire. –

+0

Ajout d'une autre solution. – saka1029

+0

saka1029, je ne pense pas que cela affecterait les résultats car ANTLR choisit une alternative en fonction de sa durée, et non de son ordre dans la production. –