1 /* 2 Copyright 2002-2006 John Plevyak, All Rights Reserved 3 */ 4 module ddparser.write_tables; 5 6 import ddparser.util; 7 import ddparser.lex; 8 import ddparser.gram; 9 import ddparser.dparse_tables; 10 import ddparser.lr; 11 12 import std.bitmanip; 13 import std.system; 14 import std.array; 15 import std.algorithm; 16 17 18 private struct ScannerBlock { 19 int state_index; 20 uint scanner_index; 21 int block_index; 22 ScanState*[] chars; 23 ScanStateTransition*[] transitions; 24 } 25 26 private alias VecScannerBlock = Vec!(ScannerBlock*); 27 private alias VecState = Vec!(State*); 28 29 private int 30 scanner_size(State *s) { 31 if (s.scanner.states.length < 255 && s.scanner.transitions.length < 255) 32 return 1; 33 if (s.scanner.states.length < 32384 && s.scanner.transitions.length < 32384) 34 return 2; 35 return 4; 36 } 37 38 uint32 39 scanner_block_hash_fn(ScannerBlock *b, int block_size) { 40 uint32 hash = 0; 41 intptr_t i; 42 ScanState*[] sb = b.chars; 43 44 for (i = 0; i < block_size; i++) { 45 hash *= 17; 46 hash += sb[i] ? sb[i].index + 2 : 1; 47 } 48 return hash; 49 } 50 51 int 52 scanner_block_cmp_fn(ScannerBlock *a, ScannerBlock *b, int block_size) { 53 intptr_t i; 54 ScanState*[] sa = a.chars; 55 ScanState*[] sb = b.chars; 56 57 for (i = 0; i < block_size; i++) { 58 if (sa[i] == sb[i]) 59 continue; 60 if (!sa[i] || !sb[i]) 61 return 1; 62 if (sa[i].index != sb[i].index) 63 return 1; 64 } 65 return 0; 66 } 67 68 alias ScannerBlockSet = Set!(ScannerBlock*, scanner_block_hash_fn, scanner_block_cmp_fn); 69 70 uint32 71 trans_scanner_block_hash_fn(ScannerBlock *b, int block_size) { 72 uint32 hash = 0; 73 intptr_t i; 74 ScanStateTransition*[] sb = b.transitions; 75 76 for (i = 0; i < block_size; i++) { 77 hash *= 3; 78 hash += sb[i] ? sb[i].index + 1 : 0; 79 } 80 return hash; 81 } 82 83 int 84 trans_scanner_block_cmp_fn(ScannerBlock *a, ScannerBlock *b, int block_size) { 85 intptr_t i; 86 ScanStateTransition*[] sa = a.transitions; 87 ScanStateTransition*[] sb = b.transitions; 88 89 for (i = 0; i < block_size; i++) { 90 if (sa[i] == sb[i]) 91 continue; 92 if (!sa[i] || !sb[i]) 93 return 1; 94 if (sa[i].index != sb[i].index) 95 return 1; 96 } 97 return 0; 98 } 99 100 101 alias TransScannerBlockSet = Set!(ScannerBlock*, trans_scanner_block_hash_fn, trans_scanner_block_cmp_fn); 102 103 104 uint32 105 shift_hash_fn(Action *sa) { 106 return sa.term.index + (sa.kind == ActionKind.ACTION_SHIFT_TRAILING ? 1000000 : 0); 107 } 108 109 110 int 111 shift_cmp_fn(Action *sa, Action *sb) { 112 return (sa.term.index != sb.term.index) || (sa.kind != sb.kind); 113 } 114 115 alias ShiftSet = Set!(Action *, shift_hash_fn, shift_cmp_fn); 116 117 118 private void 119 buildScannerData(Grammar *g, ref BuildTables tables) { 120 ScannerBlock *xv, yv; 121 ScannerBlockSet[4] scanner_block_hash; 122 ScannerBlockSet* pscanner_block_hash; 123 TransScannerBlockSet[4] trans_scanner_block_hash; 124 TransScannerBlockSet* ptrans_scanner_block_hash; 125 ShiftSet shift_hash; 126 int k, x, xx; 127 128 D_Shift*[] allShifts = new D_Shift*[g.terminals.length]; 129 D_Shift*[uint] allTShifts; 130 131 /* shift_actions */ 132 for (int i = 0; i < g.terminals.length; i++) { 133 int action_index = -1; 134 Term *t = g.terminals[i]; 135 if (t.regex_production) { 136 action_index = t.regex_production.rules[0].action_index; 137 } 138 D_Shift* shift = new D_Shift(); 139 shift.symbol = cast(ushort)(t.index + g.productions.length); 140 shift.shift_kind = cast(ubyte)t.scan_kind; 141 shift.op_assoc = cast(ubyte)t.op_assoc; 142 shift.op_priority = t.op_priority; 143 shift.term_priority = t.term_priority; 144 shift.action_index = action_index; 145 shift.speculative_code = tables.spec_code; 146 allShifts[i] = shift; 147 if (t.trailing_context) { 148 shift = new D_Shift(); 149 shift.symbol = cast(ushort)(t.index + g.productions.length); 150 shift.shift_kind = D_SCAN_TRAILING; 151 shift.op_assoc = cast(ubyte)t.op_assoc; 152 shift.op_priority = t.op_priority; 153 shift.term_priority = t.term_priority; 154 shift.action_index = action_index; 155 shift.speculative_code = tables.spec_code; 156 allTShifts[i] = shift; 157 } 158 } 159 /* scanners */ 160 size_t nvsblocks = 0; 161 foreach (i; g.states) 162 nvsblocks += i.scanner.states.length * g.scanner_blocks; 163 ScannerBlock[] vsblock = new ScannerBlock[nvsblocks ? nvsblocks : 1]; 164 165 /* shift */ 166 int ivsblock = 0; 167 168 TableMap!(D_Shift*[], 2) tables_d_accepts_diff2; 169 TableMap!(D_Shift *[], 2) tables_d_shift2; 170 TableMap!(ubyte[], 3) tables_d_accepts_diff3; 171 TableMap!(ubyte[], 3) tables_d_scanner3; 172 173 for (int i = 0; i < g.states.length; i++) { 174 State *s = g.states[i]; 175 if (s.same_shifts) 176 continue; 177 auto ss = s.scanner.states; 178 179 /* build accepts differences */ 180 for (int j = 0; j < s.scanner.transitions.n; j++) { 181 D_Shift*[] d_accepts_diff2; 182 foreach (k; s.scanner.transitions[j].accepts_diff) { 183 if (k.kind != ActionKind.ACTION_SHIFT_TRAILING) 184 d_accepts_diff2 ~= allShifts[k.term.index]; 185 else 186 d_accepts_diff2 ~= allTShifts[k.term.index]; 187 } 188 //d_accepts_diff2 ~= null; 189 tables_d_accepts_diff2[i, j] = d_accepts_diff2; 190 } 191 if (s.scanner.transitions.n) { 192 D_Shift*[][] d_accepts_diff1; 193 for (int j = 0; j < s.scanner.transitions.n; j++) { 194 d_accepts_diff1 ~= tables_d_accepts_diff2[i,j]; 195 } 196 tables.d_accepts_diff1[i] = d_accepts_diff1; 197 } 198 /* build scanner_block_hash */ 199 pscanner_block_hash = &scanner_block_hash[scanner_size(s)-1]; 200 ptrans_scanner_block_hash = &trans_scanner_block_hash[scanner_size(s)-1]; 201 for (int j = 0; j < ss.length; j++) { 202 if (!s.same_shifts) { 203 for (k = 0; k < g.scanner_blocks; k++) { 204 vsblock[ivsblock].state_index = s.index; 205 vsblock[ivsblock].scanner_index = j; 206 vsblock[ivsblock].block_index = k; 207 vsblock[ivsblock].chars = 208 ss[j].chars[k * g.scanner_block_size .. $]; 209 vsblock[ivsblock].transitions = 210 ss[j].transition[k * g.scanner_block_size .. $]; 211 xv = &vsblock[ivsblock]; 212 ivsblock++; 213 assert(ivsblock <= nvsblocks); 214 /* output state scanner blocks */ 215 yv = pscanner_block_hash.add(xv, g.scanner_block_size); 216 if (xv == yv) { 217 int size = scanner_size(s); 218 auto d_scanner3 = appender!(ubyte[])(); 219 for (x = 0; x < g.scanner_block_size; x++) { 220 xx = x + k * g.scanner_block_size; 221 uint val = ss[j].chars[xx] ? ss[j].chars[xx].index + 1 : 0; 222 if (size == 1) 223 d_scanner3.append!(ubyte, endian)(cast(ubyte)val); 224 else if (size == 2) 225 d_scanner3.append!(ushort, endian)(cast(ushort)val); 226 else 227 d_scanner3.append!(uint, endian)(val); 228 } 229 tables_d_scanner3[i,j,k] = d_scanner3.data; 230 } 231 if (s.scan_kind != D_SCAN_LONGEST || s.trailing_context) { 232 /* output accept_diff scanner blocks */ 233 yv = ptrans_scanner_block_hash.add(xv, g.scanner_block_size); 234 if (xv == yv) { 235 int size = scanner_size(s); 236 auto d_accepts_diff3 = appender!(ubyte[])(); 237 for (x = 0; x < g.scanner_block_size; x++) { 238 xx = x + k * g.scanner_block_size; 239 uint val = ss[j].transition[xx].index; 240 if (size == 1) 241 d_accepts_diff3.append!(ubyte, endian)(cast(ubyte)val); 242 else if (size == 2) 243 d_accepts_diff3.append!(ushort, endian)(cast(ushort)val); 244 else 245 d_accepts_diff3.append!(uint, endian)(val); 246 } 247 tables_d_accepts_diff3[i,j,k] = d_accepts_diff3.data; 248 } 249 } 250 } 251 /* output shifts */ 252 if (ss[j].accepts.n) { 253 size_t[2] tmp = [i, j]; 254 for (k = 0; k < ss[j].accepts.n; k++) { 255 Action *a = ss[j].accepts.v[k]; 256 if (ss[j].accepts.n == 1) { 257 if (a.temp_key[0] != size_t.max) 258 { 259 continue; 260 } 261 a.temp_key = tmp; 262 Action *aa = shift_hash.add(a); 263 if (aa != a) 264 continue; 265 } 266 /* output shifts */ 267 if (!k) 268 { 269 tables_d_shift2[i,j] = []; 270 } 271 if (a.kind != ActionKind.ACTION_SHIFT_TRAILING) { 272 tables_d_shift2[i,j] ~= allShifts[a.term.index]; 273 } else { 274 tables_d_shift2[i,j] ~= allTShifts[a.term.index]; 275 } 276 } 277 } 278 } 279 } 280 } 281 for (int i = 0; i < g.states.length; i++) { 282 State *s = g.states[i]; 283 auto ss = s.scanner.states; 284 ivsblock = 0; 285 if (ss.length && !s.same_shifts) { 286 /* output scanner state transition tables */ 287 /* assume SB_uint8, 16, and 32 have same member offsets */ 288 static assert((SB_uint8).sizeof == (SB_uint16).sizeof && (SB_uint16).sizeof == (SB_uint32).sizeof); 289 SB_uint32[] d_scanner = new SB_uint32[ss.length]; 290 pscanner_block_hash = &scanner_block_hash[scanner_size(s)-1]; 291 foreach (j, ref sb; d_scanner) { 292 if (ss[j].accepts.n) { 293 if (ss[j].accepts.n == 1) { 294 Action* a = ss[j].accepts.v[0]; 295 a = shift_hash.add(a); 296 sb.shift = tables_d_shift2.storage[a.temp_key]; 297 } else 298 sb.shift = tables_d_shift2[i, j]; 299 } 300 for (k = 0; k < g.scanner_blocks; k++) { 301 ScannerBlock vs; 302 vs.state_index = s.index; 303 vs.scanner_index = cast(uint)j; 304 vs.block_index = k; 305 vs.chars = ss[j].chars[k * g.scanner_block_size .. $]; 306 vs.transitions = 307 ss[j].transition[k * g.scanner_block_size .. $]; 308 xv = &vs; 309 yv = pscanner_block_hash.add(xv, g.scanner_block_size); 310 assert(yv != xv); 311 sb.scanner_block[k] = cast(uint*)tables_d_scanner3[yv.state_index, yv.scanner_index, yv.block_index].ptr; 312 } 313 } 314 315 tables.d_scanner1[i] = d_scanner; 316 if (s.scan_kind != D_SCAN_LONGEST || s.trailing_context) { 317 SB_trans_uint32[] d_transition = new SB_trans_uint32[ss.length]; 318 /* output scanner accepts diffs tables */ 319 ptrans_scanner_block_hash = 320 &trans_scanner_block_hash[scanner_size(s)-1]; 321 foreach (j, ref trans; d_transition) { 322 for (k = 0; k < g.scanner_blocks; k++) { 323 ScannerBlock vs; 324 vs.state_index = s.index; 325 vs.scanner_index = cast(uint)j; 326 vs.block_index = k; 327 vs.chars = ss[j].chars[k * g.scanner_block_size .. $]; 328 vs.transitions = 329 ss[j].transition[k * g.scanner_block_size .. $]; 330 xv = &vs; 331 yv = ptrans_scanner_block_hash.add(xv, g.scanner_block_size); 332 assert(yv != xv); 333 trans.scanner_block[k] = cast(uint*)tables_d_accepts_diff3[ yv.state_index, yv.scanner_index, 334 yv.block_index].ptr; 335 } 336 } 337 tables.d_transition1[i] = d_transition; 338 } 339 } 340 } 341 } 342 343 private Rule* original_reduction(Rule* r) 344 { 345 return r.same_reduction ? r.same_reduction : r; 346 } 347 348 private void 349 buildGotoData(Grammar *g, ref BuildTables tables) { 350 size_t nvalid_bytes = ((g.productions.length + g.terminals.length) + 7) / 8; 351 ushort[] vgoto; 352 for (int i = 0; i < g.states.length; i++) { 353 State *s = g.states[i]; 354 if (s.gotos.length) { 355 /* check for goto on token */ 356 foreach (j; s.gotos) 357 if (j.elem.kind == ElemKind.ELEM_TERM && 358 j.elem.term.kind == TermKind.TERM_TOKEN) 359 { 360 s.goto_on_token = 1; 361 break; 362 } 363 364 ubyte[] d_goto_valid = new ubyte[nvalid_bytes]; 365 /* find lowest goto, set valid bits */ 366 int lowest_sym = elem_symbol(g, s.gotos[0].elem); 367 SET_BIT(d_goto_valid, lowest_sym); 368 for (int j = 1; j < s.gotos.length; j++) { 369 int sym = elem_symbol(g, s.gotos[j].elem); 370 SET_BIT(d_goto_valid, sym); 371 if (sym < lowest_sym) 372 lowest_sym = sym; 373 } 374 /* insert into vgoto */ 375 bool again = true; 376 while (again) { 377 again = false; 378 for (int j = 0; j < s.gotos.length; j++) { 379 int x = elem_symbol(g, s.gotos[j].elem); 380 x -= lowest_sym; 381 if (vgoto.length <= x) 382 vgoto.length = x + 1; 383 384 if (vgoto[x]) { 385 again = true; 386 /* undo the damage */ 387 for (--j;j >= 0;j--) { 388 x = elem_symbol(g, s.gotos[j].elem); 389 x -= lowest_sym; 390 vgoto[x] = 0; 391 } 392 lowest_sym--; 393 break; 394 } 395 else 396 { 397 if (s.gotos[j].state.index + 1 > ushort.max) 398 d_fail("goto table overflow"); 399 vgoto[x] = cast(ushort)(s.gotos[j].state.index + 1); 400 } 401 } 402 } 403 s.goto_table_offset = lowest_sym; 404 /* valid bits */ 405 tables.d_goto_valid[i] = d_goto_valid; 406 } else 407 s.goto_table_offset = -int.max; 408 /* reduce_actions */ 409 if (s.reduce_actions.n) { 410 tables.d_reductions1[i] = s.reduce_actions.array 411 .map!(x => tables.reductions[original_reduction(x.rule).index]) 412 .array(); 413 } 414 /* modified_reduce_actions */ 415 if (s.right_epsilon_hints.n) { 416 D_RightEpsilonHint[] hints = new D_RightEpsilonHint[s.right_epsilon_hints.length]; 417 for (uint j = 0; j < s.right_epsilon_hints.length; ++j) 418 { 419 auto x = s.right_epsilon_hints[j]; 420 hints[j] = D_RightEpsilonHint(cast(ushort)x.depth, 421 cast(ushort)x.state.index, 422 tables.reductions[original_reduction(x.rule).index]); 423 } 424 tables.d_right_epsilon_hints1[i] = hints; 425 } 426 } 427 428 /* gotos */ 429 tables.d_gotos = vgoto; 430 } 431 432 private void 433 buildReductions(Grammar *g, ref BuildTables tables) { 434 foreach (p; g.productions) { 435 for (long j = p.rules.length - 1; j >= 0; j--) { 436 Rule *r = p.rules[j]; 437 for (int k = 0; k < j; k++) 438 if (r.elems.length == p.rules[k].elems.length && 439 r.speculative_code.code == p.rules[k].speculative_code.code && 440 r.final_code == p.rules[k].final_code && 441 r.op_priority == p.rules[k].op_priority && 442 r.op_assoc == p.rules[k].op_assoc && 443 r.rule_priority == p.rules[k].rule_priority && 444 r.rule_assoc == p.rules[k].rule_assoc && 445 r.action_index == p.rules[k].action_index) 446 { 447 if (r.pass_code.n != p.rules[k].pass_code.n) 448 continue; 449 450 bool cont = false; 451 for (int l = 0; l < r.pass_code.n; l++) { 452 if (!r.pass_code[l] && !p.rules[k].pass_code[l]) 453 continue; 454 if ((!r.pass_code[l] || !p.rules[k].pass_code[l]) || 455 (r.pass_code[l].code != p.rules[k].pass_code[l].code)) 456 { 457 cont = true; 458 break; 459 } 460 } 461 462 if (!cont) 463 { 464 r.same_reduction = p.rules[k]; 465 break; 466 } 467 } 468 } 469 foreach (r; p.rules) { 470 if (r.same_reduction) 471 continue; 472 D_Reduction* red = new D_Reduction(); 473 tables.reductions[r.index] = red; 474 red.nelements = cast(ushort)r.elems.length; 475 red.symbol = cast(ushort)r.prod.index; 476 if (!r.prod.internal && r.final_code.line == -1) 477 { 478 red.final_code = r.final_code.f; 479 } 480 else if (!r.prod.internal && r.action_index >= 0) { 481 red.speculative_code = tables.spec_code; 482 red.final_code = tables.final_code; 483 } else { 484 red.speculative_code = null; 485 red.final_code = null; 486 } 487 488 red.op_assoc = cast(ushort)r.op_assoc; 489 red.rule_assoc = cast(ushort)r.rule_assoc; 490 red.op_priority = r.op_priority; 491 red.rule_priority = r.rule_priority; 492 red.action_index = r.prod.internal ? -1 : r.action_index; 493 red.pass_code = null; 494 } 495 } 496 } 497 498 uint32 499 er_hint_hash_fn(State *a) { 500 VecHint *sa = &a.error_recovery_hints; 501 uint32 hash = 0, i; 502 Term *ta; 503 504 for (i = 0; i < sa.n; i++) { 505 ta = sa.v[i].rule.elems[$ - 1].term; 506 hash += (sa.v[i].depth + 1) * 13; 507 hash += strhashl(ta.string_); 508 if (sa.v[i].rule) 509 hash += sa.v[i].rule.prod.index * 10007; 510 } 511 return hash; 512 } 513 514 int 515 er_hint_cmp_fn(State *a, State *b) { 516 int i; 517 VecHint *sa = &a.error_recovery_hints, sb = &b.error_recovery_hints; 518 if (sa.n != sb.n) 519 return 1; 520 for (i = 0; i < sa.n; i++) { 521 Term *ta = sa.v[i].rule.elems[$ - 1].term; 522 Term *tb = sb.v[i].rule.elems[$ - 1].term; 523 if (sa.v[i].depth != sb.v[i].depth || 524 ta.string_ != tb.string_ || 525 sa.v[i].rule.prod.index != sb.v[i].rule.prod.index) 526 return 1; 527 } 528 return 0; 529 } 530 531 alias ErrorHintSet = Set!(State*, er_hint_hash_fn, er_hint_cmp_fn); 532 533 private void 534 buildErrorData(Grammar *g, ref BuildTables tables, ref ErrorHintSet er_hash) { 535 for (int i = 0; i < g.states.length; i++) { 536 State *s = g.states[i]; 537 if (s.error_recovery_hints.n) { 538 State* h = er_hash.add(s); 539 if (h == s) { 540 D_ErrorRecoveryHint[] d_error_recovery_hints; 541 foreach (erh; s.error_recovery_hints) { 542 Term *t = erh.rule.elems[$ - 1].term; 543 D_ErrorRecoveryHint hint; 544 hint.depth = cast(ushort)erh.depth; 545 hint.symbol = cast(ushort)erh.rule.prod.index; 546 hint.str = escape_string(t.string_); 547 d_error_recovery_hints ~= hint; 548 } 549 tables.d_error_recovery_hints1[i] = d_error_recovery_hints; 550 } 551 } 552 } 553 } 554 555 private void 556 buildStateData(Grammar *g, ref BuildTables tables, ref ErrorHintSet er_hash) { 557 if (g.states.length) { 558 tables.d_states = new D_State[g.states.length]; 559 foreach (i, ref state; tables.d_states) { 560 State *s = g.states[i]; 561 State *shifts = s.same_shifts ? s.same_shifts : s; 562 563 if (s.gotos.length) 564 state.goto_valid = tables.d_goto_valid[i]; 565 566 state.goto_table_offset = s.goto_table_offset; 567 568 if (s.reduce_actions.n) { 569 state.reductions = tables.d_reductions1[i]; 570 assert(s.reduce_actions.n == state.reductions.length); 571 } 572 573 if (s.right_epsilon_hints.n) { 574 state.right_epsilon_hints = tables.d_right_epsilon_hints1[i]; 575 assert(state.right_epsilon_hints.length == s.right_epsilon_hints.n); 576 } 577 578 if (s.error_recovery_hints.n) { 579 State* h = er_hash.add(s); 580 state.error_recovery_hints = tables.d_error_recovery_hints1[h.index]; 581 assert(state.error_recovery_hints.length == s.error_recovery_hints.n); 582 } 583 584 state.shifts = s.shift_actions.n || s.scanner_code || (g.scanner.code && s.goto_on_token); 585 586 if (s.scanner.states.length) { 587 state.scanner_table = tables.d_scanner1[shifts.index]; 588 } 589 590 state.scanner_size = cast(ubyte)scanner_size(s); 591 state.accept = s.accept; 592 state.scan_kind = cast(ubyte)s.scan_kind; 593 594 if ((shifts.scan_kind != D_SCAN_LONGEST || shifts.trailing_context) 595 && shifts.scanner.states.length) { 596 state.transition_table = tables.d_transition1[shifts.index]; 597 } 598 599 if ((shifts.scan_kind != D_SCAN_LONGEST || shifts.trailing_context) 600 && shifts.scanner.states.length) 601 state.accepts_diff = tables.d_accepts_diff1[shifts.index]; 602 603 if (s.reduces_to) 604 state.reduces_to = s.reduces_to.index; 605 else 606 state.reduces_to = -1; 607 } 608 } else { 609 d_fail("no states"); 610 } 611 } 612 613 bool is_EBNF(uint _x) 614 { 615 return _x == InternalKind.INTERNAL_CONDITIONAL || _x == InternalKind.INTERNAL_STAR || _x == InternalKind.INTERNAL_PLUS; 616 } 617 618 private immutable D_SymbolKind[] d_symbol_values = [ 619 D_SymbolKind.D_SYMBOL_STRING, D_SymbolKind.D_SYMBOL_REGEX, D_SymbolKind.D_SYMBOL_CODE, D_SymbolKind.D_SYMBOL_TOKEN ]; 620 621 private void 622 buildSymbolData(Grammar *g, ref BuildTables tables) { 623 int i = 0; 624 D_Symbol[] d_symbols = new D_Symbol[g.productions.length + g.terminals.length]; 625 foreach (p; g.productions) { 626 int state = -1; 627 if (!p.internal && p.elem) 628 state = p.state.index; 629 d_symbols[i].kind = p.internal ? (is_EBNF(p.internal) ? D_SymbolKind.D_SYMBOL_INTERNAL : D_SymbolKind.D_SYMBOL_EBNF) : D_SymbolKind.D_SYMBOL_NTERM; 630 d_symbols[i].name = p.name; 631 d_symbols[i].start_symbol = state; 632 ++i; 633 } 634 foreach (t; g.terminals) { 635 string name = t.term_name; 636 if (!name.length) name = escape_string(t.string_); 637 d_symbols[i].kind = d_symbol_values[t.kind]; 638 d_symbols[i].name = name; 639 ++i; 640 } 641 tables.d_symbols = d_symbols; 642 } 643 644 private void 645 buildPassesData(Grammar *g, ref BuildTables tables) { 646 int i; 647 if (g.passes.n) { 648 D_Pass[] d_passes; 649 for (i = 0; i < g.passes.n; i++) { 650 D_Pass *p = g.passes.v[i]; 651 d_passes ~= *p; 652 } 653 tables.d_passes = d_passes; 654 } 655 } 656 657 D_ParserTables* createTablesFromGrammar(Grammar* g, D_ReductionCode spec_code, D_ReductionCode final_code) 658 { 659 ErrorHintSet er_hash; 660 661 g.scanner_block_size = 256/g.scanner_blocks; 662 663 D_ParserTables* result = new D_ParserTables(); 664 BuildTables tables; 665 666 tables.final_code = final_code; 667 tables.spec_code = spec_code; 668 669 buildReductions(g, tables); 670 buildScannerData(g, tables); 671 buildGotoData(g, tables); 672 buildErrorData(g, tables, er_hash); 673 buildStateData(g, tables, er_hash); 674 buildSymbolData(g, tables); 675 buildPassesData(g, tables); 676 677 result.states = tables.d_states; 678 assert(result.states.length == g.states.length); 679 680 result.goto_table = tables.d_gotos; 681 auto ws = lookup_production(g, "whitespace"); 682 if (ws) result.whitespace_state = ws.state.index; 683 result.symbols = tables.d_symbols; 684 assert(result.symbols.length == g.productions.length + g.terminals.length); 685 result.passes = tables.d_passes; 686 assert(result.passes.length == g.passes.length); 687 result.save_parse_tree = g.save_parse_tree; 688 return result; 689 } 690 691 struct TableMap(T, int dimension = 1) 692 { 693 T[size_t[dimension]] storage; 694 695 ref T opIndex(size_t[dimension] key ...) 696 { 697 assert(key in storage); 698 return storage[key]; 699 } 700 701 void opIndexAssign(T val, size_t[dimension] key ...) 702 { 703 assert(key !in storage); 704 storage[key] = val; 705 } 706 } 707 708 struct BuildTables 709 { 710 D_Shift*[][][uint] d_accepts_diff1; 711 D_Symbol[] d_symbols; 712 713 D_Reduction*[uint] reductions; 714 SB_uint32[][uint] d_scanner1; 715 SB_trans_uint32[][uint] d_transition1; 716 ubyte[][size_t] d_goto_valid; 717 D_Reduction*[][size_t] d_reductions1; 718 D_RightEpsilonHint[][size_t] d_right_epsilon_hints1; 719 D_ErrorRecoveryHint[][size_t] d_error_recovery_hints1; 720 ushort[] d_gotos; 721 722 D_State[] d_states; 723 D_Pass[] d_passes; 724 725 D_ReductionCode spec_code; 726 D_ReductionCode final_code; 727 } 728