source: CMT/v1r14p20031120/src/cmt_regexp.cxx @ 1

Last change on this file since 1 was 1, checked in by arnault, 19 years ago

Import all tags

File size: 35.8 KB
Line 
1
2#include "cmt_std.h"
3#include "cmt_regexp.h"
4#include "cmt_vector.h"
5
6//----------------------------------------------------------
7//
8//  Declarations
9//
10//----------------------------------------------------------
11
12//----------------------------------------------------------
13class cmt_regexp_node
14{
15public:
16  static cmt_regexp_node& null ();
17  static int node_count ();
18 
19  cmt_regexp_node ();
20  virtual ~cmt_regexp_node ();
21 
22  virtual const cmt_regexp::iterator match (const cmt_string& text, 
23                                            int pos) const;
24  virtual bool is_char () const;
25  virtual bool is_many_node () const;
26 
27private:
28  static int _node_count;
29};
30//----------------------------------------------------------
31
32//----------------------------------------------------------
33class cmt_char_node : public cmt_regexp_node
34{
35public:
36  cmt_char_node (char c);
37 
38  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
39 
40  bool is_char () const;
41  operator char ();
42 
43private:
44  char _c;
45};
46//----------------------------------------------------------
47
48//----------------------------------------------------------
49class cmt_string_node : public cmt_regexp_node
50{
51public:
52  cmt_string_node (const cmt_string& s);
53 
54  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
55 
56private:
57  cmt_string _s;
58};
59//----------------------------------------------------------
60
61//----------------------------------------------------------
62class cmt_char_list_node : public cmt_regexp_node
63{
64public:
65  cmt_char_list_node (cmt_string list);
66 
67  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
68 
69protected:
70  cmt_string _list;
71  cmt_string _choices;
72};
73//----------------------------------------------------------
74
75//----------------------------------------------------------
76class cmt_not_char_list_node : public cmt_char_list_node
77{
78public:
79  cmt_not_char_list_node (cmt_string list);
80 
81  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
82};
83//----------------------------------------------------------
84
85//----------------------------------------------------------
86class cmt_any_node : public cmt_regexp_node
87{
88public:
89  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
90};
91//----------------------------------------------------------
92
93//----------------------------------------------------------
94class cmt_zero_one : public cmt_regexp_node
95{
96public:
97  cmt_zero_one (cmt_regexp_node* n);
98  ~cmt_zero_one ();
99 
100  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
101 
102protected:
103  cmt_regexp_node* _node;
104};
105//----------------------------------------------------------
106
107//----------------------------------------------------------
108class cmt_begin_node : public cmt_regexp_node
109{
110public:
111  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
112};
113//----------------------------------------------------------
114
115//----------------------------------------------------------
116class cmt_end_node : public cmt_regexp_node
117{
118public:
119  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
120};
121//----------------------------------------------------------
122
123//----------------------------------------------------------
124class cmt_regexp_node_set : public cmt_regexp_node
125{
126public:
127  cmt_regexp_node_set ();
128  cmt_regexp_node_set (cmt_regexp_node_set* father);
129  ~cmt_regexp_node_set ();
130 
131  cmt_regexp_node_set* father ();
132  void clear ();
133  void push (cmt_regexp_node* n);
134  cmt_regexp_node* pop ();
135  cmt_regexp_node* top () const;
136  int nodes () const;
137  const cmt_regexp_node* nodeAt (int index) const;
138  bool parentheses () const;
139  void set_parentheses (bool value);
140  virtual void reduce ();
141 
142protected:
143  cmt_regexp_node_set* _father;
144  cmt_vector<cmt_regexp_node*> _nodes;
145  bool _parentheses;
146};
147//----------------------------------------------------------
148
149//----------------------------------------------------------
150class cmt_and_node : public cmt_regexp_node_set
151{
152public:
153  cmt_and_node ();
154  cmt_and_node (cmt_regexp_node_set* father);
155 
156  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
157  void reduce ();
158  void fill (cmt_and_node& other, int start_index);
159};
160//----------------------------------------------------------
161
162//----------------------------------------------------------
163class cmt_or_node : public cmt_regexp_node_set
164{
165public:
166  cmt_or_node (cmt_regexp_node_set* father);
167 
168  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
169};
170//----------------------------------------------------------
171
172//----------------------------------------------------------
173class cmt_many_node : public cmt_regexp_node
174{
175public:
176  bool is_many_node () const;
177  void install (cmt_and_node& other, int index);
178  void reduce ();
179 
180protected:
181  cmt_many_node (cmt_regexp_node* n);
182  virtual ~cmt_many_node ();
183  cmt_regexp_node* _node;
184  cmt_and_node _follower;
185};
186//----------------------------------------------------------
187
188//----------------------------------------------------------
189class cmt_zero_more : public cmt_many_node
190{
191public:
192  cmt_zero_more (cmt_regexp_node* n);
193 
194  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
195};
196//----------------------------------------------------------
197
198//----------------------------------------------------------
199class cmt_one_more : public cmt_many_node
200{
201public:
202  cmt_one_more (cmt_regexp_node* n);
203
204  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
205};
206//----------------------------------------------------------
207
208//----------------------------------------------------------
209cmt_regexp_node& cmt_regexp_node::null ()
210{
211  static cmt_regexp_node null_instance;
212 
213  return (null_instance);
214}
215//----------------------------------------------------------
216
217
218
219//----------------------------------------------------------
220//
221//  Implementation
222//
223//----------------------------------------------------------
224
225//----------------------------------------------------------
226cmt_regexp_node::cmt_regexp_node ()
227{
228  _node_count++;
229}
230
231cmt_regexp_node::~cmt_regexp_node ()
232{
233  _node_count--;
234}
235
236int cmt_regexp_node::node_count ()
237{
238  return (_node_count);
239}
240
241const cmt_regexp::iterator cmt_regexp_node::match (const cmt_string& /*text*/, 
242                                            int /*pos*/) const
243{
244  return (cmt_regexp::iterator::null());
245}
246
247bool cmt_regexp_node::is_char () const
248{
249  return (false);
250}
251
252bool cmt_regexp_node::is_many_node () const
253{
254  return (false);
255}
256
257int cmt_regexp_node::_node_count = 0;
258//----------------------------------------------------------
259
260//----------------------------------------------------------
261cmt_char_node::cmt_char_node (char c)
262{
263  _c = c;
264}
265
266const cmt_regexp::iterator cmt_char_node::match (const cmt_string& text, 
267                                                 int pos) const
268{
269  if ((pos < 0) || (pos > text.size ())) 
270    {
271      return (cmt_regexp::iterator::null ());
272    }
273
274  char c = text[pos];
275
276  if (c == _c)
277    {
278      return (cmt_regexp::iterator (pos, 1));
279    }
280 
281  return (cmt_regexp::iterator::null ());
282}
283
284bool cmt_char_node::is_char () const
285{
286  return (true);
287}
288
289cmt_char_node::operator char ()
290{
291  return (_c);
292}
293//----------------------------------------------------------
294
295//----------------------------------------------------------
296cmt_string_node::cmt_string_node (const cmt_string& s)
297{
298  _s = s;
299}
300
301const cmt_regexp::iterator cmt_string_node::match (const cmt_string& text, 
302                                                  int pos) const
303{
304  if ((pos < 0) || (pos > text.size ())) 
305    {
306      return (cmt_regexp::iterator::null ());
307    }
308
309  int length = _s.size ();
310 
311  cmt_string s = text.substr (pos, length);
312 
313  if ((length == 0) || (s == _s))
314    {
315      return (cmt_regexp::iterator (pos, length));
316    }
317 
318  return (cmt_regexp::iterator::null ());
319}
320//----------------------------------------------------------
321
322//----------------------------------------------------------
323cmt_char_list_node::cmt_char_list_node (cmt_string list)
324{
325  _list = list;
326 
327  _choices = "";
328 
329  char c;
330  int i;
331 
332  for (i = 0; i < list.size (); i++)
333    {
334      c = list[i];
335     
336      switch (c)
337        {
338          case '-':
339            i++;
340            {
341              char c1 = _choices[_choices.size () - 1];
342              char c2 = list[i];
343              int j;
344              int j0 = (c1 < c2) ? c1 : c2;
345              int j1 = (c1 > c2) ? c1 : c2;
346              for (j = j0; j <= j1; j++)
347                {
348                  _choices += j;
349                }
350            }
351            break;
352          case '\\':
353            i++;
354            c = list[i];
355            switch (c)
356              {
357                case '[':
358                case ']':
359                case '(':
360                case ')':
361                case '.':
362                case '*':
363                case '?':
364                case '^':
365                case '$':
366                case '\\':
367                  break;
368                case 'r':
369                  c = '\r';
370                  break;
371                case 't':
372                  c = '\t';
373                  break;
374                case 'n':
375                  c = '\n';
376                  break;
377                default:
378                  break;
379              }
380          default:
381            _choices += c;
382            break;
383        }
384    }
385}
386
387const cmt_regexp::iterator cmt_char_list_node::match (const cmt_string& text, 
388                                                     int pos) const
389{
390  if ((pos < 0) || (pos > text.size ())) 
391    {
392      return (cmt_regexp::iterator::null ());
393    }
394
395  char c = text[pos];
396
397  int i;
398 
399  for (i = 0; i < _choices.size (); i++)
400    {
401      if (c == _choices[i]) return (cmt_regexp::iterator (pos, 1));
402    }
403 
404  return (cmt_regexp::iterator::null ());
405}
406//----------------------------------------------------------
407
408//----------------------------------------------------------
409cmt_not_char_list_node::cmt_not_char_list_node (cmt_string list) : 
410        cmt_char_list_node (list)
411{
412}
413
414const cmt_regexp::iterator cmt_not_char_list_node::match (const cmt_string& text, 
415                                                      int pos) const
416{
417  if ((pos < 0) || (pos > text.size ())) 
418    {
419      return (cmt_regexp::iterator::null ());
420    }
421
422  char c = text[pos];
423
424  int i;
425
426  for (i = 0; i < _choices.size (); i++)
427    {
428      if (c == _choices[i]) return (cmt_regexp::iterator::null ());
429    }
430 
431  return (cmt_regexp::iterator (pos, 1));
432}
433//----------------------------------------------------------
434
435//----------------------------------------------------------
436const cmt_regexp::iterator cmt_any_node::match (const cmt_string& text, 
437                                            int pos) const
438{
439  if ((pos < 0) | (pos >= text.size ())) 
440    {
441      return (cmt_regexp::iterator::null ());
442    }
443 
444  return (cmt_regexp::iterator (pos, 1));
445}
446//----------------------------------------------------------
447
448//----------------------------------------------------------
449cmt_zero_one::cmt_zero_one (cmt_regexp_node* n) : _node (n)
450{
451}
452
453cmt_zero_one::~cmt_zero_one ()
454{
455  delete _node;
456}
457
458const cmt_regexp::iterator cmt_zero_one::match (const cmt_string& text, 
459                                               int pos) const
460{
461  if ((pos < 0) || (pos > text.size ())) 
462    {
463      return (cmt_regexp::iterator::null ());
464    }
465
466  int total = 0;
467
468  if (pos < text.size ())
469    {
470      const cmt_regexp::iterator it = _node->match (text, pos);
471      if (it != cmt_regexp::iterator::null ())
472        {
473          total += it._length;
474          pos += it._length;
475        }
476    }
477 
478  return (cmt_regexp::iterator (pos, total));
479}
480//----------------------------------------------------------
481
482//----------------------------------------------------------
483cmt_many_node::cmt_many_node (cmt_regexp_node* n) : _node (n)
484{
485}
486
487bool cmt_many_node::is_many_node () const
488{
489  return (true);
490}
491
492cmt_many_node::~cmt_many_node ()
493{
494  delete _node;
495}
496
497void cmt_many_node::install (cmt_and_node& other, int start_index)
498{
499  _follower.fill (other, start_index);
500}
501
502void cmt_many_node::reduce ()
503{
504  _follower.reduce ();
505}
506//----------------------------------------------------------
507
508
509
510//----------------------------------------------------------
511cmt_zero_more::cmt_zero_more (cmt_regexp_node* n) : cmt_many_node (n)
512{
513}
514
515const cmt_regexp::iterator cmt_zero_more::match (const cmt_string& text, 
516                                             int pos) const
517{
518  if ((pos < 0) || (pos > text.size ())) 
519    {
520      return (cmt_regexp::iterator::null ());
521    }
522
523  int total = 0;
524
525  //
526  // we are at : x*y
527  //
528
529  int saved_pos = -1;
530  int saved_total = -1;
531
532  do
533    {
534      const cmt_regexp::iterator itx = _node->match (text, pos);
535      const cmt_regexp::iterator ity = _follower.match (text, pos);
536
537      if ((itx == cmt_regexp::iterator::null ()) &&
538          (ity == cmt_regexp::iterator::null ())) 
539        {
540          //
541          // There is neither x nor y. We move back to the last
542          // succesful match for y.
543          //
544          if (saved_pos >= 0)
545            {
546              //
547              // We had once a y.
548              //
549              pos = saved_pos;
550              total = saved_total;
551            }
552          else
553            {
554              //
555              // We never had any y !
556              //
557              return (cmt_regexp::iterator::null ());
558            }
559
560          break;
561        }
562
563      if (itx == cmt_regexp::iterator::null ())
564        {
565          //
566          // There is a y but no x anymore, fine, we can quit.
567          //
568          total += ity._length;
569          pos += ity._length;
570          break;
571        }
572
573      if (ity != cmt_regexp::iterator::null ())
574        {
575          //
576          //  We have both x and y. We save the current pos and total,
577          // and then skip this x.
578          //
579          saved_total = total + ity._length;
580          saved_pos = pos + ity._length;
581        }
582      total += itx._length;
583      pos += itx._length;
584    } while (true);
585 
586  return (cmt_regexp::iterator (pos, total));
587}
588//----------------------------------------------------------
589
590//----------------------------------------------------------
591cmt_one_more::cmt_one_more (cmt_regexp_node* n) : cmt_many_node (n)
592{
593}
594
595const cmt_regexp::iterator cmt_one_more::match (const cmt_string& text, 
596                                            int pos) const
597{
598  if ((pos < 0) || (pos > text.size ())) 
599    {
600      return (cmt_regexp::iterator::null ());
601    }
602
603  int total = 0;
604
605  //
606  // we are at : x+y
607  //
608
609  int saved_pos = -1;
610  int saved_total = -1;
611  bool at_least_one = false;
612
613  do
614    {
615      const cmt_regexp::iterator itx = _node->match (text, pos);
616      const cmt_regexp::iterator ity = _follower.match (text, pos);
617
618      if ((itx == cmt_regexp::iterator::null ()) &&
619          (ity == cmt_regexp::iterator::null ())) 
620        {
621          //
622          // There is neither x nor y. We move back to the last
623          // succesful match for y.
624          //
625          if (saved_pos >= 0)
626            {
627              //
628              // We had once a y.
629              //
630              pos = saved_pos;
631              total = saved_total;
632            }
633          else
634            {
635              //
636              // We never had any y !
637              //
638              return (cmt_regexp::iterator::null ());
639            }
640
641          break;
642        }
643
644      if (itx == cmt_regexp::iterator::null ())
645        {
646          //
647          // There is a y but no x anymore, fine, we can quit.
648          //
649          total += ity._length;
650          pos += ity._length;
651          break;
652        }
653
654      if (ity != cmt_regexp::iterator::null ())
655        {
656          //
657          //  We have both x and y. We save the current pos and total,
658          // and then skip this x.
659          //
660          saved_total = total + ity._length;
661          saved_pos = pos + ity._length;
662        }
663
664      total += itx._length;
665      pos += itx._length;
666
667      at_least_one = true;
668    } while (true);
669 
670  if (!at_least_one) return (cmt_regexp::iterator::null ());
671 
672  return (cmt_regexp::iterator (pos, total));
673}
674//----------------------------------------------------------
675
676
677
678//----------------------------------------------------------
679const cmt_regexp::iterator cmt_begin_node::match (const cmt_string& /*text*/, 
680                                                 int pos) const
681{
682  if (pos == 0) return (cmt_regexp::iterator (pos, 0));
683  return (cmt_regexp::iterator::null ());
684}
685//----------------------------------------------------------
686
687//----------------------------------------------------------
688const cmt_regexp::iterator cmt_end_node::match (const cmt_string& text,
689                                                int pos) const
690{
691  if (pos == text.size ()) return (cmt_regexp::iterator (pos, 0));
692  return (cmt_regexp::iterator::null ());
693}
694//----------------------------------------------------------
695
696//----------------------------------------------------------
697cmt_regexp_node_set::cmt_regexp_node_set () : _father (0)
698{
699  _parentheses = false;
700}
701
702cmt_regexp_node_set::cmt_regexp_node_set (cmt_regexp_node_set* father) : _father (father)
703{
704  if (father != 0) father->push (this);
705  _parentheses = false;
706}
707
708cmt_regexp_node_set::~cmt_regexp_node_set ()
709{
710  clear ();
711}
712
713cmt_regexp_node_set* cmt_regexp_node_set::father ()
714{
715  return (_father);
716}
717
718void cmt_regexp_node_set::clear ()
719{
720  int i;
721 
722  for (i = 0; i < _nodes.size (); i++)
723    {
724      cmt_regexp_node* n = _nodes[i];
725      delete n;
726    }
727  _nodes.clear ();
728}
729
730void cmt_regexp_node_set::push (cmt_regexp_node* n)
731{
732  _nodes.push_back (n);
733}
734
735cmt_regexp_node* cmt_regexp_node_set::pop ()
736{
737  if (_nodes.size () == 0) return (&cmt_regexp_node::null ());
738 
739  int index = _nodes.size () - 1;
740 
741  cmt_regexp_node* n = _nodes[index];
742  _nodes.erase (index);
743 
744  return (n);
745}
746
747cmt_regexp_node* cmt_regexp_node_set::top () const
748{
749  if (_nodes.size () == 0) return (&cmt_regexp_node::null ());
750 
751  int index = _nodes.size () - 1;
752 
753  cmt_regexp_node* n = _nodes[index];
754 
755  return (n);
756}
757
758int cmt_regexp_node_set::nodes () const
759{
760  return (_nodes.size ());
761}
762
763const cmt_regexp_node* cmt_regexp_node_set::nodeAt (int index) const
764{
765  return (_nodes[index]);
766}
767
768bool cmt_regexp_node_set::parentheses () const
769{
770  return (_parentheses);
771}
772
773void cmt_regexp_node_set::set_parentheses (bool value)
774{
775  _parentheses = value;
776}
777
778void cmt_regexp_node_set::reduce ()
779{
780}
781//----------------------------------------------------------
782
783//----------------------------------------------------------
784cmt_and_node::cmt_and_node () : cmt_regexp_node_set ()
785{
786}
787
788cmt_and_node::cmt_and_node (cmt_regexp_node_set* father) : cmt_regexp_node_set (father)
789{
790}
791
792const cmt_regexp::iterator cmt_and_node::match (const cmt_string& text, 
793                                                int pos) const
794{
795  if ((pos < 0) || (pos > text.size ())) 
796    {
797      return (cmt_regexp::iterator::null ());
798    }
799
800  if (_nodes.size () == 0) return (cmt_regexp::iterator (pos, 0));
801
802  int i;
803  int total = 0;
804  int p = pos;
805 
806  for (i = 0; i < _nodes.size (); i++)
807    {
808      cmt_regexp_node* n = _nodes[i];
809     
810      const cmt_regexp::iterator it = n->match (text, p);
811     
812      if (it == cmt_regexp::iterator::null ()) return (it);
813     
814      total += it._length;
815      p += it._length;
816    }
817
818    // All nodes match
819 
820  return (cmt_regexp::iterator (pos, total));
821}
822
823void cmt_and_node::reduce ()
824{
825  if (_nodes.size () < 2) return;
826 
827  char c = ' ';
828  cmt_string s = "";
829  cmt_vector<cmt_regexp_node*> new_nodes;
830
831  //
832  // We loop once too much in order to finish the possibly accumulated
833  // string at the end.
834  //
835  for (int i = 0; i <= _nodes.size (); i++)
836    {
837      cmt_regexp_node* n = 0;
838
839      if (i < _nodes.size ()) n = _nodes[i];
840
841      if ((i >= _nodes.size ()) || (!n->is_char ()))
842        {
843          if (s.size () == 1)
844            {
845              //
846              // Too bad there was only one char node to consider
847              // let's put it back as a char node !
848              //
849              new_nodes.push_back (new cmt_char_node (c));
850              s = "";
851            }
852          else if (s.size () > 1)
853            {
854              //
855              // We have real reduction here sonce there was several
856              // consecutive char nodes.
857              //
858              new_nodes.push_back (new cmt_string_node (s));
859              s = "";
860            }
861
862          if (i >= _nodes.size ()) break;
863        }
864
865      if (n->is_char ())
866        {
867          //
868          // We are now trying to compact those char nodes.
869          //
870          cmt_char_node& cn = *((cmt_char_node*) n);
871          c = (char) cn;
872          s += c;
873          delete n;
874          _nodes[i] = 0;
875        }
876      else if (n->is_many_node ())
877        {
878          cmt_many_node& mn = *((cmt_many_node*) n);
879          mn.install (*this, i + 1);
880          mn.reduce ();
881          new_nodes.push_back (n);
882          break;
883        }
884      else
885        {
886          new_nodes.push_back (n);
887        }
888    }
889 
890  _nodes = new_nodes;
891}
892
893void cmt_and_node::fill (cmt_and_node& other, int start_index)
894{
895  if ((start_index < 0) || (start_index > other.nodes ())) return;
896
897  for (int i = start_index; i < other.nodes (); i++)
898    {
899      cmt_regexp_node* n = other._nodes[i];
900      push (n);
901    }
902}
903//----------------------------------------------------------
904
905//----------------------------------------------------------
906cmt_or_node::cmt_or_node (cmt_regexp_node_set* father) : cmt_regexp_node_set (father)
907{
908}
909
910const cmt_regexp::iterator cmt_or_node::match (const cmt_string& text, 
911                                               int pos) const
912{
913  if ((pos < 0) || (pos >= text.size ())) 
914    {
915      return (cmt_regexp::iterator::null ());
916    }
917
918  if (_nodes.size () == 0) return (cmt_regexp::iterator (pos, 0));
919 
920  int i;
921 
922  for (i = 0; i < _nodes.size (); i++)
923    {
924      const cmt_regexp_node* n = _nodes[i];
925     
926      const cmt_regexp::iterator it = n->match (text, pos);
927     
928        //        at least one or-ed expression matches
929      if (it != cmt_regexp::iterator::null ()) return (it);
930    }
931 
932  return (cmt_regexp::iterator::null ());
933}
934//----------------------------------------------------------
935
936
937
938
939
940
941
942
943
944
945
946
947
948//----------------------------------------------------------
949cmt_regexp::cmt_regexp ()
950{
951  _root = 0;
952}
953
954//----------------------------------------------------------
955cmt_regexp::cmt_regexp (const cmt_string& expression)
956{
957  _root = 0;
958  set (expression);
959}
960
961//----------------------------------------------------------
962void cmt_regexp::set (const cmt_string& expression)
963{
964  if (_root != 0)
965    {
966      delete _root;
967      _root = 0;
968    }
969
970    //
971    // The root is the cmt_or_node which will be returned. It is
972    // the top of the hierarchy.
973    //
974    //  top is the running cmt_and_node.
975    //
976  cmt_regexp_node_set* or_root = 0;
977  cmt_regexp_node_set* top_and = 0;
978 
979    // abcd
980    // ab|cd
981    // a|b|cd
982    // a|b*|cd
983    // a|b*|cd?e
984    //
985    // exp     : and
986    //         | exp '|' and
987    //
988    // and     : unary
989    //         | unary and
990    //
991    // unary   : primary '*'
992    //         | primary '?'
993    //
994    // primary : '[' opt_begin opt_chars opt_end ']'
995    //         | '^'
996    //         | '$'
997    //         | char
998    //         | '(' exp ')'
999    //
1000 
1001  {
1002      //
1003      // First we build an cmt_or_node (corresponding to the
1004      // first grammatical rule)
1005      //
1006      //  Then cmt_and_nodes are pushed into it.
1007      //  and standard nodes are pushed into the running (top_and) cmt_and_node
1008      //
1009    or_root = new cmt_or_node (0);
1010    top_and = new cmt_and_node (or_root);
1011  }
1012 
1013  int i;
1014 
1015  for (i = 0; i < expression.size (); i++)
1016    {
1017      char c = expression[i];
1018      switch (c)
1019        {
1020          case '[':
1021          {
1022              //
1023              // The case is
1024              //
1025              //  exp   : '['     char ... ']'
1026              //  exp   : '[' '^' char ... ']'
1027              //
1028
1029            if (i >= expression.size ()) 
1030              {
1031                  // syntax error : unbalanced '['
1032                delete or_root;
1033                return;
1034              }
1035            i++;
1036           
1037            int i0 = i;
1038           
1039            bool done = false;
1040            bool has_not = false;
1041           
1042            cmt_string choices = "";
1043           
1044            for (; i < expression.size (); i++)
1045              {
1046                c = expression[i];
1047                switch (c)
1048                  {
1049                    case ']':
1050                      done = true;
1051                      break;
1052                    case '^':
1053                      if (i == i0) has_not = true;
1054                      else choices += c;
1055                      break;
1056                    case '\\':
1057                      choices += c;
1058                      if (i >= expression.size ())
1059                        {
1060                            // syntax error : unbalanced '[' and unfinished
1061                            // escape sequence
1062                          delete or_root;
1063                          return;
1064                        }
1065                      i++;
1066                      c = expression[i];
1067                      choices += c;
1068                      break;
1069                    default:
1070                      choices += c;
1071                      break;
1072                  }
1073                if (done) break;
1074              }
1075           
1076            if (!done)
1077              {
1078                  // syntax error : unbalanced '['
1079                delete or_root;
1080                return;
1081              }
1082            if (has_not)
1083              top_and->push (new cmt_not_char_list_node (choices));
1084            else       
1085              top_and->push (new cmt_char_list_node (choices));
1086          }
1087          break;
1088          case '*':
1089          {
1090              //
1091              //  exp : exp '*'
1092              //
1093            if (top_and->nodes () == 0)
1094              {
1095                  // Syntax error : '*' is not preceded by an expression
1096                delete or_root;
1097                return;
1098              }
1099           
1100            cmt_regexp_node* n = top_and->pop ();
1101            top_and->push (new cmt_zero_more (n));
1102          }
1103          break;
1104          case '+':
1105          {
1106              //
1107              //  exp : exp '+'
1108              //
1109            if (top_and->nodes () == 0)
1110              {
1111                  // Syntax error : '+' is not preceded by an expression
1112                delete or_root;
1113                return;
1114              }
1115           
1116            cmt_regexp_node* n = top_and->pop ();
1117            top_and->push (new cmt_one_more (n));
1118          }
1119          break;
1120          case '?':
1121          {
1122              //
1123              //  exp : exp '?'
1124              //
1125            if (top_and->nodes () == 0)
1126              {
1127                  // Syntax error : '?' is not preceded by an expression
1128                delete or_root;
1129                return;
1130              }
1131           
1132            cmt_regexp_node* n = top_and->pop ();
1133            top_and->push (new cmt_zero_one (n));
1134          }
1135          break;
1136          case '.':
1137              //
1138              //  exp : '.'
1139              //
1140            top_and->push (new cmt_any_node ());
1141            break;
1142          case '(':
1143          {
1144              //
1145              //  exp : '(' exp ')'
1146              //
1147            if (top_and->parentheses ())
1148              {
1149                  // This should never happen.
1150                delete or_root;
1151                return;
1152              }
1153           
1154            top_and->set_parentheses (true);
1155           
1156              //
1157              // A new complete expression is started.
1158              //  -> do as for top_and parsing.
1159              //
1160           
1161            top_and = new cmt_and_node (new cmt_or_node (top_and));
1162          }
1163          break;
1164          case ')':
1165          {
1166              //
1167              //  exp : '(' exp ')'
1168              //
1169           
1170              // top_and is the cmt_and_node into which new nodes are pushed.
1171            cmt_regexp_node_set* or_node = top_and->father ();
1172            if (or_node == 0) 
1173              {
1174                  // This should never happen : top_and should always be
1175                  // at least an cmt_and_node hanging at an cmt_or_node
1176                delete or_root;
1177                return;
1178              }
1179           
1180              //
1181              // The last cmt_and_node was empty, thus we had either '()' or '(...|)'
1182              //
1183           
1184            if (top_and->nodes () == 0) 
1185              {
1186                delete (or_node->pop ());
1187              }
1188            else
1189              {
1190                top_and->reduce ();
1191              }
1192           
1193            top_and = or_node->father ();
1194           
1195            if (top_and == 0)
1196              {
1197                  // Syntax error : too many ')'
1198                delete or_root;
1199                return;
1200              }
1201           
1202              //
1203              // top_and is now the previous running cmt_and_node where the '('
1204              // was originally met its top_and node contains the parenthesized
1205              // sub expression  If this one is empty, (due to an empty '()'
1206              // expression) then it may simply be discarded.
1207              //
1208           
1209            if (!top_and->parentheses ())
1210              {
1211                  // Syntax error : too many ')'
1212                delete or_root;
1213                return;
1214              }
1215           
1216            top_and->set_parentheses (false);
1217           
1218            cmt_regexp_node* unique = 0;
1219            if (or_node->nodes () == 1)
1220              {
1221                cmt_regexp_node_set* and_node = (cmt_regexp_node_set*) or_node->top ();
1222                if (and_node->nodes () == 1)
1223                  {
1224                    unique = and_node->pop ();
1225                    delete (or_node->pop ());
1226                  }
1227                else if (and_node->nodes () == 0)
1228                  {
1229                    delete (or_node->pop ());
1230                  }
1231              }
1232           
1233            if (or_node->nodes () == 0) delete (top_and->pop ());
1234            if (unique != 0) top_and->push (unique);
1235          }
1236         
1237          break;
1238          case '|':
1239          {
1240              //
1241              //  exp : exp '|' exp
1242              //
1243
1244            cmt_regexp_node_set* or_node = top_and->father ();
1245           
1246            top_and->reduce ();
1247           
1248              //
1249              // or is the father cmt_or_node, which only contains cmt_and_nodes
1250              //
1251           
1252            const cmt_regexp_node_set* and_node = (cmt_regexp_node_set*) or_node->top ();
1253            if (and_node->nodes () == 0)
1254              {
1255                  // the previous node was empty.
1256                  // we may discard it
1257                or_node->pop ();
1258              }
1259           
1260            top_and = new cmt_and_node (or_node);
1261          }
1262          break;
1263          case '^':
1264              //
1265              //  exp : '^'
1266              //
1267            top_and->push (new cmt_begin_node ());
1268            break;
1269          case '$':
1270              //
1271              //  exp : '$'
1272              //
1273            top_and->push (new cmt_end_node ());
1274            break;
1275          case '\\':
1276            if (i >= expression.size ())
1277              {
1278                delete or_root;
1279                return;
1280              }
1281            i++;
1282            c = expression[i];
1283            switch (c)
1284              {
1285                case '[':
1286                case ']':
1287                case '(':
1288                case ')':
1289                case '.':
1290                case '*':
1291                case '?':
1292                case '^':
1293                case '$':
1294                case '\\':
1295                  break;
1296                case 'r':
1297                  c = '\r';
1298                  break;
1299                case 't':
1300                  c = '\t';
1301                  break;
1302                case 'n':
1303                  c = '\n';
1304                  break;
1305                default:
1306                  break;
1307              }
1308          default:
1309            top_and->push (new cmt_char_node (c));
1310            break;
1311        }
1312    }
1313 
1314  if (or_root != 0)
1315    {
1316      cmt_regexp_node_set* and_node = (cmt_regexp_node_set*) or_root->top ();
1317     
1318      if (or_root->nodes () == 1)
1319        {
1320            //
1321            // Check whether there is at least one non-empty
1322            // cmt_and_node
1323            //
1324          if (and_node->nodes () == 0)
1325            {
1326              delete or_root;
1327              return;
1328            }
1329        }
1330     
1331      if (and_node != 0)
1332        {
1333          and_node->reduce ();
1334         
1335          if (and_node->parentheses ())
1336            {
1337              delete or_root;
1338              return;
1339            }
1340        }
1341    }
1342 
1343  _root = or_root;
1344}
1345
1346cmt_regexp::~cmt_regexp ()
1347{
1348  if (_root != 0)
1349    {
1350      delete _root;
1351    }
1352}
1353
1354bool cmt_regexp::is_valid () const
1355{
1356  if (_root != 0) return (true);
1357  else return (false);
1358}
1359
1360cmt_regexp::iterator cmt_regexp::begin (const cmt_string& text, int pos)
1361{
1362  if (_root != 0)
1363    {
1364      int i;
1365     
1366      for (i = pos; i < text.size (); i++)
1367        {
1368          cmt_regexp::iterator it = _root->match (text, i);
1369          if (it != end ()) return (it);
1370        }
1371    }
1372 
1373  return (end ());
1374}
1375
1376cmt_regexp::iterator cmt_regexp::end ()
1377{
1378  return (cmt_regexp::iterator::null ());
1379}
1380
1381cmt_regexp::iterator cmt_regexp::begin (const cmt_string& text, int pos) const
1382{
1383  if (_root != 0)
1384    {
1385      int i;
1386     
1387      for (i = pos; i < text.size (); i++)
1388        {
1389          cmt_regexp::iterator it = _root->match (text, i);
1390          if (it != end ()) return (it);
1391        }
1392    }
1393 
1394  return (end ());
1395}
1396
1397cmt_regexp::iterator cmt_regexp::end () const
1398{
1399  return (cmt_regexp::iterator::null ());
1400}
1401
1402bool cmt_regexp::match (const cmt_string& text) const
1403{
1404  iterator it = begin (text);
1405  if (it == end ()) return (false);
1406  else return (true);
1407}
1408//----------------------------------------------------------
1409
1410//----------------------------------------------------------
1411const cmt_regexp::iterator cmt_regexp::iterator::null ()
1412{
1413  static const iterator null_instance (-1, -1);
1414 
1415  return (null_instance);
1416}
1417
1418cmt_regexp::iterator::iterator ()
1419{
1420  _pos = 0;
1421  _length = 0;
1422}
1423
1424cmt_regexp::iterator::iterator (int pos, int length)
1425{
1426  _pos = pos;
1427  _length = length;
1428}
1429
1430cmt_regexp::iterator::iterator (const iterator& other)
1431{
1432  _pos = other._pos;
1433  _length = other._length;
1434}
1435
1436int cmt_regexp::iterator::operator != (const iterator& other) const
1437{
1438  return ((this->_pos != other._pos) ||
1439          (this->_length != other._length));
1440}
1441
1442int cmt_regexp::iterator::operator == (const iterator& other) const
1443{
1444  return ((this->_pos == other._pos) &&
1445          (this->_length == other._length));
1446}
1447//----------------------------------------------------------
1448
Note: See TracBrowser for help on using the repository browser.