source: CMT/v1r12p20020606/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: 34.7 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_node
14{
15public:
16  static cmt_node& null ();
17  static int node_count ();
18 
19  cmt_node ();
20  virtual ~cmt_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_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_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_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_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_node
95{
96public:
97  cmt_zero_one (cmt_node* n);
98  ~cmt_zero_one ();
99 
100  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
101 
102protected:
103  cmt_node* _node;
104};
105//----------------------------------------------------------
106
107//----------------------------------------------------------
108class cmt_begin_node : public cmt_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_node
117{
118public:
119  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
120};
121//----------------------------------------------------------
122
123//----------------------------------------------------------
124class cmt_node_set : public cmt_node
125{
126public:
127  cmt_node_set ();
128  cmt_node_set (cmt_node_set* father);
129  ~cmt_node_set ();
130 
131  cmt_node_set* father ();
132  void clear ();
133  void push (cmt_node* n);
134  cmt_node* pop ();
135  cmt_node* top () const;
136  int nodes () const;
137  const cmt_node* nodeAt (int index) const;
138  bool parentheses () const;
139  void set_parentheses (bool value);
140  virtual void reduce ();
141 
142protected:
143  cmt_node_set* _father;
144  cmt_vector<cmt_node*> _nodes;
145  bool _parentheses;
146};
147//----------------------------------------------------------
148
149//----------------------------------------------------------
150class cmt_and_node : public cmt_node_set
151{
152public:
153  cmt_and_node ();
154  cmt_and_node (cmt_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_node_set
164{
165public:
166  cmt_or_node (cmt_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_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_node* n);
182  virtual ~cmt_many_node ();
183  cmt_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_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_node* n);
203
204  const cmt_regexp::iterator match (const cmt_string& text, int pos) const;
205};
206//----------------------------------------------------------
207
208//----------------------------------------------------------
209cmt_node& cmt_node::null ()
210{
211  static cmt_node null_instance;
212 
213  return (null_instance);
214}
215//----------------------------------------------------------
216
217
218
219//----------------------------------------------------------
220//
221//  Implementation
222//
223//----------------------------------------------------------
224
225//----------------------------------------------------------
226cmt_node::cmt_node ()
227{
228  _node_count++;
229}
230
231cmt_node::~cmt_node ()
232{
233  _node_count--;
234}
235
236int cmt_node::node_count ()
237{
238  return (_node_count);
239}
240
241const cmt_regexp::iterator cmt_node::match (const cmt_string& /*text*/, 
242                                            int /*pos*/) const
243{
244  return (cmt_regexp::iterator::null());
245}
246
247bool cmt_node::is_char () const
248{
249  return (false);
250}
251
252bool cmt_node::is_many_node () const
253{
254  return (false);
255}
256
257int cmt_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_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_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_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_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_node_set::cmt_node_set () : _father (0)
698{
699  _parentheses = false;
700}
701
702cmt_node_set::cmt_node_set (cmt_node_set* father) : _father (father)
703{
704  if (father != 0) father->push (this);
705  _parentheses = false;
706}
707
708cmt_node_set::~cmt_node_set ()
709{
710  clear ();
711}
712
713cmt_node_set* cmt_node_set::father ()
714{
715  return (_father);
716}
717
718void cmt_node_set::clear ()
719{
720  int i;
721 
722  for (i = 0; i < _nodes.size (); i++)
723    {
724      cmt_node* n = _nodes[i];
725      delete n;
726    }
727  _nodes.clear ();
728}
729
730void cmt_node_set::push (cmt_node* n)
731{
732  _nodes.push_back (n);
733}
734
735cmt_node* cmt_node_set::pop ()
736{
737  if (_nodes.size () == 0) return (&cmt_node::null ());
738 
739  int index = _nodes.size () - 1;
740 
741  cmt_node* n = _nodes[index];
742  _nodes.erase (index);
743 
744  return (n);
745}
746
747cmt_node* cmt_node_set::top () const
748{
749  if (_nodes.size () == 0) return (&cmt_node::null ());
750 
751  int index = _nodes.size () - 1;
752 
753  cmt_node* n = _nodes[index];
754 
755  return (n);
756}
757
758int cmt_node_set::nodes () const
759{
760  return (_nodes.size ());
761}
762
763const cmt_node* cmt_node_set::nodeAt (int index) const
764{
765  return (_nodes[index]);
766}
767
768bool cmt_node_set::parentheses () const
769{
770  return (_parentheses);
771}
772
773void cmt_node_set::set_parentheses (bool value)
774{
775  _parentheses = value;
776}
777
778void cmt_node_set::reduce ()
779{
780}
781//----------------------------------------------------------
782
783//----------------------------------------------------------
784cmt_and_node::cmt_and_node () : cmt_node_set ()
785{
786}
787
788cmt_and_node::cmt_and_node (cmt_node_set* father) : cmt_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_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_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_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_node* n = other._nodes[i];
900      push (n);
901    }
902}
903//----------------------------------------------------------
904
905//----------------------------------------------------------
906cmt_or_node::cmt_or_node (cmt_node_set* father) : cmt_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_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 (const cmt_string& expression)
950{
951  _root = 0;
952
953    //
954    // The root is the cmt_or_node which will be returned. It is
955    // the top of the hierarchy.
956    //
957    //  top is the running cmt_and_node.
958    //
959  cmt_node_set* or_root = 0;
960  cmt_node_set* top_and = 0;
961 
962    // abcd
963    // ab|cd
964    // a|b|cd
965    // a|b*|cd
966    // a|b*|cd?e
967    //
968    // exp     : and
969    //         | exp '|' and
970    //
971    // and     : unary
972    //         | unary and
973    //
974    // unary   : primary '*'
975    //         | primary '?'
976    //
977    // primary : '[' opt_begin opt_chars opt_end ']'
978    //         | '^'
979    //         | '$'
980    //         | char
981    //         | '(' exp ')'
982    //
983 
984  {
985      //
986      // First we build an cmt_or_node (corresponding to the
987      // first grammatical rule)
988      //
989      //  Then cmt_and_nodes are pushed into it.
990      //  and standard nodes are pushed into the running (top_and) cmt_and_node
991      //
992    or_root = new cmt_or_node (0);
993    top_and = new cmt_and_node (or_root);
994  }
995 
996  int i;
997 
998  for (i = 0; i < expression.size (); i++)
999    {
1000      char c = expression[i];
1001      switch (c)
1002        {
1003          case '[':
1004          {
1005              //
1006              // The case is
1007              //
1008              //  exp   : '['     char ... ']'
1009              //  exp   : '[' '^' char ... ']'
1010              //
1011
1012            if (i >= expression.size ()) 
1013              {
1014                  // syntax error : unbalanced '['
1015                delete or_root;
1016                return;
1017              }
1018            i++;
1019           
1020            int i0 = i;
1021           
1022            bool done = false;
1023            bool has_not = false;
1024           
1025            cmt_string choices = "";
1026           
1027            for (; i < expression.size (); i++)
1028              {
1029                c = expression[i];
1030                switch (c)
1031                  {
1032                    case ']':
1033                      done = true;
1034                      break;
1035                    case '^':
1036                      if (i == i0) has_not = true;
1037                      else choices += c;
1038                      break;
1039                    case '\\':
1040                      choices += c;
1041                      if (i >= expression.size ())
1042                        {
1043                            // syntax error : unbalanced '[' and unfinished
1044                            // escape sequence
1045                          delete or_root;
1046                          return;
1047                        }
1048                      i++;
1049                      c = expression[i];
1050                      choices += c;
1051                      break;
1052                    default:
1053                      choices += c;
1054                      break;
1055                  }
1056                if (done) break;
1057              }
1058           
1059            if (!done)
1060              {
1061                  // syntax error : unbalanced '['
1062                delete or_root;
1063                return;
1064              }
1065            if (has_not)
1066              top_and->push (new cmt_not_char_list_node (choices));
1067            else       
1068              top_and->push (new cmt_char_list_node (choices));
1069          }
1070          break;
1071          case '*':
1072          {
1073              //
1074              //  exp : exp '*'
1075              //
1076            if (top_and->nodes () == 0)
1077              {
1078                  // Syntax error : '*' is not preceded by an expression
1079                delete or_root;
1080                return;
1081              }
1082           
1083            cmt_node* n = top_and->pop ();
1084            top_and->push (new cmt_zero_more (n));
1085          }
1086          break;
1087          case '+':
1088          {
1089              //
1090              //  exp : exp '+'
1091              //
1092            if (top_and->nodes () == 0)
1093              {
1094                  // Syntax error : '+' is not preceded by an expression
1095                delete or_root;
1096                return;
1097              }
1098           
1099            cmt_node* n = top_and->pop ();
1100            top_and->push (new cmt_one_more (n));
1101          }
1102          break;
1103          case '?':
1104          {
1105              //
1106              //  exp : exp '?'
1107              //
1108            if (top_and->nodes () == 0)
1109              {
1110                  // Syntax error : '?' is not preceded by an expression
1111                delete or_root;
1112                return;
1113              }
1114           
1115            cmt_node* n = top_and->pop ();
1116            top_and->push (new cmt_zero_one (n));
1117          }
1118          break;
1119          case '.':
1120              //
1121              //  exp : '.'
1122              //
1123            top_and->push (new cmt_any_node ());
1124            break;
1125          case '(':
1126          {
1127              //
1128              //  exp : '(' exp ')'
1129              //
1130            if (top_and->parentheses ())
1131              {
1132                  // This should never happen.
1133                delete or_root;
1134                return;
1135              }
1136           
1137            top_and->set_parentheses (true);
1138           
1139              //
1140              // A new complete expression is started.
1141              //  -> do as for top_and parsing.
1142              //
1143           
1144            top_and = new cmt_and_node (new cmt_or_node (top_and));
1145          }
1146          break;
1147          case ')':
1148          {
1149              //
1150              //  exp : '(' exp ')'
1151              //
1152           
1153              // top_and is the cmt_and_node into which new nodes are pushed.
1154            cmt_node_set* or_node = top_and->father ();
1155            if (or_node == 0) 
1156              {
1157                  // This should never happen : top_and should always be
1158                  // at least an cmt_and_node hanging at an cmt_or_node
1159                delete or_root;
1160                return;
1161              }
1162           
1163              //
1164              // The last cmt_and_node was empty, thus we had either '()' or '(...|)'
1165              //
1166           
1167            if (top_and->nodes () == 0) 
1168              {
1169                delete (or_node->pop ());
1170              }
1171            else
1172              {
1173                top_and->reduce ();
1174              }
1175           
1176            top_and = or_node->father ();
1177           
1178            if (top_and == 0)
1179              {
1180                  // Syntax error : too many ')'
1181                delete or_root;
1182                return;
1183              }
1184           
1185              //
1186              // top_and is now the previous running cmt_and_node where the '('
1187              // was originally met its top_and node contains the parenthesized
1188              // sub expression  If this one is empty, (due to an empty '()'
1189              // expression) then it may simply be discarded.
1190              //
1191           
1192            if (!top_and->parentheses ())
1193              {
1194                  // Syntax error : too many ')'
1195                delete or_root;
1196                return;
1197              }
1198           
1199            top_and->set_parentheses (false);
1200           
1201            cmt_node* unique = 0;
1202            if (or_node->nodes () == 1)
1203              {
1204                cmt_node_set* and_node = (cmt_node_set*) or_node->top ();
1205                if (and_node->nodes () == 1)
1206                  {
1207                    unique = and_node->pop ();
1208                    delete (or_node->pop ());
1209                  }
1210                else if (and_node->nodes () == 0)
1211                  {
1212                    delete (or_node->pop ());
1213                  }
1214              }
1215           
1216            if (or_node->nodes () == 0) delete (top_and->pop ());
1217            if (unique != 0) top_and->push (unique);
1218          }
1219         
1220          break;
1221          case '|':
1222          {
1223              //
1224              //  exp : exp '|' exp
1225              //
1226
1227            cmt_node_set* or_node = top_and->father ();
1228           
1229            top_and->reduce ();
1230           
1231              //
1232              // or is the father cmt_or_node, which only contains cmt_and_nodes
1233              //
1234           
1235            const cmt_node_set* and_node = (cmt_node_set*) or_node->top ();
1236            if (and_node->nodes () == 0)
1237              {
1238                  // the previous node was empty.
1239                  // we may discard it
1240                or_node->pop ();
1241              }
1242           
1243            top_and = new cmt_and_node (or_node);
1244          }
1245          break;
1246          case '^':
1247              //
1248              //  exp : '^'
1249              //
1250            top_and->push (new cmt_begin_node ());
1251            break;
1252          case '$':
1253              //
1254              //  exp : '$'
1255              //
1256            top_and->push (new cmt_end_node ());
1257            break;
1258          case '\\':
1259            if (i >= expression.size ())
1260              {
1261                delete or_root;
1262                return;
1263              }
1264            i++;
1265            c = expression[i];
1266            switch (c)
1267              {
1268                case '[':
1269                case ']':
1270                case '(':
1271                case ')':
1272                case '.':
1273                case '*':
1274                case '?':
1275                case '^':
1276                case '$':
1277                case '\\':
1278                  break;
1279                case 'r':
1280                  c = '\r';
1281                  break;
1282                case 't':
1283                  c = '\t';
1284                  break;
1285                case 'n':
1286                  c = '\n';
1287                  break;
1288                default:
1289                  break;
1290              }
1291          default:
1292            top_and->push (new cmt_char_node (c));
1293            break;
1294        }
1295    }
1296 
1297  if (or_root != 0)
1298    {
1299      cmt_node_set* and_node = (cmt_node_set*) or_root->top ();
1300     
1301      if (or_root->nodes () == 1)
1302        {
1303            //
1304            // Check whether there is at least one non-empty
1305            // cmt_and_node
1306            //
1307          if (and_node->nodes () == 0)
1308            {
1309              delete or_root;
1310              return;
1311            }
1312        }
1313     
1314      if (and_node != 0)
1315        {
1316          and_node->reduce ();
1317         
1318          if (and_node->parentheses ())
1319            {
1320              delete or_root;
1321              return;
1322            }
1323        }
1324    }
1325 
1326  _root = or_root;
1327}
1328
1329cmt_regexp::~cmt_regexp ()
1330{
1331  if (_root != 0)
1332    {
1333      delete _root;
1334    }
1335}
1336
1337bool cmt_regexp::is_valid () const
1338{
1339  if (_root != 0) return (true);
1340  else return (false);
1341}
1342
1343cmt_regexp::iterator cmt_regexp::begin (const cmt_string& text, int pos)
1344{
1345  if (_root != 0)
1346    {
1347      int i;
1348     
1349      for (i = pos; i < text.size (); i++)
1350        {
1351          cmt_regexp::iterator it = _root->match (text, i);
1352          if (it != end ()) return (it);
1353        }
1354    }
1355 
1356  return (end ());
1357}
1358
1359cmt_regexp::iterator cmt_regexp::end ()
1360{
1361  return (cmt_regexp::iterator::null ());
1362}
1363
1364cmt_regexp::iterator cmt_regexp::begin (const cmt_string& text, int pos) const
1365{
1366  if (_root != 0)
1367    {
1368      int i;
1369     
1370      for (i = pos; i < text.size (); i++)
1371        {
1372          cmt_regexp::iterator it = _root->match (text, i);
1373          if (it != end ()) return (it);
1374        }
1375    }
1376 
1377  return (end ());
1378}
1379
1380cmt_regexp::iterator cmt_regexp::end () const
1381{
1382  return (cmt_regexp::iterator::null ());
1383}
1384
1385bool cmt_regexp::match (const cmt_string& text) const
1386{
1387  iterator it = begin (text);
1388  if (it == end ()) return (false);
1389  else return (true);
1390}
1391//----------------------------------------------------------
1392
1393//----------------------------------------------------------
1394const cmt_regexp::iterator cmt_regexp::iterator::null ()
1395{
1396  static const iterator null_instance (-1, -1);
1397 
1398  return (null_instance);
1399}
1400
1401cmt_regexp::iterator::iterator ()
1402{
1403  _pos = 0;
1404  _length = 0;
1405}
1406
1407cmt_regexp::iterator::iterator (int pos, int length)
1408{
1409  _pos = pos;
1410  _length = length;
1411}
1412
1413cmt_regexp::iterator::iterator (const iterator& other)
1414{
1415  _pos = other._pos;
1416  _length = other._length;
1417}
1418
1419int cmt_regexp::iterator::operator != (const iterator& other) const
1420{
1421  return ((this->_pos != other._pos) ||
1422          (this->_length != other._length));
1423}
1424
1425int cmt_regexp::iterator::operator == (const iterator& other) const
1426{
1427  return ((this->_pos == other._pos) &&
1428          (this->_length == other._length));
1429}
1430//----------------------------------------------------------
1431
Note: See TracBrowser for help on using the repository browser.