OpenCores
URL https://opencores.org/ocsvn/openrisc/openrisc/trunk

Subversion Repositories openrisc

[/] [openrisc/] [trunk/] [gnu-dev/] [or1k-gcc/] [libjava/] [classpath/] [gnu/] [java/] [util/] [regex/] [RETokenRepeated.java] - Blame information for rev 769

Details | Compare with Previous | View Log

Line No. Rev Author Line
1 769 jeremybenn
/* gnu/regexp/RETokenRepeated.java
2
   Copyright (C) 2006 Free Software Foundation, Inc.
3
 
4
This file is part of GNU Classpath.
5
 
6
GNU Classpath is free software; you can redistribute it and/or modify
7
it under the terms of the GNU General Public License as published by
8
the Free Software Foundation; either version 2, or (at your option)
9
any later version.
10
 
11
GNU Classpath is distributed in the hope that it will be useful, but
12
WITHOUT ANY WARRANTY; without even the implied warranty of
13
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
General Public License for more details.
15
 
16
You should have received a copy of the GNU General Public License
17
along with GNU Classpath; see the file COPYING.  If not, write to the
18
Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
19
02110-1301 USA.
20
 
21
Linking this library statically or dynamically with other modules is
22
making a combined work based on this library.  Thus, the terms and
23
conditions of the GNU General Public License cover the whole
24
combination.
25
 
26
As a special exception, the copyright holders of this library give you
27
permission to link this library with independent modules to produce an
28
executable, regardless of the license terms of these independent
29
modules, and to copy and distribute the resulting executable under
30
terms of your choice, provided that you also meet, for each linked
31
independent module, the terms and conditions of the license of that
32
module.  An independent module is a module which is not derived from
33
or based on this library.  If you modify this library, you may extend
34
this exception to your version of the library, but you are not
35
obligated to do so.  If you do not wish to do so, delete this
36
exception statement from your version. */
37
 
38
 
39
package gnu.java.util.regex;
40
 
41
import gnu.java.lang.CPStringBuilder;
42
 
43
import java.util.ArrayDeque;
44
import java.util.Deque;
45
 
46
final class RETokenRepeated extends REToken
47
{
48
  private REToken token;
49
  private int min, max;
50
  private boolean stingy;
51
  private boolean possessive;
52
  private int tokenFixedLength;
53
 
54
    RETokenRepeated (int subIndex, REToken token, int min, int max)
55
  {
56
    super (subIndex);
57
    this.token = token;
58
    this.min = min;
59
    this.max = max;
60
    if (token.returnsFixedLengthMatches ())
61
      {
62
        tokenFixedLength = token.getMaximumLength ();
63
      }
64
    else
65
      {
66
        tokenFixedLength = -1;
67
      }
68
  }
69
 
70
    /** Sets the minimal matching mode to true. */
71
  void makeStingy ()
72
  {
73
    stingy = true;
74
  }
75
 
76
    /** Queries if this token has minimal matching enabled. */
77
  boolean isStingy ()
78
  {
79
    return stingy;
80
  }
81
 
82
    /** Sets possessive matching mode to true. */
83
  void makePossessive ()
84
  {
85
    possessive = true;
86
  }
87
 
88
    /** Queries if this token has possessive matching enabled. */
89
  boolean isPossessive ()
90
  {
91
    return possessive;
92
  }
93
 
94
    /**
95
     * The minimum length of a repeated token is the minimum length
96
     * of the token multiplied by the minimum number of times it must
97
     * match.
98
     */
99
  int getMinimumLength ()
100
  {
101
    return (min * token.getMinimumLength ());
102
  }
103
 
104
  int getMaximumLength ()
105
  {
106
    if (max == Integer.MAX_VALUE)
107
      return Integer.MAX_VALUE;
108
    int tmax = token.getMaximumLength ();
109
    if (tmax == Integer.MAX_VALUE)
110
      return tmax;
111
    return (max * tmax);
112
  }
113
 
114
  // The comment "MUST make a clone" below means that some tests
115
  // failed without doing clone(),
116
 
117
  private static class DoablesFinder
118
  {
119
    private REToken tk;
120
    private CharIndexed input;
121
    private REMatch rematch;
122
    private boolean findFirst;
123
 
124
    private DoablesFinder (REToken tk, CharIndexed input, REMatch mymatch)
125
    {
126
      this.tk = tk;
127
      this.input = input;
128
      this.rematch = (REMatch) mymatch.clone ();        // MUST make a clone
129
      this.rematch.backtrackStack = new BacktrackStack ();
130
      findFirst = true;
131
    }
132
 
133
    private REMatch find ()
134
    {
135
      int origin = rematch.index;
136
      REMatch rem;
137
      if (findFirst)
138
        {
139
          rem = tk.findMatch (input, rematch);
140
          findFirst = false;
141
        }
142
      else
143
        {
144
          while (true)
145
            {
146
              if (rematch.backtrackStack.empty ())
147
                {
148
                  rem = null;
149
                  break;
150
                }
151
              BacktrackStack.Backtrack bt = rematch.backtrackStack.pop ();
152
              rem = bt.token.backtrack (bt.input, bt.match, bt.param);
153
              if (rem != null)
154
                break;
155
            }
156
        }
157
      if (rem == null)
158
        return null;
159
      if (rem.index == origin)
160
        rem.empty = true;
161
      rematch = rem;
162
      return (REMatch) rem.clone ();    // MUST make a clone.
163
    }
164
 
165
    boolean noMore ()
166
    {
167
      return rematch.backtrackStack.empty ();
168
    }
169
  }
170
 
171
  REMatch findMatch (CharIndexed input, REMatch mymatch)
172
  {
173
    if (tokenFixedLength >= 0)
174
      return findMatchFixedLength (input, mymatch);
175
    BacktrackStack stack = new BacktrackStack ();
176
    stack.push (new StackedInfo (input, 0, mymatch, null, null));
177
    return findMatch (stack);
178
  }
179
 
180
  REMatch backtrack (CharIndexed input, REMatch mymatch, Object param)
181
  {
182
    if (tokenFixedLength >= 0)
183
      return backtrackFixedLength (input, mymatch, param);
184
    return findMatch ((BacktrackStack) param);
185
  }
186
 
187
  private static class StackedInfo extends BacktrackStack.Backtrack
188
  {
189
    int numRepeats;
190
    int[] visited;
191
    DoablesFinder finder;
192
      StackedInfo (CharIndexed input, int numRepeats, REMatch match,
193
                   int[]visited, DoablesFinder finder)
194
    {
195
      super (null, input, match, null);
196
      this.numRepeats = numRepeats;
197
      this.visited = visited;
198
      this.finder = finder;
199
    }
200
  }
201
 
202
  private static class FindMatchControl
203
  {
204
    DoablesFinder finder;
205
      FindMatchControl (DoablesFinder finder)
206
    {
207
      this.finder = finder;
208
    }
209
  }
210
 
211
  private REMatch findMatch (BacktrackStack stack)
212
  {
213
    return findMatch (stack, new ArrayDeque < FindMatchControl > ());
214
  }
215
 
216
  private REMatch findMatch (BacktrackStack stack,
217
                             Deque < FindMatchControl > controlStack)
218
  {
219
    REMatch result = null;
220
    StackedInfo si = null;
221
    CharIndexed input = null;
222
    int numRepeats = 0;
223
    REMatch mymatch = null;
224
    int[] visited = null;
225
    DoablesFinder finder = null;
226
 
227
    // Avoid using recursive calls because a match can be very long.
228
 
229
    // This is the first entry point of this method.
230
    // If you want to call this method recursively and you need the
231
    // result returned, save necessary information in a FindMatchControl
232
    // object and push it to controlStack, then continue from this point.
233
    // You can check the result after exiting MAIN_LOOP.
234
  MAIN_LOOP0:
235
    while (true)
236
      {
237
 
238
        // This is the second entry point of this method.
239
        // If you want to call this method recursively but you do not need the
240
        // result returned, just continue from this point.
241
      MAIN_LOOP:
242
        while (true)
243
          {
244
 
245
            if (stack.empty ())
246
              break MAIN_LOOP;
247
            si = (StackedInfo) (stack.peek ());
248
            input = si.input;
249
            numRepeats = si.numRepeats;
250
            mymatch = si.match;
251
            visited = si.visited;
252
            finder = si.finder;
253
 
254
            if (mymatch.backtrackStack == null)
255
              mymatch.backtrackStack = new BacktrackStack ();
256
 
257
            if (numRepeats >= max)
258
              {
259
                stack.pop ();
260
                REMatch m1 = matchRest (input, mymatch);
261
                if (m1 != null)
262
                  {
263
                    if (!stack.empty ())
264
                      {
265
                        m1.backtrackStack.push (new BacktrackStack.
266
                                                Backtrack (this, input,
267
                                                           mymatch, stack));
268
                      }
269
                    result = m1;
270
                    break MAIN_LOOP;
271
                  }
272
                if (stingy)
273
                  {
274
                    continue MAIN_LOOP;
275
                  }
276
                break MAIN_LOOP;
277
              }
278
 
279
            if (finder == null)
280
              {
281
                finder = new DoablesFinder (token, input, mymatch);
282
                si.finder = finder;
283
              }
284
 
285
            if (numRepeats < min)
286
              {
287
                while (true)
288
                  {
289
                    REMatch doable = finder.find ();
290
                    if (doable == null)
291
                      {
292
                        if (stack.empty ())
293
                          return null;
294
                        stack.pop ();
295
                        continue MAIN_LOOP;
296
                      }
297
                    if (finder.noMore ())
298
                      stack.pop ();
299
                    int newNumRepeats = (doable.empty ? min : numRepeats + 1);
300
                    stack.
301
                      push (new
302
                            StackedInfo (input, newNumRepeats, doable,
303
                                         visited, null));
304
                    continue MAIN_LOOP;
305
                  }
306
              }
307
 
308
            if (visited == null)
309
              visited = initVisited ();
310
 
311
            if (stingy)
312
              {
313
                REMatch nextMatch = finder.find ();
314
                if (nextMatch != null && !nextMatch.empty)
315
                  {
316
                    stack.
317
                      push (new
318
                            StackedInfo (input, numRepeats + 1, nextMatch,
319
                                         visited, null));
320
                  }
321
                else
322
                  {
323
                    stack.pop ();
324
                  }
325
                REMatch m1 = matchRest (input, mymatch);
326
                if (m1 != null)
327
                  {
328
                    if (!stack.empty ())
329
                      {
330
                        m1.backtrackStack.push (new BacktrackStack.
331
                                                Backtrack (this, input,
332
                                                           mymatch, stack));
333
                      }
334
                    result = m1;
335
                    break MAIN_LOOP;
336
                  }
337
                else
338
                  {
339
                    continue MAIN_LOOP;
340
                  }
341
              }
342
 
343
            visited = addVisited (mymatch.index, visited);
344
 
345
            TryAnotherResult taresult =
346
              tryAnother (stack, input, mymatch, numRepeats, finder, visited);
347
            visited = taresult.visited;
348
            switch (taresult.status)
349
              {
350
              case TryAnotherResult.TRY_FURTHER:
351
                controlStack.push (new FindMatchControl (finder));
352
                continue MAIN_LOOP0;
353
              case TryAnotherResult.RESULT_FOUND:
354
                result = taresult.result;
355
                break MAIN_LOOP;
356
              }
357
 
358
            if (!stack.empty ())
359
              {
360
                stack.pop ();
361
              }
362
            if (possessive)
363
              {
364
                stack.clear ();
365
              }
366
            REMatch m1 = matchRest (input, mymatch);
367
            if (m1 != null)
368
              {
369
                if (!stack.empty ())
370
                  {
371
                    m1.backtrackStack.push (new BacktrackStack.
372
                                            Backtrack (this, input, mymatch,
373
                                                       stack));
374
                  }
375
                result = m1;
376
                break MAIN_LOOP;
377
              }
378
 
379
          }                     // MAIN_LOOP
380
 
381
        if (controlStack.isEmpty ())
382
          return result;
383
        FindMatchControl control = controlStack.pop ();
384
        if (possessive)
385
          {
386
            return result;
387
          }
388
        if (result != null)
389
          {
390
            result.backtrackStack.push (new BacktrackStack.
391
                                        Backtrack (this, input, mymatch,
392
                                                   stack));
393
            return result;
394
          }
395
 
396
        finder = control.finder;
397
 
398
        TryAnotherResult taresult =
399
          tryAnother (stack, input, mymatch, numRepeats, finder, visited);
400
        visited = taresult.visited;
401
        switch (taresult.status)
402
          {
403
          case TryAnotherResult.TRY_FURTHER:
404
            controlStack.push (new FindMatchControl (finder));
405
            continue MAIN_LOOP0;
406
          case TryAnotherResult.RESULT_FOUND:
407
            return taresult.result;
408
          }
409
        continue MAIN_LOOP0;
410
 
411
      }                         // MAIN_LOOP0
412
  }
413
 
414
  private static class TryAnotherResult
415
  {
416
    REMatch result;
417
    int status;
418
    static final int RESULT_FOUND = 1;
419
    static final int TRY_FURTHER = 2;
420
    static final int NOTHING_FOUND = 3;
421
    int[] visited;
422
  }
423
 
424
  private TryAnotherResult tryAnother (BacktrackStack stack,
425
                                       CharIndexed input, REMatch mymatch,
426
                                       int numRepeats, DoablesFinder finder,
427
                                       int[]visited)
428
  {
429
 
430
    TryAnotherResult taresult = new TryAnotherResult ();
431
    taresult.visited = visited;
432
 
433
  DO_THIS:
434
    {
435
 
436
      boolean emptyMatchFound = false;
437
 
438
    DO_ONE_DOABLE:
439
      while (true)
440
        {
441
 
442
          REMatch doable = finder.find ();
443
          if (doable == null)
444
            {
445
              break DO_THIS;
446
            }
447
          if (doable.empty)
448
            emptyMatchFound = true;
449
 
450
          if (!emptyMatchFound)
451
            {
452
              int n = doable.index;
453
              if (visitedContains (n, visited))
454
                {
455
                  continue DO_ONE_DOABLE;
456
                }
457
              visited = addVisited (n, visited);
458
              stack.
459
                push (new
460
                      StackedInfo (input, numRepeats + 1, doable, visited,
461
                                   null));
462
              taresult.visited = visited;
463
              taresult.status = TryAnotherResult.TRY_FURTHER;
464
              return taresult;
465
            }
466
          else
467
            {
468
              REMatch m1 = matchRest (input, doable);
469
              if (possessive)
470
                {
471
                  taresult.result = m1;
472
                  taresult.status = TryAnotherResult.RESULT_FOUND;
473
                  return taresult;
474
                }
475
              if (m1 != null)
476
                {
477
                  if (!stack.empty ())
478
                    {
479
                      m1.backtrackStack.push (new BacktrackStack.
480
                                              Backtrack (this, input, mymatch,
481
                                                         stack));
482
                    }
483
                  taresult.result = m1;
484
                  taresult.status = TryAnotherResult.RESULT_FOUND;
485
                  return taresult;
486
                }
487
            }
488
 
489
        }                       // DO_ONE_DOABLE
490
 
491
    }                           // DO_THIS
492
 
493
    taresult.status = TryAnotherResult.NOTHING_FOUND;
494
    return taresult;
495
 
496
  }
497
 
498
  boolean match (CharIndexed input, REMatch mymatch)
499
  {
500
    setHitEnd (input, mymatch);
501
    REMatch m1 = findMatch (input, mymatch);
502
    if (m1 != null)
503
      {
504
        mymatch.assignFrom (m1);
505
        return true;
506
      }
507
    return false;
508
  }
509
 
510
  // Array visited is an array of character positions we have already
511
  // visited. visited[0] is used to store the effective length of the
512
  // array.
513
  private static int[] initVisited ()
514
  {
515
    int[] visited = new int[32];
516
    visited[0] = 0;
517
    return visited;
518
  }
519
 
520
  private static boolean visitedContains (int n, int[]visited)
521
  {
522
    // Experience tells that for a small array like this,
523
    // simple linear search is faster than binary search.
524
    for (int i = 1; i < visited[0]; i++)
525
      {
526
        if (n == visited[i])
527
          return true;
528
      }
529
    return false;
530
  }
531
 
532
  private static int[] addVisited (int n, int[]visited)
533
  {
534
    if (visitedContains (n, visited))
535
      return visited;
536
    if (visited[0] >= visited.length - 1)
537
      {
538
        int[] newvisited = new int[visited.length + 32];
539
        System.arraycopy (visited, 0, newvisited, 0, visited.length);
540
        visited = newvisited;
541
      }
542
    visited[0]++;
543
    visited[visited[0]] = n;
544
    return visited;
545
  }
546
 
547
  private REMatch matchRest (CharIndexed input, final REMatch newMatch)
548
  {
549
    if (next (input, newMatch))
550
      {
551
        return newMatch;
552
      }
553
    return null;
554
  }
555
 
556
  private REMatch findMatchFixedLength (CharIndexed input, REMatch mymatch)
557
  {
558
    if (mymatch.backtrackStack == null)
559
      mymatch.backtrackStack = new BacktrackStack ();
560
    int numRepeats =
561
      token.findFixedLengthMatches (input, (REMatch) mymatch.clone (), max);
562
    if (numRepeats == Integer.MAX_VALUE)
563
      numRepeats = min;
564
    int count = numRepeats - min + 1;
565
    if (count <= 0)
566
      return null;
567
    int index = 0;
568
    if (!stingy)
569
      index = mymatch.index + (tokenFixedLength * numRepeats);
570
    else
571
      index = mymatch.index + (tokenFixedLength * min);
572
    return findMatchFixedLength (input, mymatch, index, count);
573
  }
574
 
575
  private REMatch backtrackFixedLength (CharIndexed input, REMatch mymatch,
576
                                        Object param)
577
  {
578
    int[] params = (int[]) param;
579
    int index = params[0];
580
    int count = params[1];
581
    return findMatchFixedLength (input, mymatch, index, count);
582
  }
583
 
584
  private REMatch findMatchFixedLength (CharIndexed input, REMatch mymatch,
585
                                        int index, int count)
586
  {
587
    REMatch tryMatch = (REMatch) mymatch.clone ();
588
    while (true)
589
      {
590
        tryMatch.index = index;
591
        REMatch m = matchRest (input, tryMatch);
592
        count--;
593
        if (stingy)
594
          index += tokenFixedLength;
595
        else
596
          index -= tokenFixedLength;
597
        if (possessive)
598
          return m;
599
        if (m != null)
600
          {
601
            if (count > 0)
602
              {
603
                m.backtrackStack.push (new BacktrackStack.
604
                                       Backtrack (this, input, mymatch,
605
                                                  new int[]
606
                                                  {
607
                                                  index, count}));
608
              }
609
            return m;
610
          }
611
        if (count <= 0)
612
          return null;
613
      }
614
  }
615
 
616
  void dump (CPStringBuilder os)
617
  {
618
    os.append ("(?:");
619
    token.dumpAll (os);
620
    os.append (')');
621
    if ((max == Integer.MAX_VALUE) && (min <= 1))
622
      os.append ((min == 0) ? '*' : '+');
623
    else if ((min == 0) && (max == 1))
624
      os.append ('?');
625
    else
626
      {
627
        os.append ('{').append (min);
628
        if (max > min)
629
          {
630
            os.append (',');
631
            if (max != Integer.MAX_VALUE)
632
              os.append (max);
633
          }
634
        os.append ('}');
635
      }
636
    if (stingy)
637
      os.append ('?');
638
  }
639
}

powered by: WebSVN 2.1.0

© copyright 1999-2024 OpenCores.org, equivalent to Oliscience, all rights reserved. OpenCores®, registered trademark.