package agg.attribute.parser.javaExpr;
import java.awt.Frame;
import java.awt.TextField;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.Color;
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileDescriptor;
import java.io.FileOutputStream;
import java.io.PrintStream;
import agg.attribute.handler.AttrHandlerException;
import agg.attribute.handler.SymbolTable;
/**
* @version $Id: Jex.java,v 1.18 2010/09/23 08:15:01 olga Exp $
* @author $Author: olga $
*/
public class Jex implements ActionListener {
static final long serialVersionUID = 1L;
static public final int PARSE_ERROR = 0;
static public final int IS_CONSTANT = 1;
static public final int IS_VARIABLE = 2;
static public final int IS_COMPLEX = 3;
protected TextField typeTF;
static protected JexParser parser;
protected PrintStream out, err;
protected ByteArrayOutputStream redirect;
protected PrintStream redirectOut;
protected boolean isOutput = false; // true;
protected Object variableExpression;
public Jex() {
}
/* Testing environment */
public static void main(String args[]) {
Jex me = new Jex();
SimpleNode.setClassResolver(new ClassResolver());
Frame frame = new Frame("Jex-Test");
me.typeTF = new TextField("", 30);
me.typeTF.setBackground(Color.WHITE);
me.typeTF.addActionListener(me);
frame.add(me.typeTF);
frame.pack();
frame.setVisible(true);
}
public void fullTest(String line) {
try {
test_interpret(line, null, null);
} catch (AttrHandlerException ex1) {
System.out.println(ex1.getMessage());
ex1.printStackTrace();
}
}
public void actionPerformed(ActionEvent e) {
String line = this.typeTF.getText();
if (line.compareTo("q") == 0) {
System.exit(0);
}
fullTest(line);
}
protected int getExprProperty() {
synchronized (JexParser.jjtree) {
SimpleNode node = (SimpleNode) JexParser.jjtree.rootNode();
int result = IS_COMPLEX;
if (node.isConstantExpr()) {
result = IS_CONSTANT;
} else if (node.jjtGetNumChildren() == 1) {
node = (SimpleNode) node.jjtGetChild(0);
if (node.identifier.equals("PrimaryExpression")
&& node.jjtGetNumChildren() == 1) {
node = (SimpleNode) node.jjtGetChild(0);
if (node.identifier.equals("Id")) {
result = IS_VARIABLE;
}
}
}
return result;
}
}
protected void newStdOutStream() {
FileOutputStream fdOut = new FileOutputStream(FileDescriptor.out);
System.setOut(new PrintStream(new BufferedOutputStream(fdOut, 128),
true));
}
protected void newStdErrStream() {
FileOutputStream fdErr = new FileOutputStream(FileDescriptor.err);
System.setErr(new PrintStream(new BufferedOutputStream(fdErr, 128),
true));
}
protected void antiRedirect() {
newStdOutStream();
newStdErrStream();
}
/**
* Swaps StdOut and StdErr to ByteStream and vice versa
*
* @see #redirectToString
* @see #restoreOutputStream
*/
protected void swapPrintStream() {
PrintStream swapOut = System.out;
PrintStream swapErr = System.err;
System.setOut(this.out);
System.setErr(this.err);
this.out = swapOut;
this.err = swapErr;
}
protected void redirectToString() {
this.out = System.out;
this.err = System.err;
this.redirect = new ByteArrayOutputStream();
this.redirectOut = new PrintStream(this.redirect);
System.setOut(this.redirectOut);
System.setErr(this.redirectOut);
}
protected void restoreOutputStream() {
if (this.redirect != null && this.redirectOut != null) {
System.setOut(this.out);
System.setErr(this.err);
if (this.isOutput) {
System.out.println(this.redirect.toString());
}
this.redirect = null;
this.redirectOut = null;
}
}
static public String addMessage(Exception ex) {
String msg = ex.getMessage();
if (msg == null || msg.equals("null")) {
return "";
}
return "\n (" + msg + ")";
}
/* Services for JexHandler */
public void parseOutputOn() {
this.isOutput = true;
}
public void parseOutputOff() {
this.isOutput = false;
}
public int parse(String text) throws AttrHandlerException {
// swapPrintStream();
// AttrSession.logPrintln(VerboseControl.logTrace, "Jex:\n->parse");
// AttrSession.logPrintln(VerboseControl.logTrace, "Jex: text " + text);
// // only Jex parser tracing
// AttrSession.logPrintln(VerboseControl.logJexParser, "Jex:\n->parse");
// AttrSession
// .logPrintln(VerboseControl.logJexParser, "Jex: text " + text);
// swapPrintStream();
// redirectToString();
try {
return parse_(text);
} catch (Exception ex1) {
if (this.redirect != null)
throw new AttrHandlerException(this.redirect.toString()
+ addMessage(ex1));
throw new AttrHandlerException(addMessage(ex1));
} finally {
// restoreOutputStream();
// AttrSession.logPrintln(VerboseControl.logTrace, "Jex:\n<-parse");
// only Jex parser tracing
// AttrSession.logPrintln(VerboseControl.logJexParser, "Jex:\n<-parse");
}
}
protected String getPropertyText(int code) {
synchronized (this) {
if (code == IS_CONSTANT)
return "Constant expression";
if (code == IS_VARIABLE)
return "Variable";
if (code == IS_COMPLEX)
return "Complex expression";
return "Parse error";
}
}
protected int parse_(String text) throws ParseError {
// swapPrintStream();
// AttrSession.logPrintln(VerboseControl.logTrace, "Jex:\n->\tparse_");
// AttrSession.logPrintln(VerboseControl.logTrace, "Jex: text " + text);
// // only Jex parser tracing
// AttrSession.logPrintln(VerboseControl.logJexParser, "Jex:\n->\tparse_");
// AttrSession
// .logPrintln(VerboseControl.logJexParser, "Jex: text " + text);
// swapPrintStream();
int result = PARSE_ERROR;
String line = text + " ";
byte bytes[] = line.getBytes();
java.io.ByteArrayInputStream stream = new java.io.ByteArrayInputStream(
bytes);
synchronized (JexParser.jjtree) {
// if (parser == null) {
// parser = new JexParser(stream);
// } else
{
JexParser.ReInit(stream);
JexParser.jjtree.reset();
// System.out.println("parse text: "+text+" stack: "+SimpleNode.stack.size()+" top: "+SimpleNode.top+" :::: "+SimpleNode.stack.hashCode());
SimpleNode.top = -1;
SimpleNode.stack.clear();
// System.out.println("parse text: "+text+" stack: "+SimpleNode.stack.size()+" top: "+SimpleNode.top+" :::: "+SimpleNode.stack.hashCode());
}
try {
// AttrSession.logPrintln(VerboseControl.logJexParser, "Parsing ["
// + text + "] ...");
JexParser.CompilationUnit();
JexParser.jjtree.rootNode().dump(" ");
result = getExprProperty();
// AttrSession.logPrintln(VerboseControl.logJexParser,
// " Expression property: " + getPropertyText(result));
// // swapPrintStream();
// AttrSession.logPrintln(VerboseControl.logTrace, "Jex:\n<-\tparse_");
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Jex:\n<-\tparse_");
// swapPrintStream();
return result;
} catch (ParseError ex1) {
throw ex1;
}
}
}
public void check(Node ast, Class<?> type, SymbolTable symtab)
throws AttrHandlerException {
// AttrSession.logPrintln(VerboseControl.logJexParser, "Jex.check: "
// + ast + " " + type);
// redirectToString();
try {
SimpleNode.setSymbolTable(symtab);
try {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Type-Checking ...");
ast.checkContext();
this.variableExpression = ast;
} catch (ASTIdNotDeclaredException ex1) {
// AttrSession
// .logPrintln(VerboseControl.logJexParser, "Variable \""
// + ex1.getMessage() + "\" is not declared");
throw ex1;
} catch (ASTWrongTypeException ex2) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Wrong type.\n");
// if (ex2.getExpected() != null) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Required signature: " + ex2.getExpected());
// }
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Encountered: " + ex2.getFound());
throw ex2;
} catch (ASTMemberException ex3) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Exception:\n" + ex3.getMessage());
throw ex3;
} catch (Exception ex) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Exception:\n" + ex.getMessage());
throw new RuntimeException(ex.getMessage());
}
if (type != null && type != Void.TYPE) {
Class<?> resultType = ((SimpleNode) ast).getNodeClass();
boolean assignable = isAssignable(type, resultType);
if (assignable) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Types are assignable");
} else {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Wrong expression type.");
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Required: " + type.getName());
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Found: " + resultType.getName());
// unerklaerliches Ereignis.
new ASTWrongTypeException();
}
}
} catch (Exception ex1) {
if (this.redirect != null)
throw new AttrHandlerException(this.redirect.toString());
throw new AttrHandlerException(ex1.getMessage());
} finally {
// restoreOutputStream();
}
}
public void check(String text, Class<?> type, SymbolTable symtab)
throws AttrHandlerException {
// redirectToString();
try {
check_(text, type, symtab);
} catch (Exception ex1) {
if (this.redirect != null) {
// System.out.println("Jex.check:: 1) AttrHandlerException:
// "+ex1.getMessage() );
throw new AttrHandlerException(this.redirect.toString());
}
// System.out.println("Jex.check:: 2) AttrHandlerException:
// "+ex1.getMessage() );
throw new AttrHandlerException(ex1.getMessage());
} finally {
// restoreOutputStream();
}
}
public void check_(String text, Class<?> type, SymbolTable symtab)
throws ParseError {
parse_(text);
SimpleNode.setSymbolTable(symtab);
synchronized (JexParser.jjtree) {
try {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Type-Checking ...");
JexParser.jjtree.rootNode().checkContext();
JexParser.jjtree.rootNode().dump(" ");
} catch (ASTIdNotDeclaredException ex1) {
// AttrSession.logPrintln(VerboseControl.logJexParser, "Variable \""
// + ex1.getMessage() + "\" is not declared");
throw new ASTIdNotDeclaredException("Variable \""
+ ex1.getMessage() + "\" is not declared");
} catch (ASTWrongTypeException ex2) {
// AttrSession
// .logPrintln(VerboseControl.logJexParser, "Wrong type.\n");
// if (ex2.getExpected() != null) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Required signature: " + ex2.getExpected());
// }
// AttrSession.logPrintln(VerboseControl.logJexParser, "Encountered: "
// + ex2.getFound());
throw new ASTWrongTypeException(
"Wrong expression type. Required signature: "
+ ex2.getExpected() + " Encountered: "
+ ex2.getFound());
} catch (ASTMemberException ex3) {
// AttrSession.logPrintln(VerboseControl.logJexParser, "Exception:\n"
// + ex3.getMessage());
throw new ASTMemberException("Member Exception: "
+ ex3.getMessage());
} catch (Exception ex) {
// AttrSession.logPrintln(VerboseControl.logJexParser, "Exception:\n"
// + ex.getMessage());
throw new RuntimeException("Exception: " + ex.getMessage());
}
if (type != null && type != Void.TYPE) {
Class<?> resultType = ((SimpleNode) JexParser.jjtree.rootNode())
.getNodeClass();
if (!isAssignable(type, resultType)) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Wrong expression type.\n Required: " + type.getName()
// + "\n Found: " + resultType.getName());
throw new ASTWrongTypeException(
"Wrong expression type. Required: " + type.getName()
+ " Found: " + resultType.getName());
}
}
}
}
protected static Object refObj = new Object();
protected boolean isAssignable(Class<?> to, Class<?> from) {
// System.out.println("agg.parser.javaExpr.Jex.isAssignable
// "+from.getName()+" to "+to.getName());
if (to.isPrimitive() || from.isPrimitive()) {
// System.out.println("check: to.isPrimitive() ||
// from.isPrimitive()");
if (to == Byte.TYPE || to == Short.TYPE || to == Integer.TYPE
|| to == Long.TYPE) {
if (from == Byte.TYPE || from == Short.TYPE
|| from == Integer.TYPE || from == Long.TYPE) {
return true;
}
return false;
} else if (to == Float.TYPE || to == Double.TYPE) {
if (from == Float.TYPE || from == Double.TYPE) {
return true;
}
return false;
} else
return (to == from);
}
return to.isAssignableFrom(from) || from.isInstance(refObj);
}
protected Object test_interpret(String text, Class<?> type, SymbolTable symtab)
throws AttrHandlerException {
Object result;
// redirectToString();//
try {
result = interpret_(text, type, symtab);
} catch (ParseError ex1) {
if (this.redirect != null)
throw new AttrHandlerException(this.redirect.toString()
+ addMessage(ex1));
throw new AttrHandlerException(addMessage(ex1));
} finally {
// restoreOutputStream();//
}
return result;
}
/* ******************************************************************************* */
/**
* Interprets an expression.
*/
public Object interpret(Node ast, Class<?> type, SymbolTable symtab)
throws AttrHandlerException {
// AttrSession.logPrintln(VerboseControl.logTrace,
// "Jex: \n->interpret(ast)");
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Jex: \n->interpret(ast)");
try {
Object result = null;
check(ast, type, symtab);
// redirectToString();
try {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Evaluating ..." + ast);
ast.interpret();
result = ast.getRootResult();
/* If here, success */
return result;
} catch (ASTIdNotDeclaredException ex1) {
// AttrSession
// .logPrintln(VerboseControl.logJexParser, "Variable \""
// + ex1.getMessage() + "\" is not declared");
throw ex1;
} catch (ASTMissingValueException ex2) {
if (ast.getString().indexOf("==null") != -1) {
result = new Boolean(true); // ast.getRootResult();
return result;
}
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Missing value for variable \"" + ex2.getMessage()
// + "\".");
throw ex2;
} catch (ASTMemberException ex3) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "ASTMemberException " + ex3.getMessage());
throw ex3;
} catch (Exception ex) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Exception:\n" + ex.getMessage());
throw new AttrHandlerException("AttrHandlerException : "
+ ex.getMessage());
// throw new RuntimeException(ex.getMessage());
}
} catch (Exception ex1) {
// swapPrintStream();
// AttrSession.logPrintln(VerboseControl.logTrace,
// "Jex.interpret : AttrHandlerException geworfen");
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Jex.interpret: AttrHandlerException geworfen");
// swapPrintStream();
// if (this.redirect != null)
// throw new AttrHandlerException(this.redirect.toString());
throw new AttrHandlerException("AttrHandlerException : "
+ ex1.getMessage());
} finally {
// restoreOutputStream();
// AttrSession.logPrintln(VerboseControl.logTrace,
// "Jex: \n<-interpret(ast)");
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Jex: \n<-interpret(ast)");
}
}
/**
* Interprets an expression.
*
* @deprecated Strings are NOT sufficent to represent expressions
*/
public Object interpret(String text, Class<?> type, SymbolTable symtab)
throws AttrHandlerException {
// AttrSession.logPrintln(VerboseControl.logTrace, "Jex: \n->interpret()");
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Jex: \n->interpret()");
// redirectToString();
try {
return interpret_(text, type, symtab);
} catch (Exception ex1) {
// swapPrintStream();
// AttrSession.logPrintln(VerboseControl.logTrace,
// "Jex: AttrHandlerException geworfen");
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Jex: AttrHandlerException geworfen");
// swapPrintStream();
if (this.redirect != null)
throw new AttrHandlerException(this.redirect.toString());
throw new AttrHandlerException(ex1.getMessage());
} finally {
// restoreOutputStream();
// AttrSession.logPrintln(VerboseControl.logTrace,
// "Jex: \n<-interpret()");
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Jex: \n<-interpret()");
}
}
public Object interpret_(String text, Class<?> type, SymbolTable symtab)
throws ParseError {
// swapPrintStream();
// AttrSession.logPrintln(VerboseControl.logTrace,"Jex:\n->interpret_");
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Jex:\n->interpret_");
synchronized (JexParser.jjtree) {
if (JexParser.jjtree.rootNode() != null)
JexParser.jjtree.rootNode().dump("");
// swapPrintStream();
check_(text, type, symtab);
try {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Evaluating ...");
JexParser.jjtree.rootNode().interpret();
Object result = JexParser.jjtree.rootNode().getRootResult();
// String resultString = result == null ? "null" : result.toString();
// AttrSession.logPrintln(VerboseControl.logJexParser, "Result = "
// + resultString);
// swapPrintStream();
JexParser.jjtree.rootNode().dump("");
// AttrSession.logPrintln(VerboseControl.logJexParser, "Result = "
// + resultString);
// swapPrintStream();
/* If here, success */
return result;
} catch (ASTIdNotDeclaredException ex1) {
// AttrSession.logPrintln(VerboseControl.logJexParser, "Variable \""
// + ex1.getMessage() + "\" is not declared");
throw ex1;
} catch (ASTMissingValueException ex2) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Missing value for variable \"" + ex2.getMessage() + "\".");
/*
* ContextView cv = (ContextView) symtab; VarMember vm =
* ((VarTuple)cv.getVariables()).getVarMemberAt("x");
* System.out.println(vm.getExprAsText());
*
* if(parser.jjtree.rootNode().isVariable()){ swapPrintStream();
* System.out.println("eine Variable");
* parser.jjtree.rootNode().dump("->");
* parser.jjtree.rootNode().rewrite();
* System.out.println(parser.jjtree.rootNode().getClass());
* getAST().dump("ast: "); swapPrintStream(); return null; }else
*/
throw ex2;
} catch (ASTMemberException ex3) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "ASTMemberException " + ex3.getMessage());
throw ex3;
} catch (Exception ex) {
// AttrSession.logPrintln(VerboseControl.logJexParser, "Exception:\n"
// + ex.getMessage());
throw new RuntimeException(ex.getMessage());
} finally {
// swapPrintStream();
// AttrSession.logPrintln(VerboseControl.logTrace,
// "Jex:\n<-interpret_");
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Jex:\n<-interpret_");
// swapPrintStream();
}
}
}
/** Rewrites all variables */
public void rewrite(Node ast, Class<?> type, SymbolTable symtab)
throws AttrHandlerException {
// redirectToString();
try {
check(ast, type, symtab);
} catch (AttrHandlerException ahe) {
// AttrSession.logPrintln(VerboseControl.logJexParser,
// "Type-checking causes an error. Rewriting failed. "
// + ahe.getMessage());
// restoreOutputStream();
throw ahe;
} finally {
// restoreOutputStream();
}
ast.rewrite();
if (ast.getError().length() != 0)
throw new AttrHandlerException(ast.getError());
}
/** returns root node of the abstract syntax tree */
public Node getAST() {
return JexParser.jjtree.rootNode();
}
public Object getVariableExpression() {
return this.variableExpression;
}
}
/*
* $Log: Jex.java,v $
* Revision 1.18 2010/09/23 08:15:01 olga
* tuning
*
* Revision 1.17 2010/07/29 10:09:20 olga
* Array stack changed to Vector stack
*
* Revision 1.16 2010/04/28 15:16:13 olga
* tuning
*
* Revision 1.15 2010/03/31 21:10:49 olga
* tuning
*
* Revision 1.14 2010/03/18 18:17:01 olga
* synchronized - added
*
* Revision 1.13 2010/03/08 15:38:21 olga
* code optimizing
*
* Revision 1.12 2009/11/26 10:57:29 olga
* tests
*
* Revision 1.11 2007/11/05 09:18:23 olga
* code tuning
*
* Revision 1.10 2007/11/01 09:58:17 olga
* Code refactoring: generic types- done
*
* Revision 1.9 2007/09/10 13:05:48 olga
* In this update:
* - package xerces2.5.0 is not used anymore;
* - class com.objectspace.jgl.Pair is replaced by the agg own generic class agg.util.Pair;
* - bugs fixed in: usage of PACs in rules; match completion;
* usage of static method calls in attr. conditions
* - graph editing: added some new features
* Revision 1.8 2007/03/28 10:01:14 olga - extensive changes
* of Node/Edge Type Editor, - first Undo implementation for graphs and
* Node/edge Type editing and transformation, - new / reimplemented options for
* layered transformation, for graph layouter - enable / disable for NACs, attr
* conditions, formula - GUI tuning
*
* Revision 1.7 2006/12/13 13:32:58 enrico reimplemented code
*
* Revision 1.6 2006/08/09 07:42:18 olga API docu
*
* Revision 1.5 2006/08/02 09:00:57 olga Preliminary version 1.5.0 with -
* multiple node type inheritance, - new implemented evolutionary graph layouter
* for graph transformation sequences
*
* Revision 1.4 2006/04/03 08:57:50 olga New: Import Type Graph and some bugs
* fixed
*
* Revision 1.3 2006/03/01 09:55:47 olga - new CPA algorithm, new CPA GUI
*
* Revision 1.2 2006/01/16 09:37:01 olga Extended attr. setting
*
* Revision 1.1 2005/08/25 11:56:52 enrico *** empty log message ***
*
* Revision 1.2 2005/06/20 13:37:04 olga Up to now the version 1.2.8 will be
* prepared.
*
* Revision 1.1 2005/05/30 12:58:01 olga Version with Eclipse
*
* Revision 1.9 2005/03/21 09:22:57 olga ...
*
* Revision 1.8 2005/03/03 13:48:42 olga - Match with NACs and attr. conditions
* with mixed variables - error corrected - save/load class packages written by
* user - PACs : creating T-equivalents - improved - save/load matches of the
* rules (only one match of a rule) - more friendly graph/rule editor GUI - more
* syntactical checks in attr. editor
*
* Revision 1.7 2004/12/20 14:53:47 olga Changes because of matching
* optimisation.
*
* Revision 1.6 2003/03/05 18:24:14 komm sorted/optimized import statements
*
* Revision 1.5 2003/02/20 17:38:25 olga Tests
*
* Revision 1.4 2003/01/15 11:36:00 olga Neue VerboseControl Konstante
* :logJexParser zum Testen
*
* Revision 1.3 2002/12/20 11:25:47 olga Tests
*
* Revision 1.2 2002/11/25 14:56:36 olga Der Fehler unter Windows 2000 im
* AttributEditor ist endlich behoben. Es laeuft aber mit Java1.3.0 laeuft
* endgueltig nicht. Also nicht Java1.3.0 benutzen!
*
* Revision 1.1.1.1 2002/07/11 12:17:04 olga Imported sources
*
* Revision 1.11 2000/06/05 14:08:10 shultzke Debugausgaben fuer V1.0.0b
* geloescht
*
* Revision 1.10 2000/05/24 10:03:10 olga Nur Testausgaben eingebaut bei der
* Suche nach dem Fehler in DISAGG : Match Konstante auf Konstante
*
* Revision 1.9 2000/05/17 11:33:38 shultzke diverse Aenderungen. Version von
* Olga wird erwartet
*
* Revision 1.8 2000/04/05 12:10:51 shultzke serialVersionUID aus V1.0.0
* generiert
*
* Revision 1.7 2000/03/14 10:59:40 shultzke Transformieren von Variablen auf
* Variablen sollte jetzt funktionieren Ueber das Design der Copy-Methode des
* abstrakten Syntaxbaumes sollte unbedingt diskutiert werden.
*
* Revision 1.6 2000/03/03 11:32:45 shultzke Alphaversion von Variablen auf
* Variablen matchen
*/