Das ANTLR Eclipse-Plugin
Für den beliebten Parsergenerator ANTLR gibt es unter http://www.javadude.com/tools/antlr3-eclipse/ ein praktisches Plugin. Der Update-Manger von Eclipse wird auf die URL gelegt, installiert und neu gestartet. Anschließend geht man im Projekt auf das Kontextmenü und aktiviert Add/Remove ANTLR 3 Nature.
Als nächstes kann man eine ANTLR-Datei ablegen. Auf der Doku-Seite vom Plugin wird eine Grammatik (Datei Expr.g3) angegeben, die hier — leicht überarbeitet — angegeben werden soll:
grammar Expr;@header {package com.tutego.script.fp;import java.util.HashMap;}@lexer::header {package com.tutego.script.fp;}@members { HashMap memory = new HashMap();}prog: stat + ;stat: expr NEWLINE { System.out.println( $expr.value ); } | ID '=' expr NEWLINE { memory.put( $ID.text, $expr.value ); } | NEWLINE ;expr returns [int value]: e = multExpr { $value = $e.value; } ( '+' e = multExpr { $value += $e.value; } | '-' e = multExpr { $value -= $e.value; } )* ;multExpr returns [int value]: e = atom { $value = $e.value; } ( '*' e = atom { $value *= $e.value; } )* ; atom returns [int value]: INT { $value = Integer.parseInt($INT.text); } | ID { Integer v = memory.get( $ID.text ); if ( v!=null ) $value = v.intValue(); else System.err.println( "Undefined variable " + $ID.text ); } | '(' expr ')' {$value = $expr.value;} ;ID: ('a'..'z' | 'A'..'Z') + ;INT: '0'..'9' + ;NEWLINE: '\r' ? '\n' ;WS: (' ' | '\t') + { skip(); } ;
Bearbeiten lässt sich die Grammatik in Eclipse nicht ordentlich, doch dafür dient ja die ANTLRWorks: The ANTLR GUI Development Environment.
Das Schöne beim Plugin: Es generiert automatisch im Hintergrund den Parser und Lexer. Das Testprogramm ist schnell geschrieben:
package com.tutego.script.fp; import org.antlr.runtime.*; public class FpRunner{public static void main( String[] args ) throws Exception{ ExprLexer lex = new ExprLexer( new ANTLRStringStream("age=34\nage*2\n12*111\n") ); ExprParser parser = new ExprParser( new CommonTokenStream( lex ) ); try{parser.prog();}catch ( RecognitionException e ){e.printStackTrace();}}}
Die Ausgabe ist dann
68 1332