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