1 module ddparser.lr; 2 3 import ddparser.gram; 4 import ddparser.util; 5 6 import std.algorithm; 7 8 enum INITIAL_ALLITEMS = 3359; 9 10 private uint item_hash(Item* _i) 11 { 12 return ((cast(uint)_i.rule.index << 8) + 13 (cast(uint)(_i.kind != ElemKind.ELEM_END ? _i.index : _i.rule.elems.length))); 14 } 15 16 private int 17 insert_item(State *s, Elem *e) { 18 if (e !in s.items_hash) { 19 s.items_hash[e] = true; 20 s.items ~= e; 21 return 1; 22 } 23 return 0; 24 } 25 26 bool itemIsLessThanItem(Item* a, Item* b) 27 { 28 return item_hash(a) < item_hash(b); 29 } 30 31 private void 32 free_state(State *s) { 33 FREE(s); 34 } 35 36 private State * 37 maybe_add_state(Grammar *g, State *s) { 38 foreach (i; g.states) { 39 if (s.hash == i.hash && s.items.length == i.items.length) { 40 bool cont = false; 41 for (int j = 0; j < s.items.length; j++) 42 if (s.items[j] != i.items[j]) 43 { 44 cont = true; 45 break; 46 } 47 if (!cont) 48 { 49 free_state(s); 50 return i; 51 } 52 } 53 } 54 s.index = cast(uint)g.states.length; 55 g.states ~= s; 56 return s; 57 } 58 59 private Elem * 60 next_elem(Item *i) { 61 if (i.index + 1 >= i.rule.elems.length) 62 return i.rule.end; 63 else 64 return i.rule.elems[i.index + 1]; 65 } 66 67 private State * 68 build_closure(Grammar *g, State *s) { 69 for (int i = 0; i < s.items.length; i++) { // s.items may change during iteration 70 if (s.items[i].kind == ElemKind.ELEM_NTERM) { 71 foreach (r; s.items[i].e.nterm.rules) 72 insert_item(s, r.elems.length ? 73 r.elems[0] : r.end); 74 } 75 } 76 s.items.sort!itemIsLessThanItem(); 77 s.hash = 0; 78 foreach (i; s.items) 79 s.hash += item_hash(i); 80 return maybe_add_state(g, s); 81 } 82 83 private Elem * 84 clone_elem(Elem *e) { 85 Elem *ee = new Elem(); 86 *ee = *e; 87 return ee; 88 } 89 90 private void 91 add_goto(State *s, State *ss, Elem *e) { 92 Goto *g = new Goto(); 93 g.state = ss; 94 g.elem = clone_elem(e); 95 s.gotos ~= g; 96 } 97 98 private void 99 build_state_for(Grammar *g, State *s, Elem *e) { 100 State *ss = null; 101 102 foreach (i; s.items) { 103 if (i.kind != ElemKind.ELEM_END && elemTermOrNtermEqual(*i, *e)) 104 { 105 if (!ss) ss = new State(); 106 insert_item(ss, next_elem(i)); 107 } 108 } 109 if (ss) 110 add_goto(s, build_closure(g, ss), e); 111 } 112 113 private void 114 build_new_states(Grammar *g) { 115 Elem e; 116 for (int i = 0; i < g.states.length; i++) { // g.states may change during iteration 117 foreach (t; g.terminals) { 118 e.term = t; 119 build_state_for(g, g.states[i], &e); 120 } 121 foreach (p; g.productions) { 122 e.nterm = p; 123 build_state_for(g, g.states[i], &e); 124 } 125 } 126 } 127 128 private void 129 build_states_for_each_production(Grammar *g) { 130 foreach (p; g.productions) 131 if (!p.internal && p.elem) { 132 State *s = new State(); 133 insert_item(s, p.elem); 134 p.state = build_closure(g, s); 135 } 136 } 137 138 uint 139 elem_symbol(Grammar *g, Elem *e) { 140 if (e.kind == ElemKind.ELEM_NTERM) 141 return e.nterm.index; 142 else 143 return cast(uint)(g.productions.length + e.term.index); 144 } 145 146 bool gotoIsLessThanGoto(Goto* a, Goto* b) 147 { 148 return a.state.index < b.state.index; 149 } 150 151 private void 152 sort_Gotos(Grammar *g) { 153 foreach (s; g.states) { 154 s.gotos.sort!gotoIsLessThanGoto(); 155 } 156 } 157 158 private void 159 build_LR_sets(Grammar *g) { 160 State *s = new State(); 161 insert_item(s, g.productions[0].rules[0].elems[0]); 162 build_closure(g, s); 163 build_states_for_each_production(g); 164 build_new_states(g); 165 sort_Gotos(g); 166 } 167 168 private Action * 169 new_Action(Grammar *g, ActionKind akind, Term *aterm, Rule *arule, State *astate) { 170 Action *a = new Action(); 171 a.kind = akind; 172 a.term = aterm; 173 a.rule = arule; 174 a.state = astate; 175 a.index = g.action_count++; 176 g.actions ~= a; 177 return a; 178 } 179 180 void 181 free_Action(Action *a) { 182 FREE(a); 183 } 184 185 private void 186 add_action(Grammar *g, State *s, ActionKind akind, Term *aterm, 187 Rule *arule, State *astate) 188 { 189 Action *a; 190 191 if (akind == ActionKind.ACTION_REDUCE) { 192 /* eliminate duplicates */ 193 foreach (i; s.reduce_actions) 194 if (i.rule == arule) 195 return; 196 a = new_Action(g, akind, aterm, arule, astate); 197 s.reduce_actions ~= a; 198 } else { 199 /* eliminate duplicates */ 200 foreach (i; s.shift_actions) 201 if (i.term == aterm && 202 i.state == astate && 203 i.kind == akind) 204 return; 205 a = new_Action(g, akind, aterm, arule, astate); 206 s.shift_actions ~= a; 207 } 208 } 209 210 private void 211 init_LR(Grammar *g) { 212 g.action_count = 0; 213 } 214 215 extern(C) private int 216 actioncmp(const void *aa, const void *bb) { 217 Action *a = *cast(Action **)aa, b = *cast(Action **)bb; 218 int i, j; 219 if (a.kind == ActionKind.ACTION_SHIFT_TRAILING) 220 i = a.term.index + 11000000; 221 else if (a.kind == ActionKind.ACTION_SHIFT) 222 i = a.term.index + 1000000; 223 else 224 i = a.rule.index; 225 if (b.kind == ActionKind.ACTION_SHIFT_TRAILING) 226 j = b.term.index + 11000000; 227 else if (b.kind == ActionKind.ACTION_SHIFT) 228 j = b.term.index + 1000000; 229 else 230 j = b.rule.index; 231 return ((i > j) ? 1 : ((i < j) ? -1 : 0)); 232 } 233 234 bool actionIsLessThanAction(Action* a, Action* b) 235 { 236 int i, j; 237 if (a.kind == ActionKind.ACTION_SHIFT_TRAILING) 238 i = a.term.index + 11000000; 239 else if (a.kind == ActionKind.ACTION_SHIFT) 240 i = a.term.index + 1000000; 241 else 242 i = a.rule.index; 243 if (b.kind == ActionKind.ACTION_SHIFT_TRAILING) 244 j = b.term.index + 11000000; 245 else if (b.kind == ActionKind.ACTION_SHIFT) 246 j = b.term.index + 1000000; 247 else 248 j = b.rule.index; 249 return i < j; 250 } 251 252 void 253 sort_VecAction(ref VecAction v) { 254 v.array.sort!actionIsLessThanAction(); 255 } 256 257 private void 258 build_actions(Grammar *g) { 259 foreach(s; g.states) 260 { 261 foreach(e; s.items) 262 { 263 if (e.kind != ElemKind.ELEM_END) { 264 if (e.kind == ElemKind.ELEM_TERM) { 265 foreach (z; s.gotos) { 266 if (z.elem.kind == ElemKind.ELEM_TERM && z.elem.e.term == e.term) 267 add_action(g, s, ActionKind.ACTION_SHIFT, 268 e.term, null, z.state); 269 } 270 } 271 } else if (e.rule.prod.index) 272 add_action(g, s, ActionKind.ACTION_REDUCE, null, e.rule, null); 273 else 274 s.accept = 1; 275 } 276 sort_VecAction(s.shift_actions); 277 sort_VecAction(s.reduce_actions); 278 } 279 } 280 281 State * 282 goto_State(State *s, Elem *e) { 283 foreach (i; s.gotos) 284 if (elemTermOrNtermEqual(*i.elem, *e)) 285 return i.state; 286 return null; 287 } 288 289 private Hint * 290 new_Hint(size_t d, State *s, Rule *r) { 291 Hint *h = new Hint(); 292 h.depth = cast(uint)d; 293 h.state = s; 294 h.rule = r; 295 return h; 296 } 297 298 bool isHintLessThanHint(Hint* a, Hint* b) 299 { 300 return (a.depth < b.depth) || (a.depth == b.depth && a.rule.index < b.rule.index); 301 } 302 303 private void 304 build_right_epsilon_hints(Grammar *g) { 305 foreach (s; g.states) { 306 foreach (e; s.items) { 307 if (e.kind != ElemKind.ELEM_END) { 308 Rule *r = e.rule; 309 bool next = false; 310 for (int z = e.index; z < r.elems.length; z++) { 311 if ((r.elems[z].kind != ElemKind.ELEM_NTERM || 312 !r.elems[z].nterm.nullable)) 313 { 314 next = true; 315 break; 316 } 317 } 318 if (!next) 319 { 320 State *ss = s; 321 for (int z = e.index; z < r.elems.length; z++) 322 ss = goto_State(ss, r.elems[z]); 323 if (ss && r.elems.length) 324 vec_add(&s.right_epsilon_hints, 325 new_Hint(r.elems.length - e.index - 1, ss, r)); 326 else { /* ignore for states_for_each_productions */ } 327 } 328 } 329 } 330 if (s.right_epsilon_hints.length > 1) 331 s.right_epsilon_hints.array.sort!isHintLessThanHint(); 332 } 333 } 334 335 private void 336 build_error_recovery(Grammar *g) { 337 foreach (s; g.states) { 338 foreach (i; s.items) { 339 Rule *r = i.rule; 340 if (r.elems.length > 1 && 341 r.elems[r.elems.length - 1].kind == ElemKind.ELEM_TERM && 342 r.elems[r.elems.length - 1].term.kind == TermKind.TERM_STRING) 343 { 344 int depth = i.index; 345 Elem *e = r.elems[r.elems.length - 1]; 346 bool done = false; 347 foreach (erh; s.error_recovery_hints) { 348 Rule *rr = erh.rule; 349 Elem *ee = rr.elems[rr.elems.length - 1]; 350 if (e.term.string_ == ee.term.string_) 351 { 352 if (erh.depth > depth) 353 erh.depth = depth; 354 done = true; 355 break; 356 } 357 } 358 if (!done) 359 { 360 vec_add(&s.error_recovery_hints, new_Hint(depth, null, r)); 361 } 362 } 363 } 364 s.error_recovery_hints.array.sort!isHintLessThanHint(); 365 } 366 } 367 368 void 369 build_LR_tables(Grammar *g) { 370 init_LR(g); 371 build_LR_sets(g); 372 build_actions(g); 373 build_right_epsilon_hints(g); 374 build_error_recovery(g); 375 } 376