1 /* Hapy is a public domain software. See Hapy README file for the details. */
2
3 #ifndef HAPY_PREE__H
4 #define HAPY_PREE__H
5
6 #include <Hapy/Top.h>
7 #include <Hapy/Area.h>
8 #include <Hapy/RuleId.h>
9 #include <Hapy/PreeKids.h>
10 #include <Hapy/String.h>
11 #include <Hapy/IosFwd.h>
12
13 namespace Hapy {
14
15 // a node of a parse result tree
16 class Pree {
17 public:
18 typedef unsigned int size_type;
19 typedef PreeKidsIterator<Pree> iterator;
20 typedef PreeKidsIterator<const Pree> const_iterator;
21
22 public:
23 Pree();
24 Pree(const Pree &p);
25 ~Pree();
26
27 void clear();
28
29 // these are usually used by interpreters; they skip trimmings
30 const RuleId &rid() const;
31 size_type count() const;
32 const_iterator begin() const;
33 const_iterator end() const;
34 const Pree &operator [](size_type idx) const;
35 const Pree &find(const RuleId &id) const;
36 const string &image() const;
37
38 // these raw interfaces are usually used by parsers
39 const RuleId &rawRid() const;
40 void rawRid(const RuleId &aRid);
41 size_type rawCount() const;
42 size_type rawDeepCount() const;
43 const Pree &top() const;
44 const Pree &backChild() const;
45 const Pree &rawChild(size_type idx) const;
46 Pree &backChild();
47 Pree &newChild();
48 void popChild(); // extracts and destroys the last child
49 void rawPopChild(Pree *kid); // extracts specified child
50 void pushChild(Pree *kid); // adds the last child
51 Pree *popSubTree(); // extracts this->down and shapes it as a tree
52
53 bool emptyHorizontalLoop() const;
54 bool emptyVerticalLoop() const;
55 size_type expectedMinSize() const;
56 void commit();
57 const string &rawImage() const;
58 void rawImage(const string &anImage);
59 const_iterator rawBegin() const;
60 const_iterator rawEnd() const;
61
62 std::ostream &print(std::ostream &os) const;
63 std::ostream &print(std::ostream &os, const string &pfx) const;
64 std::ostream &rawPrint(std::ostream &os, const string &pfx) const;
65
66 // maybe slow; not optimized yet!
67 Pree &operator =(const Pree &p);
68
69 protected:
70 inline static void InsertAfter(Pree *p1, Pree *p2);
71 inline static void HalfConnect(Pree *p1, Pree *p2);
72
73 public:
74 Area match;
75
76 Pree *up; // parent or null
77 Pree *down; // kids or null
78 Pree *left; // previous sibling or self
79 Pree *right; // next sibling or self
80 size_type kidCount; // number of children
81
82 size_type idata; // used by parsing rules to keep state
83 size_type minSize; // used by parsing rules to keep state
84
85 bool implicit;
86 bool leaf;
87
88 protected:
89 bool deeplyImplicit() const;
90 void clearKids();
91 void kidlessAssign(const Pree &p);
92 void copyKids(const Pree &source);
aboutToModify()93 void aboutToModify() {}
94 const Pree &coreNode() const;
95
96 bool sameState(const Pree &n) const;
97 bool sameSegment(const Pree *them, bool &exhausted) const;
98
99 private:
100 RuleId theRid;
101 };
102
103 template <class Function>
104 inline
for_some(const Pree & n,const RuleId & rid,Function f)105 void for_some(const Pree &n, const RuleId &rid, Function f) {
106 for (Pree::const_iterator i = n.begin(); i < n.end(); ++i) {
107 if (i->rid() == rid)
108 (f)(*i);
109 else
110 for_some(*i, rid, f);
111 }
112 }
113
114 inline
find_first(const Pree & n,const RuleId & rid)115 const Pree *find_first(const Pree &n, const RuleId &rid) {
116 for (Pree::const_iterator i = n.begin(); i < n.end(); ++i) {
117 if (i->rid() == rid)
118 return &(*i);
119 if (const Pree *p = find_first(*i, rid))
120 return p;
121 }
122 return 0;
123 }
124
125 template <class Function>
126 inline
find_if(const Pree & n,Function f)127 const Pree *find_if(const Pree &n, Function f) {
128 for (Pree::const_iterator i = n.begin(); i < n.end(); ++i) {
129 if ((f)(*i))
130 return &(*i);
131 if (const Pree *p = find_if(*i, f))
132 return p;
133 }
134 return 0;
135 }
136
137 inline
HalfConnect(Pree * p1,Pree * p2)138 void Pree::HalfConnect(Pree *p1, Pree *p2) {
139 p1->right = p2; // ignores p1->left
140 p2->left = p1; // ignores p2->right
141 }
142
143 inline
InsertAfter(Pree * p1,Pree * p2)144 void Pree::InsertAfter(Pree *p1, Pree *p2) {
145 Pree *p4 = p1->right;
146 Pree *p3 = p2->left;
147 HalfConnect(p1, p2);
148 HalfConnect(p3, p4);
149 }
150
151
152 } // namespace
153
154 #endif
155
156