2010-10-20 23 views
1

Je travaille sur un projet pour l'école avec la conversion d'une forme BNF Decaf spec en une grammaire sans contexte et la construction dans ANTLR. J'y ai travaillé pendant quelques semaines et je suis allée chez le professeur quand je suis coincé, mais j'ai finalement rencontré quelque chose qui, selon lui, ne devrait pas causer d'erreur. Voici la partie isolée de ma grammaire, expr est le point de départ. Avant de faire cela, j'ai une question.ambiguïté ANTLR dans DeCaf - professeur ne sait pas où l'erreur est

Est-ce que cela importe si mes règles lexer apparaissent avant mes règles d'analyseur dans ma grammaire, ou si elles sont mélangées par intermittence à travers mon fichier de grammaire?

calloutarg:   expr | STRING; 
expr: multexpr ((PLUS|MINUS) multexpr)* ; 
multexpr : atom ((MULT|DIVISION) atom)* 
; 

atom : OPENPAR expr CLOSEPAR | ID ((OPENBRACKET expr CLOSEBRACKET)? | OPENPAR ((expr (COMMA)*)+)? CLOSEPAR)| 
CALLOUT OPENPAR STRING (COMMA (calloutarg)+ COMMA)? CLOSEPAR | constant; 
constant: INT | CHAR | boolconstant; 
boolconstant: TRUE|FALSE; 

La mise en forme est laide parce qu'une partie de ses conseils pour le débogage était de prendre des règles individuelles et les décomposer où l'ambiguïté est de voir où les erreurs commencent. Dans ce cas, il est dit que le problème est dans la partie ID longue, que OPENBRACKET et OPENPAR sont la cause. Si vous avez des idées, je suis profondément reconnaissant. Merci, et désolé pour la façon dont le formatage est désagréable sur le code que j'ai posté.

Répondre

1

t-il si mes règles apparaissent devant mes analyseurs lexicaux règles de l'analyseur dans ma grammaire ...

Non, ça ne fait rien.

Le problème est que l'intérieur de votre règle atom, ANTLR ne peut pas faire un choix entre ces trois variantes:

  1. ID (...
  2. ID [ ...
  3. ID

sans avoir recours à (peut-être) retour en arrière. Vous pouvez le résoudre en utilisant des prédicats syntaxiques (qui ressemblent à: (...)=> ...). Un prédicat syntaxique n'est rien de plus qu'un «regard vers l'avenir» et si ce «regard vers l'avant» est un succès, il choisit ce chemin particulier.

Votre règle actuelle atom peut être réécrite comme suit:

atom 
    : OPENPAR expr CLOSEPAR 
    | ID OPENPAR ((expr (COMMA)*)+)? CLOSEPAR 
    | ID OPENBRACKET expr CLOSEBRACKET 
    | ID 
    | CALLOUT OPENPAR STRING (COMMA (calloutarg)+ COMMA)? CLOSEPAR 
    | constant 
    ; 

Et avec les prédicats il ressemblera:

atom 
    : OPENPAR expr CLOSEPAR 
    | (ID OPENPAR)=>  ID OPENPAR ((expr (COMMA)*)+)? CLOSEPAR 
    | (ID OPENBRACKET)=> ID OPENBRACKET expr CLOSEBRACKET 
    | ID 
    | CALLOUT OPENPAR STRING (COMMA (calloutarg)+ COMMA)? CLOSEPAR 
    | constant 
    ; 

qui devrait faire l'affaire.

Remarque: ne faites pas utilisez ANTLRWorks pour générer ou tester l'analyseur! Il ne peut pas gérer les prédicats (bien). Il vaut mieux le faire sur la ligne de commande.

Voir aussi: https://wincent.com/wiki/ANTLR_predicates


EDIT

Nous allons étiqueter les six différentes "branches" de votre règle atomA-F:

atom               // branch 
    : OPENPAR expr CLOSEPAR          // A 
    | ID OPENBRACKET expr CLOSEBRACKET       // B 
    | ID OPENPAR ((expr COMMA*)+)? CLOSEPAR      // C 
    | ID               // D 
    | CALLOUT OPENPAR STRING (COMMA calloutarg+ COMMA)? CLOSEPAR // E 
    | constant             // F 
    ; 

Maintenant, lorsque le (futur) parser devrait gérer l'entrée comme ceci:

ID OPENPAR expr CLOSEPAR 

ANTLR ne sait pas comment l'analyseur doit le gérer. Il pourrait être analysé de deux manières différentes:

  1. branche D suivie par branche A
  2. branche C

Quelle est la source de la ANTLR d'ambiguïté se plaint. Si vous deviez commenter l'une des branches A, C ou D, l'erreur disparaîtrait.

Espérons que ça aide.

+0

Merci pour votre aide! Une question que j'ai eue, pourquoi mon affacturage de gauche ne prendrait pas soin de l'ID | ID [| ID (problème? – Nick

+0

@Nick, voir le ** EDIT ** à ma réponse. –