Rule.h (6554B)
1 /* GRAPHITE2 LICENSING 2 3 Copyright 2011, 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 Rule(); 45 ~Rule() {} 46 47 CLASS_NEW_DELETE; 48 49 private: 50 Rule(const Rule &); 51 Rule & operator = (const Rule &); 52 }; 53 54 inline 55 Rule::Rule() 56 : constraint(0), 57 action(0), 58 sort(0), 59 preContext(0) 60 { 61 #ifndef NDEBUG 62 rule_idx = 0; 63 #endif 64 } 65 66 67 struct RuleEntry 68 { 69 const Rule * rule; 70 71 inline 72 bool operator < (const RuleEntry &r) const 73 { 74 const unsigned short lsort = rule->sort, rsort = r.rule->sort; 75 return lsort > rsort || (lsort == rsort && rule < r.rule); 76 } 77 78 inline 79 bool operator == (const RuleEntry &r) const 80 { 81 return rule == r.rule; 82 } 83 }; 84 85 86 struct State 87 { 88 const RuleEntry * rules, 89 * rules_end; 90 91 bool empty() const; 92 }; 93 94 inline 95 bool State::empty() const 96 { 97 return rules_end == rules; 98 } 99 100 101 class SlotMap 102 { 103 public: 104 enum {MAX_SLOTS=64}; 105 SlotMap(Segment & seg, uint8 direction, size_t maxSize); 106 107 Slot * * begin(); 108 Slot * * end(); 109 size_t size() const; 110 unsigned short context() const; 111 void reset(Slot &, unsigned short); 112 113 Slot * const & operator[](int n) const; 114 Slot * & operator [] (int); 115 void pushSlot(Slot * const slot); 116 void collectGarbage(Slot *& aSlot); 117 118 Slot * highwater() { return m_highwater; } 119 void highwater(Slot *s) { m_highwater = s; m_highpassed = false; } 120 bool highpassed() const { return m_highpassed; } 121 void highpassed(bool v) { m_highpassed = v; } 122 123 uint8 dir() const { return m_dir; } 124 int decMax() { return --m_maxSize; } 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 int m_maxSize; 133 uint8 m_dir; 134 bool m_highpassed; 135 }; 136 137 138 class FiniteStateMachine 139 { 140 public: 141 enum {MAX_RULES=128}; 142 143 private: 144 class Rules 145 { 146 public: 147 Rules(); 148 void clear(); 149 const RuleEntry * begin() const; 150 const RuleEntry * end() const; 151 size_t size() const; 152 153 void accumulate_rules(const State &state); 154 155 private: 156 RuleEntry * m_begin, 157 * m_end, 158 m_rules[MAX_RULES*2]; 159 }; 160 161 public: 162 FiniteStateMachine(SlotMap & map, json * logger); 163 void reset(Slot * & slot, const short unsigned int max_pre_ctxt); 164 165 Rules rules; 166 SlotMap & slots; 167 json * const dbgout; 168 }; 169 170 171 inline 172 FiniteStateMachine::FiniteStateMachine(SlotMap& map, json * logger) 173 : slots(map), 174 dbgout(logger) 175 { 176 } 177 178 inline 179 void FiniteStateMachine::reset(Slot * & slot, const short unsigned int max_pre_ctxt) 180 { 181 rules.clear(); 182 int ctxt = 0; 183 for (; ctxt != max_pre_ctxt && slot->prev(); ++ctxt, slot = slot->prev()); 184 slots.reset(*slot, ctxt); 185 } 186 187 inline 188 FiniteStateMachine::Rules::Rules() 189 : m_begin(m_rules), m_end(m_rules) 190 { 191 } 192 193 inline 194 void FiniteStateMachine::Rules::clear() 195 { 196 m_end = m_begin; 197 } 198 199 inline 200 const RuleEntry * FiniteStateMachine::Rules::begin() const 201 { 202 return m_begin; 203 } 204 205 inline 206 const RuleEntry * FiniteStateMachine::Rules::end() const 207 { 208 return m_end; 209 } 210 211 inline 212 size_t FiniteStateMachine::Rules::size() const 213 { 214 return m_end - m_begin; 215 } 216 217 inline 218 void FiniteStateMachine::Rules::accumulate_rules(const State &state) 219 { 220 // Only bother if there are rules in the State object. 221 if (state.empty()) return; 222 223 // Merge the new sorted rules list into the current sorted result set. 224 const RuleEntry * lre = begin(), * rre = state.rules; 225 RuleEntry * out = m_rules + (m_begin == m_rules)*MAX_RULES; 226 const RuleEntry * const lrend = out + MAX_RULES, 227 * const rrend = state.rules_end; 228 m_begin = out; 229 while (lre != end() && out != lrend) 230 { 231 if (*lre < *rre) *out++ = *lre++; 232 else if (*rre < *lre) { *out++ = *rre++; } 233 else { *out++ = *lre++; ++rre; } 234 235 if (rre == rrend) 236 { 237 while (lre != end() && out != lrend) { *out++ = *lre++; } 238 m_end = out; 239 return; 240 } 241 } 242 while (rre != rrend && out != lrend) { *out++ = *rre++; } 243 m_end = out; 244 } 245 246 inline 247 SlotMap::SlotMap(Segment & seg, uint8 direction, size_t maxSize) 248 : segment(seg), m_size(0), m_precontext(0), m_highwater(0), 249 m_maxSize(int(maxSize)), m_dir(direction), m_highpassed(false) 250 { 251 m_slot_map[0] = 0; 252 } 253 254 inline 255 Slot * * SlotMap::begin() 256 { 257 return &m_slot_map[1]; // allow map to go 1 before slot_map when inserting 258 // at start of segment. 259 } 260 261 inline 262 Slot * * SlotMap::end() 263 { 264 return m_slot_map + m_size + 1; 265 } 266 267 inline 268 size_t SlotMap::size() const 269 { 270 return m_size; 271 } 272 273 inline 274 short unsigned int SlotMap::context() const 275 { 276 return m_precontext; 277 } 278 279 inline 280 void SlotMap::reset(Slot & slot, short unsigned int ctxt) 281 { 282 m_size = 0; 283 m_precontext = ctxt; 284 *m_slot_map = slot.prev(); 285 } 286 287 inline 288 void SlotMap::pushSlot(Slot*const slot) 289 { 290 m_slot_map[++m_size] = slot; 291 } 292 293 inline 294 Slot * const & SlotMap::operator[](int n) const 295 { 296 return m_slot_map[n + 1]; 297 } 298 299 inline 300 Slot * & SlotMap::operator[](int n) 301 { 302 return m_slot_map[n + 1]; 303 } 304 305 } // namespace graphite2