Quel est le problème avec cet exemple de grammaire Python ANTLR 3 ?
Question
J'essaie d'apprendre à utiliser ANTLR, et il semble que j'ai rencontré une erreur en suivant ce "tutoriel" :https://theantlrguy.atlassian.net/wiki/display/ANTLR3/Five+minute+introduction+to+ANTLR+3
Essentiellement, je crée le fichier SimpleCalc.g :
grammar SimpleCalc;
options {
language = Python;
}
tokens {
PLUS = '+' ;
MINUS = '-' ;
MULT = '*' ;
DIV = '/' ;
}
@header {
import sys
import traceback
from SimpleCalcLexer import SimpleCalcLexer
}
@main {
def main(argv, otherArg=None):
char_stream = ANTLRFileStream(sys.argv[1])
lexer = SimpleCalcLexer(char_stream)
tokens = CommonTokenStream(lexer)
parser = SimpleCalcParser(tokens);
try:
parser.expr()
except RecognitionException:
traceback.print_stack()
}
/*------------------------------------------------------------------
* PARSER RULES
*------------------------------------------------------------------*/
expr : term ( ( PLUS | MINUS ) term )* ;
term : factor ( ( MULT | DIV ) factor )* ;
factor : NUMBER ;
/*------------------------------------------------------------------
* LEXER RULES
*------------------------------------------------------------------*/
NUMBER : (DIGIT)+ ;
WHITESPACE : ( '\t' | ' ' | '\r' | '\n'| '\u000C' )+ { $channel = HIDDEN; } ;
fragment DIGIT : '0'..'9' ;
Quand j'exécute les outils ANTLR
java -classpath antlr-3.1.3.jar antlr.Tool SimpleCalc.g
Je reçois des erreurs, en commençant par la première ligne :
ANTLR Parser Generator Version 2.7.7 (20060906) 1989-2005
SimpleCalc.g:2:1: unexpected token: grammar
error: Token stream error reading grammar(s):
SimpleCalc.g:15:1: unexpected char: '@'
SimpleCalc.g:2:1: rule grammar trapped:
SimpleCalc.g:2:1: unexpected token: grammar
TokenStreamException: unexpected char: '@'
Cela me porte à croire que je fais quelque chose de stupide, mais je ne sais pas vraiment quoi.
La solution
Vous utilisez le mauvais Tool
classe pour générer le lexer et l’analyseur.La plupart des versions ANTLR 3.x ont encore des dépendances avec l'ancienne version v2.7, qui est donc incluse dans la v3.x.Le Tool
la classe de la v2.7 est appelée antlr.Tool
, alors que la version v3.x s'appelle org.antlr.Tool
.Ce dernier est celui que vous devriez utiliser :
java -classpath antlr-3.1.3.jar org.antlr.Tool SimpleCalc.g
MODIFIER
Voici une petite démo basée sur la grammaire du Wiki, mais avec un peu de code Python ajouté qui évalue l'expression :
grammar SimpleCalc;
options {
language=Python;
}
@header {
import sys
import traceback
from SimpleCalcLexer import SimpleCalcLexer
}
@main {
def main(argv, otherArg=None):
char_stream = ANTLRStringStream(sys.argv[1])
lexer = SimpleCalcLexer(char_stream)
tokens = CommonTokenStream(lexer)
parser = SimpleCalcParser(tokens);
try:
print parser.eval()
except RecognitionException:
traceback.print_stack()
}
eval returns [value]
: add EOF {$value = $add.value}
;
add returns [value]
: m1=mult {$value = $m1.value} ( '+' m2=mult {$value += $m2.value}
| '-' m2=mult {$value -= $m2.value}
)*
;
mult returns [value]
: a1=atom {$value = $a1.value} ( '*' a2=atom {$value *= $a2.value}
| '/' a2=atom {$value /= $a2.value}
)*
;
atom returns [value]
: NUMBER {$value = float($NUMBER.text)}
| '(' add ')' {$value = $add.value}
;
NUMBER : DIGIT+ ('.' DIGIT*)?;
WHITESPACE : ('\t' | ' ' | '\r' | '\n')+ {$channel = HIDDEN;};
fragment DIGIT : '0'..'9' ;
Générer un lexer/analyseur et évaluer une expression :
java -cp antlr-3.1.3.jar org.antlr.Tool SimpleCalc.g
python SimpleCalcParser.py "5 * (8 + 2)"
produit le résultat :
50.0