Modules |
Files |
Inheritance Tree |
Inheritance Graph |
Name Index |
Config
File: Synopsis/Parser/C++/occ/ptree-core.cc
1| /*
2| Copyright (C) 1997-2000 Shigeru Chiba, University of Tsukuba.
3|
4| Permission to use, copy, distribute and modify this software and
5| its documentation for any purpose is hereby granted without fee,
6| provided that the above copyright notice appear in all copies and that
7| both that copyright notice and this permission notice appear in
8| supporting documentation.
9|
10| Shigeru Chiba makes no representations about the suitability of this
11| software for any purpose. It is provided "as is" without express or
12| implied warranty.
13| */
14|
15| #include <iostream>
16| #include <cstring>
17| #include "ptree.h"
18| #include "token.h"
19| #include "walker.h"
20| #include "typeinfo.h"
21| #include "buffer.h"
22|
23| #if defined(_MSC_VER) || defined(IRIX_CC) || defined(__GLIBC__)
24| #include <stdlib.h> /
25| #endif
26|
27| bool Ptree::show_encoded = FALSE;
28|
29|
30|
31| void MopErrorMessage(char* where, char* msg)
32| {
33| std::cerr << "MOP error: in " << where << ", " << msg << '\n';
34| exit(1);
35| }
36|
37| void MopErrorMessage2(char* msg1, char* msg2)
38| {
39| std::cerr << "MOP error: " << msg1 << msg2 << '\n';
40| exit(1);
41| }
42|
43| void MopWarningMessage(char* where, char* msg)
44| {
45| std::cerr << "MOP warning: in " << where << ", " << msg << '\n';
46| }
47|
48| void MopWarningMessage2(char* msg1, char* msg2)
49| {
50| std::cerr << "MOP warning: " << msg1 << msg2 << '\n';
51| }
52|
53| void MopMoreWarningMessage(char* msg1, char* msg2)
54| {
55| std::cerr << " " << msg1;
56| if(msg2 != nil)
57| std::cerr << msg2;
58|
59| std::cerr << '\n';
60| }
61|
62| // class Ptree
63|
64| void Ptree::Display()
65| {
66| Display2(std::cerr);
67| }
68|
69| void Ptree::Display2(std::ostream& s)
70| {
71| if(this == nil)
72| s << "nil\n";
73| else{
74| Print(s, 0, 0);
75| s << '\n';
76| }
77| }
78|
79| int Ptree::Write(std::ostream& s)
80| {
81| if(this == nil)
82| return 0;
83| else
84| return Write(s, 0);
85| }
86|
87| void Ptree::PrintIndent(std::ostream& out, int indent)
88| {
89| out << '\n';
90| for(int i = 0; i < indent; ++i)
91| out << " ";
92| }
93|
94| char* Ptree::ToString()
95| {
96| if(this == nil)
97| return nil;
98| else{
99| ProgramString ps;
100| WritePS(ps);
101| return (char*)ps.Read(0);
102| }
103| }
104|
105| bool Ptree::Eq(char c)
106| {
107| if(this == nil)
108| return FALSE;
109| else
110| return(IsLeaf() && GetLength() == 1 && *GetPosition() == c);
111| }
112|
113| bool Ptree::Eq(char* str)
114| {
115| if(this == nil)
116| return FALSE;
117| else if(IsLeaf()){
118| char* p = GetPosition();
119| int n = GetLength();
120| int i;
121| for(i = 0; i < n; ++i)
122| if(p[i] != str[i] || str[i] == '\0')
123| return FALSE;
124|
125| return bool(str[i] == '\0');
126| }
127| else
128| return FALSE;
129| }
130|
131| bool Ptree::Eq(char* str, int len)
132| {
133| if(this != nil && IsLeaf()){
134| char* p = GetPosition();
135| int n = GetLength();
136| if(n == len){
137| int i;
138| for(i = 0; i < n; ++i)
139| if(p[i] != str[i])
140| return FALSE;
141|
142| return TRUE;
143| }
144| }
145|
146| return FALSE;
147| }
148|
149| Ptree* Ptree::Ca_ar() // compu
150| {
151| Ptree* p = this;
152| while(p != nil && !p->IsLeaf())
153| p = p->Car();
154|
155| return p;
156| }
157|
158| char* Ptree::LeftMost()
159| {
160| if(this == nil)
161| return nil;
162| else if(IsLeaf())
163| return GetPosition();
164| else{
165| Ptree* p = this;
166| while(p != nil){
167| char* i = p->Car()->LeftMost();
168| if(i != nil)
169| return i;
170| else
171| p = p->Cdr();
172| }
173| return nil;
174| }
175| }
176|
177| char* Ptree::RightMost()
178| {
179| if(this == nil)
180| return nil;
181| else if(IsLeaf())
182| return GetPosition() + GetLength();
183| else{
184| int n = Length();
185| while(n > 0){
186| char* i = Nth(--n)->RightMost();
187| if(i != nil)
188| return i;
189| }
190|
191| return nil;
192| }
193| }
194|
195| int Ptree::What()
196| {
197| return BadToken;
198| }
199|
200| bool Ptree::IsA(int kind)
201| {
202| if(this == nil)
203| return FALSE;
204| else
205| return bool(What() == kind);
206| }
207|
208| bool Ptree::IsA(int kind1, int kind2)
209| {
210| if(this == nil)
211| return FALSE;
212| else{
213| int k = What();
214| return bool(k == kind1 || k == kind2);
215| }
216| }
217|
218| bool Ptree::IsA(int kind1, int kind2, int kind3)
219| {
220| if(this == nil)
221| return FALSE;
222| else{
223| int k = What();
224| return bool(k == kind1 || k == kind2 || k == kind3);
225| }
226| }
227|
228| Ptree* Ptree::Translate(Walker* w)
229| {
230| return w->TranslatePtree(this);
231| }
232|
233| void Ptree::Typeof(Walker* w, TypeInfo& t)
234| {
235| w->TypeofPtree(this, t);
236| }
237|
238| char* Ptree::GetEncodedType()
239| {
240| return nil;
241| }
242|
243| char* Ptree::GetEncodedName()
244| {
245| return nil;
246| }
247|
248|
249| // static members
250|
251| bool Ptree::Eq(Ptree* p, char c)
252| {
253| return p->Eq(c);
254| }
255|
256| bool Ptree::Eq(Ptree* p, char* str)
257| {
258| return p->Eq(str);
259| }
260|
261| bool Ptree::Eq(Ptree* p, char* str, int len)
262| {
263| return p->Eq(str, len);
264| }
265|
266| bool Ptree::Eq(Ptree* p, Ptree* q)
267| {
268| if(p == q)
269| return TRUE;
270| else if(p == nil || q == nil)
271| return FALSE;
272| else if(p->IsLeaf() && q->IsLeaf()){
273| int plen = p->GetLength();
274| int qlen = q->GetLength();
275| if(plen == qlen){
276| char* pstr = p->GetPosition();
277| char* qstr = q->GetPosition();
278| while(--plen >= 0)
279| if(pstr[plen] != qstr[plen])
280| return FALSE;
281|
282| return TRUE;
283| }
284| }
285|
286| return FALSE;
287| }
288|
289| /*
290| Equiv() returns true even if p and q are lists and all the elements
291| are equal respectively.
292| */
293| bool Ptree::Equiv(Ptree* p, Ptree* q)
294| {
295| if(p == q)
296| return TRUE;
297| else if(p == nil || q == nil)
298| return FALSE;
299| else if(p->IsLeaf() || q->IsLeaf())
300| return Eq(p, q);
301| else{
302| while(p != nil && q != nil)
303| if(p->Car() != q->Car())
304| return FALSE;
305| else{
306| p = p->Cdr();
307| q = q->Cdr();
308| }
309|
310| return p == nil && q == nil;
311| }
312| }
313|
314| bool Ptree::Equal(Ptree* p, Ptree* q)
315| {
316| if(p == q)
317| return TRUE;
318| else if(p == nil || q == nil)
319| return FALSE;
320| else if(p->IsLeaf() || q->IsLeaf())
321| return Eq(p, q);
322| else
323| return Equal(p->Car(), q->Car()) && Equal(p->Cdr(), q->Cdr());
324| }
325|
326| Ptree* Ptree::Last(Ptree* p) // return the last cons c
327| {
328| Ptree* next;
329| if(p == nil)
330| return nil;
331|
332| while((next = p->Cdr()) != nil)
333| p = next;
334|
335| return p;
336| }
337|
338| Ptree* Ptree::First(Ptree* p)
339| {
340| if(p != nil)
341| return p->Car();
342| else
343| return p;
344| }
345|
346| Ptree* Ptree::Rest(Ptree* p)
347| {
348| if(p != nil)
349| return p->Cdr();
350| else
351| return p;
352| }
353|
354| Ptree* Ptree::Second(Ptree* p)
355| {
356| if(p != nil){
357| p = p->Cdr();
358| if(p != nil)
359| return p->Car();
360| }
361|
362| return p;
363| }
364|
365| Ptree* Ptree::Third(Ptree* p)
366| {
367| if(p != nil){
368| p = p->Cdr();
369| if(p != nil){
370| p = p->Cdr();
371| if(p != nil)
372| return p->Car();
373| }
374| }
375|
376| return p;
377| }
378|
379| /*
380| Nth(lst, 0) is equivalent to First(lst).
381| */
382| Ptree* Ptree::Nth(Ptree* p, int n)
383| {
384| while(p != nil && n-- > 0)
385| p = p->Cdr();
386|
387| if(p != nil)
388| return p->Car();
389| else
390| return p;
391| }
392|
393| /*
394| Length() returns a negative number if p is not a list.
395| */
396| int Ptree::Length(Ptree* p)
397| {
398| int i = 0;
399|
400| if(p != nil && p->IsLeaf())
401| return -2; /* p is not a pa
402|
403| while(p != nil){
404| ++i;
405| if(p->IsLeaf())
406| return -1; /* p is a pair, but not a list. *
407| else
408| p = p->Cdr();
409| }
410|
411| return i;
412| }
413|
414| Ptree* Ptree::ListTail(Ptree* p, int k)
415| {
416| while(p != nil && k-- > 0)
417| p = p->Cdr();
418|
419| return p;
420| }
421|
422| Ptree* Ptree::Cons(Ptree* p, Ptree* q)
423| {
424| return new NonLeaf(p, q);
425| }
426|
427| Ptree* Ptree::List(Ptree* p)
428| {
429| return new NonLeaf(p, nil);
430| }
431|
432| Ptree* Ptree::List()
433| {
434| return nil;
435| }
436|
437| Ptree* Ptree::List(Ptree* p, Ptree* q)
438| {
439| return new NonLeaf(p, new NonLeaf(q, nil));
440| }
441|
442| Ptree* Ptree::List(Ptree* p1, Ptree* p2, Ptree* p3)
443| {
444| return new NonLeaf(p1, new NonLeaf(p2, new NonLeaf(p3, nil)));
445| }
446|
447| Ptree* Ptree::List(Ptree* p1, Ptree* p2, Ptree* p3, Ptree* p4)
448| {
449| return new NonLeaf(p1, List(p2, p3, p4));
450| }
451|
452| Ptree* Ptree::List(Ptree* p1, Ptree* p2, Ptree* p3, Ptree* p4, Ptree* p5)
453| {
454| return Nconc(List(p1, p2), List(p3, p4, p5));
455| }
456|
457| Ptree* Ptree::List(Ptree* p1, Ptree* p2, Ptree* p3, Ptree* p4, Ptree* p5,
458| Ptree* p6)
459| {
460| return Nconc(List(p1, p2, p3), List(p4, p5, p6));
461| }
462|
463| Ptree* Ptree::List(Ptree* p1, Ptree* p2, Ptree* p3, Ptree* p4, Ptree* p5,
464| Ptree* p6, Ptree* p7)
465| {
466| return Nconc(List(p1, p2, p3), List(p4, p5, p6, p7));
467| }
468|
469| Ptree* Ptree::List(Ptree* p1, Ptree* p2, Ptree* p3, Ptree* p4, Ptree* p5,
470| Ptree* p6, Ptree* p7, Ptree* p8)
471| {
472| return Nconc(List(p1, p2, p3, p4), List(p5, p6, p7, p8));
473| }
474|
475| Ptree* Ptree::CopyList(Ptree* p)
476| {
477| return Append(p, nil);
478| }
479|
480| // q may be a leaf
481| //
482| Ptree* Ptree::Append(Ptree* p, Ptree* q)
483| {
484| Ptree *result, *tail;
485|
486| if(p == nil)
487| if(q->IsLeaf())
488| return Cons(q, nil);
489| else
490| return q;
491|
492| result = tail = Cons(p->Car(), nil);
493| p = p->Cdr();
494| while(p != nil){
495| Ptree* cell = Cons(p->Car(), nil);
496| tail->SetCdr(cell);
497| tail = cell;
498| p = p->Cdr();
499| }
500|
501| if(q != nil && q->IsLeaf())
502| tail->SetCdr(Cons(q, nil));
503| else
504| tail->SetCdr(q);
505|
506| return result;
507| }
508|
509| /*
510| ReplaceAll() substitutes SUBST for all occurences of ORIG in LIST.
511| It recursively searches LIST for ORIG.
512| */
513| Ptree* Ptree::ReplaceAll(Ptree* list, Ptree* orig, Ptree* subst)
514| {
515| if(Eq(list, orig))
516| return subst;
517| else if(list == nil || list->IsLeaf())
518| return list;
519| else{
520| PtreeArray newlist;
521| bool changed = FALSE;
522| Ptree* rest = list;
523| while(rest != nil){
524| Ptree* p = rest->Car();
525| Ptree* q = ReplaceAll(p, orig, subst);
526| newlist.Append(q);
527| if(p != q)
528| changed = TRUE;
529|
530| rest = rest->Cdr();
531| }
532|
533| if(changed)
534| return newlist.All();
535| else
536| return list;
537| }
538| }
539|
540| Ptree* Ptree::Subst(Ptree* newone, Ptree* old, Ptree* tree)
541| {
542| if(old == tree)
543| return newone;
544| else if(tree== nil || tree->IsLeaf())
545| return tree;
546| else{
547| Ptree* head = tree->Car();
548| Ptree* head2 = Subst(newone, old, head);
549| Ptree* tail = tree->Cdr();
550| Ptree* tail2 = (tail == nil) ? tail : Subst(newone, old, tail);
551| if(head == head2 && tail == tail2)
552| return tree;
553| else
554| return Cons(head2, tail2);
555| }
556| }
557|
558| Ptree* Ptree::Subst(Ptree* newone1, Ptree* old1, Ptree* newone2, Ptree* old2,
559| Ptree* tree)
560| {
561| if(old1 == tree)
562| return newone1;
563| else if(old2 == tree)
564| return newone2;
565| else if(tree == nil || tree->IsLeaf())
566| return tree;
567| else{
568| Ptree* head = tree->Car();
569| Ptree* head2 = Subst(newone1, old1, newone2, old2, head);
570| Ptree* tail = tree->Cdr();
571| Ptree* tail2 = (tail == nil) ? tail
572| : Subst(newone1, old1, newone2, old2, tail);
573| if(head == head2 && tail == tail2)
574| return tree;
575| else
576| return Cons(head2, tail2);
577| }
578| }
579|
580| Ptree* Ptree::Subst(Ptree* newone1, Ptree* old1, Ptree* newone2, Ptree* old2,
581| Ptree* newone3, Ptree* old3, Ptree* tree)
582| {
583| if(old1 == tree)
584| return newone1;
585| else if(old2 == tree)
586| return newone2;
587| else if(old3 == tree)
588| return newone3;
589| else if(tree == nil || tree->IsLeaf())
590| return tree;
591| else{
592| Ptree* head = tree->Car();
593| Ptree* head2 = Subst(newone1, old1, newone2, old2,
594| newone3, old3, head);
595| Ptree* tail = tree->Cdr();
596| Ptree* tail2 = (tail == nil) ? tail :
597| Subst(newone1, old1, newone2, old2,
598| newone3, old3, tail);
599| if(head == head2 && tail == tail2)
600| return tree;
601| else
602| return Cons(head2, tail2);
603| }
604| }
605|
606| // ShallowSubst() doesn't recursively apply substitution to a subtree.
607|
608| Ptree* Ptree::ShallowSubst(Ptree* newone, Ptree* old, Ptree* tree)
609| {
610| if(old == tree)
611| return newone;
612| else if(tree== nil || tree->IsLeaf())
613| return tree;
614| else{
615| Ptree *head, *head2;
616| head = tree->Car();
617| if(old == head)
618| head2 = newone;
619| else
620| head2 = head;
621|
622| Ptree* tail = tree->Cdr();
623| Ptree* tail2 = (tail == nil) ? tail : ShallowSubst(newone, old, tail);
624| if(head == head2 && tail == tail2)
625| return tree;
626| else
627| return Cons(head2, tail2);
628| }
629| }
630|
631| Ptree* Ptree::ShallowSubst(Ptree* newone1, Ptree* old1,
632| Ptree* newone2, Ptree* old2, Ptree* tree)
633| {
634| if(old1 == tree)
635| return newone1;
636| else if(old2 == tree)
637| return newone2;
638| else if(tree == nil || tree->IsLeaf())
639| return tree;
640| else{
641| Ptree *head, *head2;
642| head = tree->Car();
643| if(old1 == head)
644| head2 = newone1;
645| else if(old2 == head)
646| head2 = newone2;
647| else
648| head2 = head;
649|
650| Ptree* tail = tree->Cdr();
651| Ptree* tail2 = (tail == nil) ? tail :
652| ShallowSubst(newone1, old1, newone2, old2, tail);
653| if(head == head2 && tail == tail2)
654| return tree;
655| else
656| return Cons(head2, tail2);
657| }
658| }
659|
660| Ptree* Ptree::ShallowSubst(Ptree* newone1, Ptree* old1,
661| Ptree* newone2, Ptree* old2,
662| Ptree* newone3, Ptree* old3, Ptree* tree)
663| {
664| if(old1 == tree)
665| return newone1;
666| else if(old2 == tree)
667| return newone2;
668| else if(old3 == tree)
669| return newone3;
670| else if(tree == nil || tree->IsLeaf())
671| return tree;
672| else{
673| Ptree *head, *head2;
674| head = tree->Car();
675| if(old1 == head)
676| head2 = newone1;
677| else if(old2 == head)
678| head2 = newone2;
679| else if(old3 == head)
680| head2 = newone3;
681| else
682| head2 = head;
683|
684| Ptree* tail = tree->Cdr();
685| Ptree* tail2 = (tail == nil) ? tail :
686| ShallowSubst(newone1, old1, newone2, old2,
687| newone3, old3, tail);
688| if(head == head2 && tail == tail2)
689| return tree;
690| else
691| return Cons(head2, tail2);
692| }
693| }
694|
695| Ptree* Ptree::ShallowSubst(Ptree* newone1, Ptree* old1,
696| Ptree* newone2, Ptree* old2,
697| Ptree* newone3, Ptree* old3,
698| Ptree* newone4, Ptree* old4, Ptree* tree)
699| {
700| if(old1 == tree)
701| return newone1;
702| else if(old2 == tree)
703| return newone2;
704| else if(old3 == tree)
705| return newone3;
706| else if(old4 == tree)
707| return newone4;
708| else if(tree == nil || tree->IsLeaf())
709| return tree;
710| else{
711| Ptree *head, *head2;
712| head = tree->Car();
713| if(old1 == head)
714| head2 = newone1;
715| else if(old2 == head)
716| head2 = newone2;
717| else if(old3 == head)
718| head2 = newone3;
719| else if(old4 == head)
720| head2 = newone4;
721| else
722| head2 = head;
723|
724| Ptree* tail = tree->Cdr();
725| Ptree* tail2 = (tail == nil) ? tail :
726| ShallowSubst(newone1, old1, newone2, old2,
727| newone3, old3, newone4, old4, tail);
728| if(head == head2 && tail == tail2)
729| return tree;
730| else
731| return Cons(head2, tail2);
732| }
733| }
734|
735| Ptree* Ptree::SubstSublist(Ptree* newsub, Ptree* oldsub, Ptree* lst)
736| {
737| if(lst == oldsub)
738| return newsub;
739| else
740| return Cons(lst->Car(), SubstSublist(newsub, oldsub, lst->Cdr()));
741| }
742|
743| Ptree* Ptree::Snoc(Ptree* p, Ptree* q)
744| {
745| return Nconc(p, Cons(q, nil));
746| }
747|
748| /* Nconc is desctructive append */
749|
750| Ptree* Ptree::Nconc(Ptree* p, Ptree* q)
751| {
752| if(p == nil)
753| return q;
754| else{
755| Last(p)->data.nonleaf.next = q; // Last(p)->Se
756| return p;
757| }
758| }
759|
760| Ptree* Ptree::Nconc(Ptree* p, Ptree* q, Ptree* r)
761| {
762| return Nconc(p, Nconc(q, r));
763| }
764|
765|
766| // class PtreeIter
767|
768| Ptree* PtreeIter::Pop()
769| {
770| if(ptree == nil)
771| return nil;
772| else{
773| Ptree* p = ptree->Car();
774| ptree = ptree->Cdr();
775| return p;
776| }
777| }
778|
779| bool PtreeIter::Next(Ptree*& car)
780| {
781| if(ptree == nil)
782| return FALSE;
783| else{
784| car = ptree->Car();
785| ptree = ptree->Cdr();
786| return TRUE;
787| }
788| }
789|
790| Ptree* PtreeIter::This()
791| {
792| if(ptree == nil)
793| return nil;
794| else
795| return ptree->Car();
796| }
797|
798| // class PtreeArray
799|
800| PtreeArray::PtreeArray(int s)
801| {
802| num = 0;
803| if(s > 8){
804| size = s;
805| array = new (GC) Ptree*[s];
806| }
807| else{
808| size = 8;
809| array = default_buf;
810| }
811| }
812|
813| void PtreeArray::Append(Ptree* p)
814| {
815| if(num >= size){
816| size += 8;
817| Ptree** a = new (GC) Ptree*[size];
818| memmove(a, array, size_t(num * sizeof(Ptree*)));
819| array = a;
820| }
821|
822| array[num++] = p;
823| }
824|
825| Ptree*& PtreeArray::Ref(uint i)
826| {
827| if(i < num)
828| return array[i];
829| else{
830| MopErrorMessage("PtreeArray", "out of range");
831| return array[0];
832| }
833| }
834|
835| Ptree* PtreeArray::All()
836| {
837| Ptree* lst = nil;
838|
839| for(sint i = Number() - 1; i >= 0; --i)
840| lst = Ptree::Cons(Ref(i), lst);
841|
842| return lst;
843| }