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 http://javadude.com/eclipse/update 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<String,Integer> memory = new HashMap<String,Integer>();
}
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