// This class belongs to the following package: package agg.parser; import java.util.EmptyStackException; import java.util.Enumeration; import java.util.Hashtable; import java.util.Iterator; import java.util.Stack; import java.util.Vector; import agg.xt_basis.BadMappingException; import agg.xt_basis.BaseFactory; import agg.xt_basis.Graph; import agg.xt_basis.GraphObject; import agg.xt_basis.MorphCompletionStrategy; import agg.xt_basis.Node; import agg.xt_basis.Arc; import agg.xt_basis.Match; import agg.xt_basis.OrdinaryMorphism; import agg.xt_basis.Rule; import agg.xt_basis.TypeException; import agg.util.Pair; //****************************************************************************+ /** * This class provides a parser which needs critical pairs. The criticl pair * must be <code>ExcludePair</code>. So objects has to be instaciated with * <code>ExcludePairContainer</code>. To be independent of a grammar it is * necessary to instanciate a object with a host graph and stop graph * seperately. * * @author $Author: olga $ * @version $Id: ExcludeParser.java,v 1.17 2010/08/18 09:26:52 olga Exp $ */ public class ExcludeParser extends AbstractParser implements Runnable { /** * Main part of a backtracking algorithm */ protected Stack<Object> stack; protected boolean stop; protected boolean correct; /** * Creates a new parser. This parser uses critical pair analysis for * optimized parsing. * * @param grammar * The graph grammar. * @param hostGraph * The host graph. * @param stopGraph * The stop graph. * @param excludeContainer * The critical pairs. */ public ExcludeParser(agg.xt_basis.GraGra grammar, Graph hostGraph, Graph stopGraph, ExcludePairContainer excludeContainer) { super(grammar, hostGraph, stopGraph, excludeContainer); this.stack = new Stack<Object>(); this.stop = false; } // ****************************************************************************+ /** * Starts the parser. The result is true if the parser can parse the graph * * @return true if the graph can be parsed. */ @SuppressWarnings("rawtypes") public boolean parse() { System.out.println("Starting exclude parser with CPA ... "); this.correct = true; fireParserEvent(new ParserMessageEvent(this, "Starting exclude parser ...")); Hashtable<Rule, Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>> conflictFree = null; try { fireParserEvent(new ParserMessageEvent(this, "Computting conflict free pairs. Please wait ...")); conflictFree = this.pairContainer .getContainer(CriticalPair.CONFLICTFREE); fireParserEvent(new ParserMessageEvent(this, "Computting conflict free pairs done")); } catch (InvalidAlgorithmException iae) { fireParserEvent(new ParserErrorEvent(iae, "ERROR: " + iae.getMessage())); return false; } Hashtable<Rule, Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>> exclude = null; try { fireParserEvent(new ParserMessageEvent(this, "Computting exclude pairs. Please wait ...")); exclude = this.pairContainer.getContainer(CriticalPair.EXCLUDE); fireParserEvent(new ParserMessageEvent(this, "Computting exclude pairs done")); } catch (InvalidAlgorithmException iae) { fireParserEvent(new ParserErrorEvent(iae, "ERROR: " + iae.getMessage())); return false; } Hashtable<Rule, Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>> conflictFreeLight = new Hashtable<Rule, Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>>(); Hashtable<Rule, Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>> excludeLight = new Hashtable<Rule, Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>>(); makeLightContainer(exclude, excludeLight); makeLightContainer(conflictFree, conflictFreeLight); /* * makeLightContainer kann nur die Elemente filtern, in denen alle teile * false liefern. Mischformen fallen durch */ for (Enumeration<Rule> keys = conflictFreeLight.keys(); keys .hasMoreElements();) { Object key = keys.nextElement(); if (excludeLight.containsKey(key)) { conflictFreeLight.remove(key); } } /* * haelt alle Matche, die kritisch sind, damit nicht an einer Stelle * immer wieder angesetzt wird */ RuleInstances eri = new RuleInstances(); fireParserEvent(new ParserMessageEvent(this, "Parser initialized")); while (!this.stop && !this.graph.isIsomorphicTo(this.stopGraph) && this.correct) { boolean ruleApplied = false; /* zuerst sollen alle konfliktfreien Regeln probiert werden. */ for (Enumeration<Rule> keys = conflictFreeLight.keys(); keys .hasMoreElements() && !ruleApplied;) { Rule r = keys.nextElement(); // System.out.println("try to apply rule: "+r.getName()); fireParserEvent(new ParserMessageEvent(this, "Searching for simple match")); Match m = BaseFactory.theFactory().createMatch(r, getHostGraph()); m.setCompletionStrategy((MorphCompletionStrategy) this.grammar .getMorphismCompletionStrategy().clone(), true); while (!ruleApplied && m.nextCompletion()) { if (m.isValid()) { if (applyRule(m)) { ruleApplied = true; try { Thread.sleep(this.delay); } catch (InterruptedException ex1) { } } } } m.dispose(); } // end for(Enumeration keys = conflictFreeLight.keys(); /* Die konfliktfreien Regeln sind abgearbeitet */ /* Die Excluderegeln muessen ueberprueft werden */ if (!ruleApplied && !this.stop) { /* * Zuerst wird ein beliebiger Ansatz einer Regel gesucht. Dann * muss der Ansatz geprueft werden, ob ein Ueberlappungsgraph * mit diesem Ansatz eingebettet werden kann. Findet sich keine * Einbettung, so kann die Regel angewendet werden. Sonst wird * nach einem anderen Ansatz gesucht. */ Match savedMatch = null; for (Enumeration<Rule> keys = excludeLight.keys(); keys .hasMoreElements() && !ruleApplied && !this.stop;) { Rule r = keys.nextElement(); // System.out.println("try to apply rule: "+r.getName()); Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> inclusions = findInclusions(r, CriticalPair.EXCLUDE); fireParserEvent(new ParserMessageEvent(this, "Searching for difficult match")); Match m = BaseFactory.theFactory().createMatch(r, getHostGraph()); m.setCompletionStrategy((MorphCompletionStrategy) this.grammar .getMorphismCompletionStrategy().clone(), true); boolean validMatch = false; while (!ruleApplied && m.nextCompletion()) { if (m.isValid()) { if (!isMatchCritic(m, inclusions)) { if (applyRule(m)) { ruleApplied = true; try { Thread.sleep(this.delay); } catch (InterruptedException ex1) { } } } else { if (!validMatch && savedMatch == null) { if (!eri.isIn(m)) { validMatch = true; savedMatch = m; } } } } // end if(m.isValid()) } if (!validMatch) { /* * Match darf nur geloescht werden, wenn er nicht * savedMatch ist */ BaseFactory.theFactory().destroyMatch(m); } } // end for(Enumeration keys = excludeLight.keys(); /* * wenn keine Regel angewendet wurde, dann kann nur noch eine * kritische Regel angewendet werden. */ if (!ruleApplied && (savedMatch != null) && !this.stop) { OrdinaryMorphism copyMorph = getHostGraph().isomorphicCopy(); if (copyMorph != null) { fireParserEvent(new ParserMessageEvent(copyMorph, "IsoCopy")); eri.add(savedMatch); /* * ERI muss nicht kopiert werden, da nur an * Entscheidungsstellen der Match/die Matches gemerkt werden * mssen, die uns m�licherweise auf einen Holzweg fhren. Der * Match in ERI ist eine Stufe tiefer (also nach * Regelanwendung, denn wir loeschen) nicht mehr verfgbar. * Dadurch kann ein neues ERI erzeugt werden. Auf dem Stack * liegen dann nur die Ableitungen, die uns in eine * Sackgasse gefhrt haben. */ Pair<Graph, RuleInstances> tmpPair = new Pair<Graph, RuleInstances>( getHostGraph(), eri); this.stack.push(tmpPair); eri = new RuleInstances(); /* * Die Regel muss auf den kopierten Graphen mit DEMSELBEN * kopierten Match angewendet werden. */ setHostGraph(copyMorph.getImage()); OrdinaryMorphism tmpMorph = savedMatch.compose(copyMorph); Match n = tmpMorph.makeMatch(savedMatch.getRule()); n.setCompletionStrategy((MorphCompletionStrategy) this.grammar .getMorphismCompletionStrategy().clone(), true); boolean notFound = false; while (!n.isValid() && !notFound) { if (!n.nextCompletion()) notFound = true; } if (!notFound) { if (applyRule(n)) { ruleApplied = true; try { Thread.sleep(this.delay); } catch (InterruptedException ex1) { } } } } } // end if(!ruleApplied && (savedMatch != null) if (!ruleApplied) { try { Pair<?,?> tmpPair = (Pair) this.stack.pop(); /* backtrack */ setHostGraph((Graph)tmpPair.first); eri = (RuleInstances)tmpPair.second; } catch (EmptyStackException ioe) { /* Stack ist leer */ fireParserEvent(new ParserErrorEvent(this, "ERROR: This graph is not part of the language")); this.correct = false; } } // end if(!ruleApplied } // end if(!ruleApplied } // end while(!graph.isIsomorphicWith(stopGraph) && correct /* Fertig mit den Excluderegeln */ while (!this.stack.empty()) { try { fireParserEvent(new ParserMessageEvent(this, "Cleaning stack.")); Pair<?,?> tmpPair = (Pair) this.stack.pop(); Graph g = (Graph)tmpPair.first; g.dispose(); tmpPair.second = null; } catch (EmptyStackException ioe) { } } fireParserEvent(new ParserMessageEvent(this, "Stopping parser. Result is " + this.correct + ".")); return this.correct; } /** * Clears some internal stuff. */ protected void finalize() { getHostGraph().dispose(); } /* MUSs in ExcludePairContainer gehoert */ /** * A container stores all pairs with the information if two rules critic or * not. This method filters all pairs that are not critic. * * @param in * The complete container. * @param out * The new filtered container. */ protected void makeLightContainer( Hashtable<Rule, Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>> in, Hashtable<Rule, Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>> out) { // Report.println("-------------------------------------------",Report.CONTAINER); Enumeration<Rule> keys = in.keys(); while (keys.hasMoreElements()) { Rule key = keys.nextElement(); if (key != null) { // Report.println("erster key "+key,Report.CONTAINER); Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>> value = in .get(key); // Report.println("erster Wert "+value,Report.CONTAINER); boolean allTrue = true; Enumeration<Rule> keys2 = value.keys(); while (keys2.hasMoreElements() && allTrue) { Rule key2 = keys2.nextElement(); if (key == key2) continue; // Report.println("zweiter key "+key2,Report.CONTAINER); Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>> p = value.get(key2); // Report.println("zweiter Wert "+p,Report.CONTAINER); Boolean first = p.first; // allTrue = allTrue && first.booleanValue(); if (first.booleanValue()) { if (out.containsKey(key)) { Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>> secondPart = out .get(key); secondPart.put(key2, p); } else { Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>> secondPart = new Hashtable<Rule, Pair<Boolean, Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>>>>(); secondPart.put(key2, p); out.put(key, secondPart); } } } } // else System.out.println("ExcludeParser.makeLightContainer key == // null"); /* * if(allTrue){ out.put(key,value); } */ } } /* finds all inclusions from the value of the exclude hashtable */ /** * Returns all inclusion of the overlapping of a given rule into the host * graph. * * @param r1 * The rule * @param kind * The critical pair algorithm. * @return A set of morphisms from the overlapping graph into the host * graph. */ protected Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> findInclusions(Rule r1, int kind) { Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> resultVector = new Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>>(); Vector<Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>>> criticVector = null; try { criticVector = this.pairContainer.getCriticalSet(kind, r1); } catch (InvalidAlgorithmException iae) { fireParserEvent(new ParserErrorEvent(this, "Cannot get Container")); return resultVector; } for (int i = 0; i < criticVector.size(); i++) { Pair<Pair<OrdinaryMorphism, OrdinaryMorphism>, Pair<OrdinaryMorphism, OrdinaryMorphism>> p = criticVector.elementAt(i); // Pair result = new Pair(p.first.first, p.first.second); Pair<OrdinaryMorphism, OrdinaryMorphism> morphisms = p.first; if (p.second != null) { if (morphisms.first.getSource() == r1 .getRight()) { // handle produce-forbid overlapping Graph overlap = morphisms.first.getImage(); OrdinaryMorphism overlapIso = overlap.isomorphicCopy(); if (overlapIso != null) { Iterator<?> e = morphisms.first.getSource().getArcsSet().iterator(); while (e.hasNext()) { Arc obj = (Arc) e.next(); if (!r1.getInverseImage(obj).hasMoreElements()) { try { overlapIso.getTarget() .destroyObject(overlapIso.getImage(morphisms.first.getImage(obj))); } catch (TypeException exc) {} } } e = morphisms.first.getSource().getNodesSet().iterator(); while (e.hasNext()) { Node obj = (Node) e.next(); if (!r1.getInverseImage(obj).hasMoreElements()) { try { overlapIso.getTarget() .destroyObject(overlapIso.getImage(morphisms.first.getImage(obj))); } catch (TypeException exc) {} } } OrdinaryMorphism matchMorph1 = r1.compose(morphisms.first).compose(overlapIso); Match match1 = BaseFactory.theFactory().makeMatch(r1, matchMorph1); // match1.getTarget().unsetTransientAttrValues(); morphisms.first = match1; // result = new Pair(match1, p.first.second); // System.out.println("RHS: makeMatch...: "+match1); } } } Graph overlapGraph = morphisms.first.getImage(); // Graph overlapGraph = result.first.getImage(); OrdinaryMorphism inclusion = BaseFactory.theFactory() .createMorphism(overlapGraph, getHostGraph()); boolean graphOk = false; while (inclusion.nextCompletion() && !graphOk) { if (inclusion.isTotal() && inclusion.isInjective()) { graphOk = true; resultVector.addElement(morphisms); // resultVector.addElement(result); } } BaseFactory.theFactory().destroyMorphism(inclusion); } return resultVector; } /** * Checks if a current match is critic. * * @param m * The match. * @param inclusions * The set of inclusions from overlapping graphs into the host * graph. * @return true if with this one rule exclude another rule. */ protected boolean isMatchCritic(Match m, Vector<Pair<OrdinaryMorphism, OrdinaryMorphism>> inclusions) { /* check3a */ // Report.trace("isMatchCritic: anfang",2); boolean critic = false; OrdinaryMorphism o = null; OrdinaryMorphism composed = null; for (int i = 0; i < inclusions.size(); i++) { // Report.println("ExcludeParser.isMatchCritic:: checke Inklusion #" // + i + " von " + inclusions.size(), Report.PARSER); Pair<OrdinaryMorphism, OrdinaryMorphism> morphisms = inclusions.elementAt(i); Graph overlapGraph = morphisms.first.getImage(); o = BaseFactory.theFactory().createMorphism(overlapGraph, getHostGraph()); OrdinaryMorphism overlapMorph = morphisms.first; OrdinaryMorphism inverted = overlapMorph.invert(); composed = inverted.compose(m); /* * agg.util.Debug.printlnMorph(m,"der Match m"); * agg.util.Debug.printlnMorph(overlapMorph,"overlapMorph"); * agg.util.Debug.printlnMorph(inverted,"inverted"); */ // System.out.println(i+": composed match: "+composed); while (composed.nextCompletion() && !critic) { /* agg.util.Debug.printlnMorph(composed,"composed"); */ Vector<GraphObject> leftNodes = new Vector<GraphObject>(); for (Enumeration<GraphObject> en = m.getDomain(); en.hasMoreElements();) { GraphObject grob = en.nextElement(); if (grob.isNode()) leftNodes.addElement(grob); } for (int k = 0; k < leftNodes.size(); k++) { Node n = (Node) leftNodes.elementAt(k); /* * System.out.println("versuche "+n+" "+k+" zu mappen auf * "+m.getImage(n)); */ try { o.addMapping(overlapMorph.getImage(n), m.getImage(n)); } catch (BadMappingException bme) { // System.err.println("ExcludeParser.isMatchCritic:: // small panic, but hopefully only performance lost"); // n+" an stelle "+k+" konnte nicht gemappt werden."); } } while (o.nextCompletion() && !critic) { // System.out.println("suche next Completion of overlap // morphism: "+(j++)); /* * agg.util.Debug.printlnMorph(o,"der o Morph"); * System.out.print("\t"+(j++)); */ if (o.isIsomorphicTo(composed)) critic = true; } } BaseFactory.theFactory().destroyMorphism(composed); BaseFactory.theFactory().destroyMorphism(o); } // Report.trace("isMatchCritic: Ende " + critic, -2); // System.out.println("isMatchCritic: Ende "+critic); return critic; } /** * Usually this method is invoked by the start method from the class <CODE>Thread</CODE>. * This method starts the parse method. */ public void run() { fireParserEvent(new ParserMessageEvent(this, "Thread - Parsing - runs ...")); parse(); if (this.stop) { fireParserEvent(new ParserMessageEvent(this, "Thread - Parsing - was stopped.")); this.stop = false; } else fireParserEvent(new ParserMessageEvent(this, "Thread - Parsing - finished. Result is " + this.correct + ".")); } /** * Stops the running. */ public void stop() { this.stop = true; } public boolean wasStopped() { return this.stop; } } // End of ExcludeParser.java /* * $Log: ExcludeParser.java,v $ * Revision 1.17 2010/08/18 09:26:52 olga * tuning * * Revision 1.16 2010/06/09 10:56:07 olga * tuning * * Revision 1.15 2010/03/04 14:11:13 olga * code optimizing * * Revision 1.14 2008/05/05 09:11:51 olga * Graph parser - bug fixed. * New AGG feature - Applicability of Rule Sequences - in working. * * Revision 1.13 2008/04/07 09:36:51 olga * Code tuning: refactoring + profiling * Extension: CPA - two new options added * * Revision 1.12 2007/11/05 09:18:22 olga * code tuning * * Revision 1.11 2007/11/01 09:58:17 olga * Code refactoring: generic types- done * * Revision 1.10 2007/10/22 09:03:17 olga * First implementation of CPA for grammars with node type inheritance. * Only for internal tests. * * Revision 1.9 2007/09/10 13:05:41 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/06/13 08:32:58 olga Update: * V161 * * Revision 1.7 2007/04/11 10:03:36 olga Undo, Redo tuning, Simple Parser- bug * fixed * * Revision 1.6 2007/03/28 10:00:58 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.5 2006/11/09 10:31:05 olga Matching error fixed * * Revision 1.4 2006/03/13 10:04:42 olga CPA tuning * * Revision 1.3 2006/03/02 12:03:23 olga CPA: check host graph - done * * Revision 1.2 2006/03/01 09:55:46 olga - new CPA algorithm, new CPA GUI * * Revision 1.1 2005/08/25 11:56:57 enrico *** empty log message *** * * Revision 1.1 2005/05/30 12:58:03 olga Version with Eclipse * * Revision 1.4 2004/12/20 14:53:48 olga Changes because of matching * optimisation. * * Revision 1.3 2004/01/28 17:58:38 olga Errors suche * * Revision 1.2 2003/03/05 18:24:08 komm sorted/optimized import statements * * Revision 1.1.1.1 2002/07/11 12:17:23 olga Imported sources * * Revision 1.11 2001/07/04 10:45:34 olga Mehr Testarbeit. * * Revision 1.10 2001/06/18 13:37:46 olga Bei Critical Pair ein neuer Menuitem: * Debug, wo man einzelne Regelpaare testen kann. System.gc() eingefuegt. * * Revision 1.9 2001/06/13 16:49:35 olga Parser Classen Optimierung. * * Revision 1.8 2001/05/31 11:57:55 olga Zusaetzliche Parser Meldungen fuer GUI * eingefuegt. * * Revision 1.7 2001/05/14 12:03:00 olga Zusaetzliche Parser Events Aufrufe * eingebaut, um bessere Kommunikation mit GUI Status Anzeige zu ermoeglichen. * * Revision 1.6 2001/04/11 14:59:19 olga Stop Method eingefuegt. * * Revision 1.5 2001/03/29 12:01:34 olga MorphCompletionStrategy: dangling * condition wieder ON * * Revision 1.4 2001/03/22 15:53:26 olga Zusaetzliche Events Meldungen * eingebaut. * * Revision 1.3 2001/03/14 17:32:05 olga nur Tests * * Revision 1.1.2.16 2001/01/28 13:14:53 shultzke API fertig * * Revision 1.1.2.15 2001/01/03 09:45:00 shultzke TODO's bis auf laden und * speichern erledigt. Wann meldet sich endlich Michael? * * Revision 1.1.2.14 2001/01/02 12:28:58 shultzke Alle Optionen angebunden * * Revision 1.1.2.13 2001/01/01 21:24:32 shultzke alle Parser fertig inklusive * Layout * * Revision 1.1.2.12 2000/12/26 10:00:03 shultzke Layered Parser hinzugefuegt * * Revision 1.1.2.11 2000/12/04 12:26:47 shultzke drei parser stehen zur * verfuegung * * Revision 1.1.2.10 2000/11/28 09:54:50 shultzke stack aufgeraeumt nach parsing * * Revision 1.1.2.9 2000/11/27 13:16:45 shultzke referenzparser SimpleParser * implementiert * * Revision 1.1.2.8 2000/11/14 14:02:11 shultzke check3a(isMatchCritic) bug * fixed * * Revision 1.1.2.7 2000/11/08 14:58:02 shultzke parser erste stufe fertig * * Revision 1.1.2.6 2000/11/06 14:02:36 shultzke der Parser laeuft, wenn auch * langsam * ---------------------------------------------------------------------- * * Revision 1.1.2.5 2000/11/02 14:50:14 shultzke der konfliktteil des parsers * wird etwas trickreich * * Revision 1.1.2.4 2000/11/01 14:55:25 shultzke conflictfree part fast fertig * * Revision 1.1.2.3 2000/11/01 12:19:21 shultzke erste Regelanwendung im parser * CVs: ---------------------------------------------------------------------- * * Revision 1.1.2.2 2000/10/25 13:43:44 shultzke parser start dialog * * Revision 1.1.2.1 2000/09/18 14:11:24 shultzke erstes Geruest des Parsers * erstellt. Und parallelen Ablauf der ExcludePairs synchronisiert * */