2011-08-17 5 views
0

J'essaye de construire un analyseur pour un DSL que je construis en utilisant Irony dans .NET et j'ai trouvé un problème que je n'arrive pas à contourner. Depuis qu'il gère BNF, je pense que toute solution BNF sera utile.Faire face à l'ambiguïté dans la grammaire BNF

J'ai l'entrée suivante:

 
$10 yesterday at drug store 

Avec la grammaire suivante:

<expr> :== unit | expr + unit 
<unit> :== money | date | location 

<date> : == yesterday|today|tomorrow 
<location> :== .* | <preposition> .* 
<preposition> :== at 
<money> :== ((\$)?\d*((\.*)\d*)*\,?\d{1,2}) 

Il fonctionne comme un charme avec cette entrée. Je reçois exactement le résultat que je voulais qui est:

Money Amount: 10 
Date: Yesterday 
Location: Drug Store 

Cependant, si je change l'ordre de l'entrée comme suit

$10 at drug store yesterday 

en raison de réduire les étapes qu'il ne me donne la même sortie. La sortie devient:

Money amount: 10 
Location: Drug Store Yesterday 

Je me demandais s'il y a moyen de faire en sorte que Lieu (qui est un match de regex vraiment large) est évaluée uniquement lorsque tous les autres jetons sont capturés et rien d'autre est laissé.

Toute aide est appréciée.

Merci!

Edit: Titre Mise à jour selon la suggestion

+0

Ce n'est pas vraiment une question à propos de BNF, en soi. Dans une grammaire BNF, il n'y a pas de notion de "préséance" des règles. Ce que vous avez est une grammaire ambiguë; c'est-à-dire qu'il y a plus d'une dérivation de certaines chaînes dans votre langue. La seule façon pour BNF de résoudre ce problème est de proposer une grammaire sans ambiguïté, ce qui n'est pas toujours possible. Dans votre cas, la manière évidente d'essayer d'obtenir une grammaire non ambiguë est de définir afin que les chaînes contenant des éléments tels que "hier" soient capturées et non acceptées comme des emplacements valides. – Patrick87

+0

Merci @ Patrick87 pour le commentaire. En supposant que j'ai plus qu'hier pour "ignorer" dans la définition , comment suggérez-vous que je le fasse? Y a-t-il un moyen de dire "assortir ceci et exclure tout cela"? – tucaz

+0

Il existe des moyens faciles et des moyens difficiles de le faire; les moyens faciles dépendent des capacités de votre syntaxe regex, et les méthodes difficiles fonctionnent pour toutes les expressions régulières mais, eh bien, prenez un peu de travail à faire. Vous devriez vérifier votre syntaxe regex pour les opérateurs/opérations comme "set difference/except", "union", "intersection", "complement", etc. Si vous pouvez le faire, c'est facile; Sinon, vous devrez vous asseoir, construire un DFA acceptant les chaînes que vous voulez rejeter, construire le complément DFA, puis créer une regex basée sur ceci. Certains outils automatisés peuvent exister pour rendre ce processus moins douloureux. – Patrick87

Répondre

-1

Outre le fait que ce n'est pas une réponse générale à la BNF ambiguïté que j'ai pu résoudre mon problème avec Irony en créant un nouveau terminal.

Donc, si quelqu'un rencontre d'autre ce problème, le code pour le nouveau terminal (sans ajouté au projet principal Irony) se trouvent dans ce lien: http://irony.codeplex.com/discussions/269483

Merci