1 : /* GRAPHITE2 LICENSING
2 :
3 : Copyright 2010, SIL International
4 : All rights reserved.
5 :
6 : This library is free software; you can redistribute it and/or modify
7 : it under the terms of the GNU Lesser General Public License as published
8 : by the Free Software Foundation; either version 2.1 of License, or
9 : (at your option) any later version.
10 :
11 : This program is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should also have received a copy of the GNU Lesser General Public
17 : License along with this library in the file named "LICENSE".
18 : If not, write to the Free Software Foundation, 51 Franklin Street,
19 : Suite 500, Boston, MA 02110-1335, USA or visit their web page on the
20 : internet at http://www.fsf.org/licenses/lgpl.html.
21 :
22 : Alternatively, the contents of this file may be used under the terms of the
23 : Mozilla Public License (http://mozilla.org/MPL) or the GNU General Public
24 : License, as published by the Free Software Foundation, either version 2
25 : of the License or (at your option) any later version.
26 : */
27 :
28 : #pragma once
29 :
30 : #include "inc/Code.h"
31 : #include "inc/Slot.h"
32 :
33 : namespace graphite2 {
34 :
35 : struct Rule {
36 : const vm::Machine::Code * constraint,
37 : * action;
38 : unsigned short sort;
39 : byte preContext;
40 : #ifndef NDEBUG
41 : uint16 rule_idx;
42 : #endif
43 :
44 0 : Rule() : constraint(0), action(0) {}
45 : ~Rule();
46 :
47 0 : CLASS_NEW_DELETE;
48 : };
49 :
50 0 : inline Rule::~Rule()
51 : {
52 0 : delete constraint;
53 0 : delete action;
54 0 : }
55 :
56 :
57 : struct RuleEntry
58 : {
59 : const Rule * rule;
60 :
61 0 : inline bool operator < (const RuleEntry &r) const
62 : {
63 0 : const unsigned short lsort = rule->sort, rsort = r.rule->sort;
64 0 : return lsort > rsort || (lsort == rsort && rule < r.rule);
65 : }
66 :
67 : inline bool operator == (const RuleEntry &r) const
68 : {
69 : return rule == r.rule;
70 : }
71 : };
72 :
73 :
74 : struct State
75 : {
76 : const RuleEntry * rules,
77 : * rules_end;
78 : const State * const * transitions;
79 :
80 : size_t size() const;
81 : bool is_success() const;
82 : bool is_transition() const;
83 : #ifndef NDEBUG
84 : uint32 index;
85 : #endif
86 : };
87 :
88 0 : inline size_t State::size() const
89 : {
90 0 : return rules_end - rules;
91 : }
92 :
93 0 : inline bool State::is_success() const
94 : {
95 0 : return (rules != NULL);
96 : }
97 :
98 0 : inline bool State::is_transition() const
99 : {
100 0 : return (transitions != NULL);
101 : }
102 :
103 :
104 : class SlotMap
105 : {
106 : public:
107 : enum {MAX_SLOTS=64};
108 : SlotMap(Segment & seg);
109 :
110 : Slot * * begin();
111 : Slot * * end();
112 : size_t size() const;
113 : unsigned short context() const;
114 : void reset(Slot &, unsigned short);
115 :
116 : Slot * const & operator[](int n) const;
117 : Slot * & operator [] (int);
118 : void pushSlot(Slot * const slot);
119 : void collectGarbage();
120 :
121 0 : Slot * highwater() { return m_highwater; }
122 0 : void highwater(Slot *s) { m_highwater = s; m_highpassed = false; }
123 0 : bool highpassed() const { return m_highpassed; }
124 0 : void highpassed(bool v) { m_highpassed = v; }
125 :
126 : Segment & segment;
127 : private:
128 : Slot * m_slot_map[MAX_SLOTS+1];
129 : unsigned short m_size;
130 : unsigned short m_precontext;
131 : Slot * m_highwater;
132 : bool m_highpassed;
133 : };
134 :
135 :
136 : class FiniteStateMachine
137 : {
138 : public:
139 : enum {MAX_RULES=128};
140 :
141 : private:
142 : class Rules
143 : {
144 : public:
145 : Rules();
146 : void clear();
147 : const RuleEntry * begin() const;
148 : const RuleEntry * end() const;
149 : size_t size() const;
150 :
151 : void accumulate_rules(const State &state);
152 :
153 : private:
154 : RuleEntry * m_begin,
155 : * m_end,
156 : m_rules[MAX_RULES*2];
157 : };
158 :
159 : public:
160 : FiniteStateMachine(SlotMap & map);
161 : void reset(Slot * & slot, const short unsigned int max_pre_ctxt);
162 : Rules rules;
163 : SlotMap & slots;
164 : };
165 :
166 0 : inline FiniteStateMachine::FiniteStateMachine(SlotMap& map)
167 0 : : slots(map)
168 : {
169 0 : }
170 :
171 0 : inline void FiniteStateMachine::reset(Slot * & slot, const short unsigned int max_pre_ctxt)
172 : {
173 0 : rules.clear();
174 0 : int ctxt = 0;
175 0 : for (; ctxt != max_pre_ctxt && slot->prev(); ++ctxt, slot = slot->prev());
176 0 : slots.reset(*slot, ctxt);
177 0 : }
178 :
179 0 : inline FiniteStateMachine::Rules::Rules()
180 0 : : m_begin(m_rules)
181 : {
182 0 : m_end = m_begin;
183 0 : }
184 :
185 0 : inline void FiniteStateMachine::Rules::clear()
186 : {
187 0 : m_end = m_begin;
188 0 : }
189 :
190 0 : inline const RuleEntry * FiniteStateMachine::Rules::begin() const
191 : {
192 0 : return m_begin;
193 : }
194 :
195 0 : inline const RuleEntry * FiniteStateMachine::Rules::end() const
196 : {
197 0 : return m_end;
198 : }
199 :
200 : inline size_t FiniteStateMachine::Rules::size() const
201 : {
202 : return m_end - m_begin;
203 : }
204 :
205 0 : inline void FiniteStateMachine::Rules::accumulate_rules(const State &state)
206 : {
207 : // Only bother if there are rules in the State object.
208 0 : if (state.size() == 0) return;
209 :
210 : // Merge the new sorted rules list into the current sorted result set.
211 0 : const RuleEntry * lre = begin(), * rre = state.rules;
212 0 : RuleEntry * out = m_rules + (m_begin == m_rules)*MAX_RULES;
213 0 : const RuleEntry * lrend = out + MAX_RULES;
214 0 : m_begin = out;
215 0 : while (lre != end() && out != lrend)
216 : {
217 0 : if (*lre < *rre) *out++ = *lre++;
218 0 : else if (*rre < *lre) { *out++ = *rre++; }
219 0 : else { *out++ = *lre++; ++rre; }
220 :
221 0 : if (rre == state.rules_end)
222 : {
223 0 : while (lre != end() && out != lrend) { *out++ = *lre++; }
224 0 : m_end = out;
225 0 : return;
226 : }
227 : }
228 0 : while (rre != state.rules_end && out != lrend) { *out++ = *rre++; }
229 0 : m_end = out;
230 : }
231 :
232 0 : inline SlotMap::SlotMap(Segment & seg)
233 0 : : segment(seg), m_size(0), m_precontext(0)
234 : {
235 0 : m_slot_map[0] = 0;
236 0 : }
237 :
238 0 : inline Slot * * SlotMap::begin()
239 : {
240 0 : return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting
241 : // at start of segment.
242 : }
243 :
244 0 : inline Slot * * SlotMap::end()
245 : {
246 0 : return m_slot_map + m_size + 1;
247 : }
248 :
249 0 : inline size_t SlotMap::size() const
250 : {
251 0 : return m_size;
252 : }
253 :
254 0 : inline short unsigned int SlotMap::context() const
255 : {
256 0 : return m_precontext;
257 : }
258 :
259 0 : inline void SlotMap::reset(Slot & slot, short unsigned int ctxt)
260 : {
261 0 : m_size = 0;
262 0 : m_precontext = ctxt;
263 0 : *m_slot_map = slot.prev();
264 0 : }
265 :
266 0 : inline void SlotMap::pushSlot(Slot*const slot)
267 : {
268 0 : m_slot_map[m_size++ + 1] = slot;
269 0 : }
270 :
271 0 : inline Slot * const & SlotMap::operator[](int n) const
272 : {
273 0 : return m_slot_map[n + 1];
274 : }
275 :
276 0 : inline Slot * & SlotMap::operator[](int n)
277 : {
278 0 : return m_slot_map[n + 1];
279 : }
280 :
281 : } // namespace graphite2
|