2010-09-26 4 views
2

Je le code suivant écrit en ANTLRWorks 1,4Quel est le problème avec cette grammaire? (ANTLRWorks 1.4)

grammar hmm; 

s   : (put_a_in_b)|(put_out_a)|(drop_kick)|(drop_a)|(put_on_a); 

put_a_in_b : (PUT_SYN)(ID)(IN_SYN)(ID); 
put_out_a : (PUT2_SYN)(OUT_SYN)(ID) | (E1)(ID); 
drop_kick : ('drop')('kick')(ID); 
drop_a  : (DROP_SYN)(ID); 
put_on_a : (E2)(ID); 

PUT_SYN  : 'put' | 'place' | 'drop'; 
PUT2_SYN : 'put' | 'douse'; 
IN_SYN  : 'in' | 'into' | 'inside' | 'within';  
OUT_SYN  : 'out'; 
E1   : 'extinguish'|'douse'; 
DROP_SYN : 'drop' | 'throw' | 'relinquish'; 
WS   : (' ' | '\t' | '\r' | '\n') {$channel=HIDDEN;}; 
ID   : ('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*; 
E2   : 'put on'|'don'|'wear'; 
COMMENT 
    : '//' ~('\n'|'\r')* '\r'? '\n' {$channel=HIDDEN;} 
    | '/*' (options {greedy=false;} : .)* '*/' {$channel=HIDDEN;} 
    ; 

Quand je lance avec l'entrée:

drop object 

je reçois un MismatchedTokenException (5 = 15!).

Et avec l'entrée:

put o1 in o2 

je reçois un NoViableAltException.

Bien qu'il fonctionne très bien avec

place o2 in o2 

Je suis nouveau à cela, mais il semble qu'il y ait des ambiguïtés? Ou peut-être que mon utilisation d'ANTLR est incorrecte?

+0

-t-elle poignée « mis sur l'objet '? Qu'en est-il de 'jeter objet'? –

+0

(Ceci est "rikki", le questionneur qui avait des problèmes à se connecter sur un autre ordinateur, mais je suis connecté maintenant.) Oui, ceux-ci sont bien analysés. – Rao

Répondre

2

Vous avez mis 'drop' et 'put' dans deux règles de Lexer différentes:

PUT_SYN : 'put' | 'place' | 'drop';   // drop & put 
PUT2_SYN : 'put' | 'douse';     //  put 
... 
DROP_SYN : 'drop' | 'throw' | 'relinquish'; // drop 

Lorsque put est rencontrée par le lexer, PUT_SYN sera toujours la règle qui correspond, donc 'put' pourrait (ou devrait) être supprimé de la règle PUT2_SYN.

Ainsi, votre problème avec l'analyse de la chaîne drop object: l'analyseur essayera de correspondre drop_a : (DROP_SYN)(ID); mais le "drop" sera adaptée à la règle de lexer PUT_SYN.

EDIT

peuvent être mieux Les synonymes listes faites dans les règles de l'analyseur (au lieu de Lexer règles). Voici une petite démo:

grammar TextAdventure; 

parse 
    : command (EndCommand command)* EOF 
    ; 

command 
    : put_syn_1 OtherWord in_syn OtherWord 
    | put_syn_2 out_syn_1 OtherWord 
    | out_syn_2 OtherWord 
    | Drop Kick OtherWord 
    | drop_syn OtherWord 
    ; 

drop_syn 
    : Drop 
    | Throw 
    | Relinquish 
    ; 

in_syn 
    : In 
    | Into 
    | Inside 
    | Within 
    ; 

put_syn_1 
    : Put 
    | Place 
    | Drop 
    ; 

put_syn_2 
    : Put 
    | Douse 
    ; 

out_syn_1 
    : Out 
    ; 

out_syn_2 
    : Extinguish 
    | Douse 
    ; 

Space  : (' ' | '\t' | '\r' | '\n'){$channel=HIDDEN;}; 
EndCommand : ';'; 
Put  : 'put'; 
Place  : 'place'; 
Drop  : 'drop'; 
Douse  : 'douse'; 
In   : 'in'; 
Into  : 'into'; 
Inside  : 'inside'; 
Within  : 'within';  
Out  : 'out'; 
Extinguish : 'extinguish'; 
Throw  : 'throw'; 
Relinquish : 'relinquish'; 
Kick  : 'kick'; 
OtherWord : ('a'..'z' | 'A'..'Z')+; 

Lors de l'interprétation de la source suivante:

drop object ; put yourself in myshoes ; place it in avase 

vous verrez ANTLRWorks générer l'analyse syntaxique-arborescence suivante:

alt text

+0

Semble plausible ... quelle est la solution de contournement - pour obtenir les différentes alternatives? Utilisez un non-terminal pour 'drop' (et un autre pour 'put') et ensuite construire les alternatives en utilisant ce non-terminal? –

+0

Merci pour l'explication, Bart. Moi aussi je m'interroge sur une solution de contournement. – Rao

+0

La solution est de factoriser cette communalité et de mettre le mot-clé 'put' dans sa propre règle. Quelque chose comme 'PUT_SYN: 'put' (PUT_CMD); PUT_CMD: (ID) ... | (OUT_SYN) ...; 'C'est juste un exemple de ce que je veux dire par" factoriser ". – linuxuser27

Questions connexes