| ConstraintGroup |

    1   /*
    2    *  ConstraintGroup.java - transducer class
    3    *
    4    *  Copyright (c) 1998-2001, The University of Sheffield.
    5    *
    6    *  This file is part of GATE (see http://gate.ac.uk/), and is free
    7    *  software, licenced under the GNU Library General Public License,
    8    *  Version 2, June 1991 (in the distribution as file licence.html,
    9    *  and also available at http://gate.ac.uk/gate/licence.html).
    10   *
    11   *  Hamish Cunningham, 24/07/98
    12   *
    13   *  $Id: ConstraintGroup.java,v 1.8 2001/09/13 12:09:50 kalina Exp $
    14   */
    15
    16
    17  package gate.jape;
    18
    19  import java.util.*;
    20  import gate.annotation.*;
    21  import gate.util.*;
    22  import gate.*;
    23
    24
    25  /**
    26    * A sequence of conjunctions of PatternElement that form a
    27    * disjunction.
    28    */
    29  public class ConstraintGroup
    30  extends PatternElement implements JapeConstants, java.io.Serializable
    31  {
    32    /** Debug flag */
    33    private static final boolean DEBUG = false;
    34
    35    /** Anonymous constructor. */
    36    public ConstraintGroup() {
    37      patternElementDisjunction1 = new ArrayList();
    38      currentConjunction = new ArrayList();
    39      patternElementDisjunction1.add(currentConjunction);
    40    } // Anonymous constructor
    41
    42    /** Need cloning for processing of macro references. See comments on
    43      * <CODE>PatternElement.clone()</CODE>
    44      */
    45    public Object clone() {
    46      ConstraintGroup newPE = (ConstraintGroup) super.clone();
    47
    48      // created by createDisjunction
    49      newPE.currentConjunction = null;
    50
    51      newPE.patternElementDisjunction1 = new ArrayList();
    52      // for each (conjunction) member of the pattern element discjunction
    53      for(
    54        Iterator disjunction = patternElementDisjunction1.iterator();
    55        disjunction.hasNext();
    56
    57      ) {
    58
    59        newPE.createDisjunction();
    60        // for each pattern element making up this conjunction
    61        for(
    62          Iterator conjunction = ((ArrayList) disjunction.next()).iterator();
    63          conjunction.hasNext();
    64
    65        ) {
    66          PatternElement pat = (PatternElement) conjunction.next();
    67
    68          newPE.addPatternElement((PatternElement) pat.clone());
    69        } // for each element of the conjunction
    70      } // for each conjunction (element of the disjunction)
    71
    72      return newPE;
    73    } // clone
    74
    75    /** An array of arrays that represent PatternElement conjunctions
    76      * during parsing of the .jape. Each conjunction is
    77      * considered as being disjunct with the next. (I.e. they are
    78      * or'd, in the same way as expressions around "||" in C and
    79      * Java.) Set during parsing; replaced by finish().
    80      */
    81    private ArrayList patternElementDisjunction1;
    82
    83    /** The pattern element disjunction for transduction - Java arrays. */
    84    private PatternElement[][] patternElementDisjunction2;
    85
    86    /** An array of PatternElements making up a conjunction. It is a member of
    87      * patternElementDisjunction. This is the one we're adding to
    88      * at present. Used during parsing, not matching.
    89      */
    90    private ArrayList currentConjunction;
    91
    92    /** Make a new disjunction at this point. */
    93    public void createDisjunction() {
    94      currentConjunction = new ArrayList();
    95      patternElementDisjunction1.add(currentConjunction);
    96    } // createDisjunction
    97
    98    /** Add an element to the current conjunction. */
    99    public void addPatternElement(PatternElement pe) {
    100     currentConjunction.add(pe);
    101   } // addPatternElement
    102
    103   /** Get an list of CPEs that we contain. */
    104   protected Iterator getCPEs() {
    105     ArrayList cpes = new ArrayList();
    106
    107     // for each (conjunction) member of the pattern element discjunction
    108     for(
    109       Iterator disjunction = patternElementDisjunction1.iterator();
    110       disjunction.hasNext();
    111     ) {
    112       // for each pattern element making up this conjunction
    113       for(
    114         Iterator conjunction = ((ArrayList) disjunction.next()).iterator();
    115         conjunction.hasNext();
    116       ) {
    117         PatternElement pat = (PatternElement) conjunction.next();
    118
    119         Iterator i = null;
    120         if(pat instanceof ComplexPatternElement) {
    121           cpes.add(pat);
    122           i = ((ComplexPatternElement) pat).getCPEs();
    123         }
    124         else if(pat instanceof ConstraintGroup)
    125           i = ((ConstraintGroup) pat).getCPEs();
    126
    127         if(i != null)
    128           for( ; i.hasNext(); )
    129             cpes.add(i.next());
    130       } // for each element of the conjunction
    131     } // for each conjunction (element of the disjunction)
    132
    133     return cpes.iterator();
    134   } // getCPEs
    135
    136   /** Finish: replace dynamic data structures with Java arrays; called
    137     * after parsing.
    138     */
    139   public void finish() {
    140
    141     // index into patternElementDisjunction2
    142     int i = 0;
    143
    144     // index into the conjunctions (second dimension of pED2)
    145     int j = 0;
    146
    147     patternElementDisjunction2 =
    148       new PatternElement[patternElementDisjunction1.size()][];
    149
    150     // for each (conjunction) member of the pattern element discjunction
    151     for(
    152       Iterator disjuncIter = patternElementDisjunction1.iterator();
    153       disjuncIter.hasNext();
    154       i++
    155     ) {
    156       ArrayList conjunction = (ArrayList) disjuncIter.next();
    157       patternElementDisjunction2[i] = new PatternElement[conjunction.size()];
    158       j = 0;
    159
    160       // for each pattern element making up this conjunction
    161       for(
    162         Iterator conjIter = conjunction.iterator();
    163         conjIter.hasNext();
    164         j++
    165       ) {
    166         patternElementDisjunction2[i][j] = (PatternElement) conjIter.next();
    167         patternElementDisjunction2[i][j].finish();
    168       } // loop on conjunction
    169
    170     } // loop on patternElementDisjunction1
    171
    172     patternElementDisjunction1 = null;
    173   } // finish
    174
    175   /** Access to the annotations that have been matched by this group. */
    176   public AnnotationSet getMatchedAnnots() {
    177     AnnotationSet matchedAnnots = new AnnotationSetImpl((Document) null);
    178     int pEDLen = patternElementDisjunction2.length;
    179
    180     // for each (conjunction) member of the pattern element disjunction
    181     for(int i = 0; i < pEDLen; i++) {
    182       int conjLen = patternElementDisjunction2[i].length;
    183
    184       // for each pattern element making up this conjunction
    185       for(int j = 0; j < conjLen; j++) {
    186         PatternElement pat = patternElementDisjunction2[i][j];
    187         AnnotationSet patMatchedAnnots = pat.getMatchedAnnots();
    188         if(patMatchedAnnots != null)
    189           matchedAnnots.addAll(pat.getMatchedAnnots());
    190       } // for each element of the conjunction
    191
    192     } // for each conjunction (element of the disjunction)
    193
    194     return matchedAnnots;
    195   } // getMatchedAnnots
    196
    197
    198   /** Clear all the annotations that have been matched by this group. */
    199   public void reset() {
    200     // Debug.pr(this, "CG reset, matchHistory.size() = " + matchHistory.size());
    201     int pEDLen = patternElementDisjunction2.length;
    202
    203     // for each (conjunction) member of the pattern element disjunction
    204     for(int i = 0; i < pEDLen; i++) {
    205       int conjLen = patternElementDisjunction2[i].length;
    206
    207       // for each pattern element making up this conjunction
    208       for(int j = 0; j < conjLen; j++)
    209         patternElementDisjunction2[i][j].reset();
    210     }
    211
    212     super.reset(); // should be redundant: there for if PE.reset changes
    213   } // reset
    214
    215   /** Multilevel rollback of annot caches etc. */
    216   public void rollback(int arity) {
    217     // Debug.pr(this, "CG rollback(" + arity + "), matchHistory.size() = " +
    218     //                   matchHistory.size());
    219     for(int i=0; i<arity; i++) {
    220       PatternElement[] conjunction = (PatternElement[]) matchHistory.pop();
    221       int conjLen = conjunction.length;
    222       for(int j = 0; j < conjLen; j++)
    223         conjunction[j].rollback(1);
    224     }
    225   } // rollback
    226
    227
    228   /** Does this element match the document at this position? */
    229   public boolean matches(
    230     Document doc, int position, MutableInteger newPosition
    231   ) {
    232     // if a whole conjunction matches, we set newPosition to the max of
    233     // rightmost advance of all the composite elements that matched, and
    234     // position.
    235     int rightmostAdvance = position;
    236
    237     // when we fail the whole disjunction, we set newPosition to the max of
    238     // leftmost failure point, and position
    239     int leftmostFailurePoint = Integer.MAX_VALUE;
    240
    241     // outerLoop:
    242     // for each conjunction
    243     //   for each element in the conjunction
    244     //     if it fails continue outerLoop;
    245     //   return true;
    246     // return false;
    247
    248     // for each member of the disjunctions array
    249     int savedPosition = position;
    250     int pEDLen = patternElementDisjunction2.length;
    251     outerLoop:
    252     for(int i = 0; i < pEDLen; i++) {
    253       int conjLen = patternElementDisjunction2[i].length;
    254       position = savedPosition;
    255       rightmostAdvance = position;
    256
    257       // for each pattern element making up this conjunction
    258       for(int j = 0; j < conjLen; j++) {
    259         PatternElement pat = patternElementDisjunction2[i][j];
    260
    261         if(! pat.matches(doc, position, newPosition)) {
    262           // reset the last failure point to the furthest we got so far
    263           leftmostFailurePoint =
    264             Math.min(leftmostFailurePoint, newPosition.value);
    265
    266           // rollback matches done in the previous elements of this conjunction
    267           for(int k = j - 1; k >= 0; k--)
    268             patternElementDisjunction2[i][k].rollback(1);
    269
    270           // try the next conjunction
    271           continue outerLoop;
    272         }
    273
    274         // reset our advance point to the furthest so far
    275         position = rightmostAdvance =
    276           Math.max(rightmostAdvance, newPosition.value);
    277
    278       } // for each element of the conjunction
    279
    280       // a whole conjunction matched: record advance and which conj succeeded
    281       newPosition.value = rightmostAdvance;
    282       matchHistory.push(patternElementDisjunction2[i]);
    283       //Debug.pr(this, "CG matches: pushing");
    284       return true;
    285
    286     } // for each conjunction (element of the disjunction)
    287
    288     // we reached the end of the disjunction without matching a
    289     // whole conjunction
    290     if(leftmostFailurePoint == Integer.MAX_VALUE)
    291       leftmostFailurePoint = position + 1;
    292     newPosition.value = Math.max(position + 1, leftmostFailurePoint);
    293     return false; // annot caches have been rolled back already in inner loop
    294   } // matches
    295
    296
    297   /** Create a string representation of the object. */
    298   public String toString() { return toString(""); }
    299
    300   /** Create a string representation of the object. */
    301   public String toString(String pad) {
    302     String newline = Strings.getNl();
    303
    304     StringBuffer buf =
    305       new StringBuffer(pad + "CG: disjunction(" + newline);
    306     String newPad = Strings.addPadding(pad, INDENT_PADDING);
    307
    308     boolean firstTime = true;
    309
    310     if(patternElementDisjunction1 != null) { // before finish()
    311       // for each (conjunction) member of the pattern element discjunction
    312       for(
    313         Iterator disjunction = patternElementDisjunction1.iterator();
    314         disjunction.hasNext();
    315       ) {
    316         if(firstTime) firstTime = false;
    317         else buf.append(newline + pad + "|" + newline);
    318
    319         // for each pattern element making up this conjunction
    320         for(
    321           Iterator conjunction = ((ArrayList) disjunction.next()).iterator();
    322           conjunction.hasNext();
    323         ) {
    324           buf.append(
    325             ((PatternElement) conjunction.next()).toString(newPad) + newline
    326           );
    327         } // for each element of the conjunction
    328       } // for each conjunction (element of the disjunction)
    329
    330     } else { // after finish
    331       int pEDLen = patternElementDisjunction2.length;
    332       if(firstTime) firstTime = false;
    333       else buf.append(newline + pad + "|" + newline);
    334
    335       for(int i = 0; i < pEDLen; i++) {
    336         int conjLen = patternElementDisjunction2[i].length;
    337         // for each pattern element making up this conjunction
    338         for(int j = 0; j < conjLen; j++)
    339           buf.append(
    340             patternElementDisjunction2[i][j].toString(newPad) + newline
    341           );
    342       }
    343     }
    344
    345     buf.append(pad + ") CG." + newline);
    346
    347     return buf.toString();
    348   } // toString
    349
    350
    351   //needed by FSM
    352   public PatternElement[][] getPatternElementDisjunction(){
    353     return patternElementDisjunction2;
    354   }
    355
    356 } // class ConstraintGroup
    357
    358
    359 // $Log: ConstraintGroup.java,v $
    360 // Revision 1.8  2001/09/13 12:09:50  kalina
    361 // Removed completely the use of jgl.objectspace.Array and such.
    362 // Instead all sources now use the new Collections, typically ArrayList.
    363 // I ran the tests and I ran some documents and compared with keys.
    364 // JAPE seems to work well (that's where it all was). If there are problems
    365 // maybe look at those new structures first.
    366 //
    367 // Revision 1.7  2001/09/12 11:59:33  kalina
    368 // Changed the old JAPE stuff to use the new Collections API,
    369 // instead of com.objectspace stuff. Will eliminate that library
    370 // completely very soon! Just one class left to re-implement,
    371 //
    372 // ParseCPSL.jj changed accordingly. All tested and no smoke.
    373 //
    374 // Revision 1.6  2000/11/08 16:35:02  hamish
    375 // formatting
    376 //
    377 // Revision 1.5  2000/10/26 10:45:30  oana
    378 // Modified in the code style
    379 //
    380 // Revision 1.4  2000/10/16 16:44:33  oana
    381 // Changed the comment of DEBUG variable
    382 //
    383 // Revision 1.3  2000/10/10 15:36:35  oana
    384 // Changed System.out in Out and System.err in Err;
    385 // Added the DEBUG variable seted on false;
    386 // Added in the header the licence;
    387 //
    388 // Revision 1.2  2000/04/14 18:02:46  valyt
    389 // Added some gate.fsm classes
    390 // added some accessor function in old jape classes
    391 //
    392 // Revision 1.1  2000/02/23 13:46:06  hamish
    393 // added
    394 //
    395 // Revision 1.1.1.1  1999/02/03 16:23:01  hamish
    396 // added gate2
    397 //
    398 // Revision 1.17  1998/11/24 16:18:29  hamish
    399 // fixed toString for calls after finish
    400 //
    401 // Revision 1.16  1998/11/01 21:21:36  hamish
    402 // use Java arrays in transduction where possible
    403 //
    404 // Revision 1.15  1998/11/01 14:55:54  hamish
    405 // fixed lFP setting in matches
    406 //
    407 // Revision 1.14  1998/10/30 14:06:45  hamish
    408 // added getTransducer
    409 //
    410 // Revision 1.13  1998/10/29 12:07:49  hamish
    411 // toString change
    412 //
    413 // Revision 1.12  1998/10/06 16:16:10  hamish
    414 // negation percolation during constrain add; position advance when none at end
    415 //
    416 // Revision 1.11  1998/10/01 16:06:30  hamish
    417 // new appelt transduction style, replacing buggy version
    418 //
    419 // Revision 1.10  1998/09/26 09:19:16  hamish
    420 // added cloning of PE macros
    421 //
    422 // Revision 1.9  1998/09/17 16:48:31  hamish
    423 // added macro defs and macro refs on LHS
    424 //
    425 // Revision 1.8  1998/08/12 19:05:43  hamish
    426 // fixed multi-part CG bug; set reset to real reset and fixed multi-doc bug
    427 //
    428 // Revision 1.7  1998/08/12 15:39:35  hamish
    429 // added padding toString methods
    430 //
    431 // Revision 1.6  1998/08/05 21:58:06  hamish
    432 // backend works on simple test
    433 //
    434 // Revision 1.5  1998/08/03 19:51:20  hamish
    435 // rollback added
    436 //
    437 // Revision 1.4  1998/07/31 13:12:16  hamish
    438 // done RHS stuff, not tested
    439 //
    440 // Revision 1.3  1998/07/30 11:05:16  hamish
    441 // more jape
    442 //
    443 // Revision 1.2  1998/07/29 11:06:56  hamish
    444 // first compiling version
    445 //
    446 // Revision 1.1.1.1  1998/07/28 16:37:46  hamish
    447 // gate2 lives
    448

| ConstraintGroup |