Christophe Jacquet: Research and Teaching

Enseignement > Exemples en Java >

ANTLR : interpréter des chaînes de caractères (parsing)

ANTLR est un générateur de lexeurs et parseurs de flux de caractères. Certes, ANTLR donne la possibilité de transformer automatiquement des flux de caractères en structures hiérarchiques, les arbres de syntaxe abstraite (AST). Cependant, ces AST sont construits à partir d'objets fournis par ANTLR, et pas à partir des types métiers des applications.

Cet exemple montre comment il est possible de créer directement une hiérarchie d'objets métiers grâce à ANTRL. L'idée est de transformer des expressions mathématiques, données sous forme de chaînes, directement en hiérarchie d'objets.

Les fichiers comprennent :

Si vous utilisez l'environnement de développement Eclipse, je ne peux que vous recommander le plugin ANTLR pour Eclipse.

// ############################################################################
// 
// expr.g : grammaire ANTLR destinee a generer directement des objets metiers
//          lors du parsing d'expressions mathematiques bien parenthesees,
//          construites a base de nombres entiers et d'operateurs + et *
//
// Exemple d'expression reconnue : (2 + 13) * 4 +7
// 
// Auteur : Christophe Jacquet, Supelec
// 
// Historique
// 2007-02-26  Creation
// 
// ############################################################################


header {
	package parsing;
	
	import expression.*;
}

class ExprParser extends Parser;

expr returns [Expression e = null]
{Expression x;}
	:   e=mexpr 
		(PLUS x=mexpr {e = new Plus(e, x);}
		)*
    ;      

mexpr returns [Expression e = null]
{Expression x;}    
    :   e=atom (STAR x=atom {e = new Fois(e, x);})*
    ;    

atom returns [Expression e = null]
	:   i:INT { e = new Entier(Integer.parseInt(i.getText())); } 
    |   LPAREN e=expr RPAREN 
    ;


class ExprLexer extends Lexer;

options {
    k=2; // lookahead
    charVocabulary='\u0000'..'\u007F'; // caract. ASCII
}

LPAREN: '(' ;
RPAREN: ')' ;
PLUS  : '+' ;
STAR  : '*' ;
INT   : ('0'..'9')+ ;
WS    : ( ' '
        | '\r' '\n'
        | '\n'
        | '\t'
        )
        {$setType(Token.SKIP);}
      ;    
/* ############################################################################
 * 
 * Expression.java : classe abstraite pour représenter des expressions
 *                   mathématiques
 * 
 * Auteur : Christophe Jacquet, Supélec
 * 
 * Historique
 * 2007-02-26  Création
 * 
 * ############################################################################
 */

package expression;

public abstract class Expression {
	public abstract int eval();
}
/* ############################################################################
 * 
 * Entier.java : sous-classe d'Expression pour représenter des constantes
 *               entières
 * 
 * Auteur : Christophe Jacquet, Supélec
 * 
 * Historique
 * 2007-02-26  Création
 * 
 * ############################################################################
 */

package expression;

public class Entier extends Expression {
	int i;
	
	public Entier(int i) {
		this.i = i;
	}
	
	public int eval() {
		return i;
	}
	
	public String toString() {
		return Integer.toString(i);
	}

}
/* ############################################################################
 * 
 * Plus.java : représentation de sommes d'expressions mathématiques
 * 
 * Auteur : Christophe Jacquet, Supélec
 * 
 * Historique
 * 2007-02-26  Création
 * 
 * ############################################################################
 */

package expression;

public class Plus extends Expression {
	private final Expression a, b;
	
	public Plus(Expression a, Expression b) {
		this.a  = a;
		this.b = b;
	}
	
	@Override
	public int eval() {
		return a.eval()+b.eval();
	}
	
	@Override
	public String toString() {
		return "(" + a + " + " + b + ")";
	}

}
/* ############################################################################
 * 
 * Fois.java : représentation de produits d'expressions mathématiques
 * 
 * Auteur : Christophe Jacquet, Supélec
 * 
 * Historique
 * 2007-02-26  Création
 * 
 * ############################################################################
 */

package expression;

public class Fois extends Expression {
	private final Expression a, b;
	
	public Fois(Expression a, Expression b) {
		this.a  = a;
		this.b = b;
	}
	
	@Override
	public int eval() {
		return a.eval()*b.eval();
	}
	
	@Override
	public String toString() {
		return a + " * " + b;
	}

}
import parsing.ExprLexer;
import parsing.ExprParser;
import expression.Expression;

/* ############################################################################
 * 
 * TestExpression : programme principal pour tester le parsing d'expressions
 *                  textuelles grâce à une grammaire ANTLR, ce qui permet de
 *                  les transformer en hiérarchies d'objets de type Expression,
 *                  puis simplement de les évaluer. 
 * 
 * Auteur : Christophe Jacquet, Supélec
 * 
 * Historique
 * 2007-02-26  Création
 * 
 * ############################################################################
 */
public class TestExpression {
    public static void main(String[] args) throws Exception {
        ExprLexer lexer = new ExprLexer(System.in);
        ExprParser parser = new ExprParser(lexer);
        Expression e = parser.expr();
        System.out.println(e);
        System.out.println(">> " + e.eval());
    }
}