2009-04-26 10 views
5

Je m'apprends à utiliser JavaCC dans un projet de loisir, et j'ai une grammaire simple pour écrire un analyseur. Une partie de l'analyseur comprend les éléments suivants:Explication et solution pour l'avertissement de JavaCC "Choix d'expression rationnelle: FOO ne peut jamais être apparié comme: BAR"?

TOKEN : { < DIGIT : (["0"-"9"]) > } 
TOKEN : { < INTEGER : (<DIGIT>)+ > } 
TOKEN : { < INTEGER_PAIR : (<INTEGER>){2} > } 
TOKEN : { < FLOAT : (<NEGATE>)? <INTEGER> | (<NEGATE>)? <INTEGER> "." <INTEGER> | (<NEGATE>)? <INTEGER> "." | (<NEGATE>)? "." <INTEGER> > } 
TOKEN : { < FLOAT_PAIR : (<FLOAT>){2} > } 
TOKEN : { < NUMBER_PAIR : <FLOAT_PAIR> | <INTEGER_PAIR> > } 
TOKEN : { < NEGATE : "-" > } 

Lors de la compilation avec JavaCC je reçois la sortie:

Warning: Regular Expression choice : FLOAT_PAIR can never be matched as : NUMBER_PAIR 

Warning: Regular Expression choice : INTEGER_PAIR can never be matched as : NUMBER_PAIR 

Je suis sûr que c'est un concept simple mais je ne comprends pas l'avertissement, être un novice dans la génération de l'analyseur et dans les expressions régulières.

Que signifie cet avertissement (dans les termes as-novice-as-you-get-get)?

Répondre

4

Je ne connais pas JavaCC, mais je suis un ingénieur compilateur.

La règle FLOAT_PAIR est ambiguë. Considérez le texte suivant:

0.0 

Cela pourrait être suivi par FLOAT 0FLOAT .0; ou il pourrait être FLOAT 0. suivi de FLOAT 0; les deux entraînant FLOAT_PAIR. Ou il pourrait s'agir d'un seul FLOAT 0.0. Cependant, plus important encore, vous utilisez l'analyse lexicale avec la composition d'une manière qui ne fonctionnera probablement jamais. Considérez ce numéro:

12345 

Cela pourrait être analysé comme INTEGER 12, INTEGER 345 entraînant une INTEGER_PAIR. Ou il pourrait être analysé comme INTEGER 123, INTEGER 45, un autre INTEGER_PAIR. Ou il pourrait être INTEGER 12345, un autre jeton. Le problème existe parce que vous n'exigez pas d'espace entre les éléments lexicaux du INTEGER_PAIR (ou FLOAT_PAIR).

Vous ne devriez presque jamais essayer de gérer des paires comme celle-ci dans la lexer. Au lieu de cela, vous devez gérer les nombres simples (INTEGER et FLOAT) comme des jetons, et gérer des choses comme la négation et l'appariement dans l'analyseur, où les espaces ont été traités et supprimés.

(Par exemple, comment allez-vous traiter "----42"?Ceci est une expression valide dans la plupart des langages de programmation, qui calculeront correctement plusieurs négations, mais ne seront pas traitées par votre lexer.)

Notez également que les entiers à un chiffre de votre lexer ne correspondent pas à INTEGER, ils sortiront comme DIGIT. Je ne connais pas la syntaxe correcte pour que JavaCC corrige cela pour vous, cependant. Ce que vous voulez, c'est définir DIGIT non pas comme un jeton, mais simplement quelque chose que vous pouvez utiliser dans les définitions d'autres jetons; alternativement, incorporer la définition de DIGIT ([0-9]) directement où vous utilisez DIGIT dans vos règles.

0

Je n'ai pas utilisé JavaCC, mais il est possible que NUMBER_PAIR soit ambigu.

Je pense que le problème se résume au fait que la même chose exacte peut correspondre à la fois FLOAT_PAIR et INTEGER_PAIR puisque FLOAT peut correspondre à un INTEGER.

Mais ceci est juste une supposition avoir jamais vu la syntaxe JavaCC :)

+0

Je ne suis pas sûr de cela, j'ai changé Float afin qu'il ne puisse pas correspondre Integer - {)? "." | ()? "." | ()? "." >}, et a quand même reçu l'avertissement. Je suis surpris par ça, parce que ce que tu as dit me semblait parfaitement logique :) – Grundlefleck

+0

Hmm ... Je pense toujours que c'est lié à l'ambiguïté mais honnêtement, puisque je n'ai pas essayé JavaCC je ne suis d'aucune utilité pour toi ici ... Je vais différer et j'espère que quelqu'un qui le sait répondra. – Uri

0

Cela signifie probablement que pour chaque FLOAT_PAIR vous aurez juste un jeton FLOAT_PAIR, jamais un jeton NUMBER_PAIR. La règle FLOAT_PAIR correspond déjà à toutes les entrées et JavaCC n'essaiera pas de trouver d'autres règles de correspondance. Ce serait mon interprétation, mais je ne connais pas JavaCC, alors prenez-le avec un grain de sel.

Peut-être que vous pouvez spécifier en quelque sorte que NUMBER_PAIR est la production principale et que vous ne voulez pas obtenir d'autres jetons comme résultats.

0

Merci à la réponse de Barry Kelly, la solution que je suis venu avec est:

SKIP : { < #TO_SKIP : " " | "\t" > } 
    TOKEN : { < #DIGIT : (["0"-"9"]) > } 
    TOKEN : { < #DIGITS : (<DIGIT>)+ > } 
    TOKEN : { < INTEGER : <DIGITS> > } 
    TOKEN : { < INTEGER_PAIR : (<INTEGER>) (<TO_SKIP>)+ (<INTEGER>) > } 
    TOKEN : { < FLOAT : (<NEGATE>)?<DIGITS>"."<DIGITS> | (<NEGATE>)?"."<DIGITS> > } 
    TOKEN : { < FLOAT_PAIR : (<FLOAT>) (<TO_SKIP>)+ (<FLOAT>) > } 
    TOKEN : { < #NUMBER : <FLOAT> | <INTEGER> > } 
    TOKEN : { < NUMBER_PAIR : (<NUMBER>) (<TO_SKIP>)+ (<NUMBER>) >} 
    TOKEN : { < NEGATE : "-" > } 

Je l'avais complètement oublié d'inclure l'espace qui est utilisé pour séparer les deux jetons, je l'ai aussi utilisé le Symbole "#" qui arrête l'appariement des jetons, et qui est simplement utilisé dans la définition des autres jetons. Ce qui précède est compilé par JavaCC sans avertissement ni erreur. Cependant, comme l'a noté Barry, il existe des raisons de ne pas le faire.