os

An operating system
git clone https://erai.gay/code/os/
Log | Files | Refs | README | LICENSE

commit 45bbbb593e7c2aa83a8bf9b40728cf441afb1ca6
parent faa784e971aba23ab59bf3aba9e860fc4a7fbd54
Author: erai <erai@omiltem.net>
Date:   Sun, 13 Apr 2025 07:10:50 -0400

generate slr sets

Diffstat:
Mcc0.c | 521+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--
Mlalr.om | 381+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++----
2 files changed, 878 insertions(+), 24 deletions(-)

diff --git a/cc0.c b/cc0.c @@ -149,12 +149,20 @@ u zlabels_to_ir(); u zlalr_alt(); u zlalr_alt_nonterminal(); u zlalr_alt_terminal(); +u zlalr_assoc(); u zlalr_compiler(); +u zlalr_goto(); +u zlalr_itemcmp(); u zlalr_items(); +u zlalr_itemsetcmp(); +u zlalr_linkout(); u zlalr_lookup(); +u zlalr_memoset(); u zlalr_mkalt(); +u zlalr_mkitemset(); u zlalr_mkprod(); u zlalr_pattern(); +u zlalr_pointcmp(); u zlalr_primary(); u zlalr_rules(); u zlalr_suffix(); @@ -26232,14 +26240,14 @@ u zlalr_alt_nonterminal(u vlc, u va, u vs) { v6 = va + 0UL; v7 = va + 16UL; v8 = *(u*)(va + 8UL) + 1UL; - v9 = 24UL; + v9 = 64UL; v10 = ((u(*)())v4)(v5, v6, v7, v8, v9); v10; vi = *(u*)(va + 8UL); *(u*)(va + 8UL) = *(u*)(va + 8UL) + 1UL; - *(u*)(*(u*)(va + 0UL) + vi * 24UL + 0UL) = 1UL; - *(u*)(*(u*)(va + 0UL) + vi * 24UL + 8UL) = *(u*)(vs + 32UL); - *(u*)(*(u*)(va + 0UL) + vi * 24UL + 16UL) = *(u*)(vs + 40UL); + *(u*)(*(u*)(va + 0UL) + vi * 64UL + 32UL) = 0UL; + *(u*)(*(u*)(va + 0UL) + vi * 64UL + 40UL) = *(u*)(vs + 32UL); + *(u*)(*(u*)(va + 0UL) + vi * 64UL + 48UL) = *(u*)(vs + 40UL); return 0UL; } u zlalr_alt_terminal(u vlc, u va, u vname, u vid) { @@ -26256,18 +26264,77 @@ u zlalr_alt_terminal(u vlc, u va, u vname, u vid) { v7 = va + 0UL; v8 = va + 16UL; v9 = *(u*)(va + 8UL) + 1UL; - v10 = 24UL; + v10 = 64UL; v11 = ((u(*)())v5)(v6, v7, v8, v9, v10); v11; vi = *(u*)(va + 8UL); *(u*)(va + 8UL) = *(u*)(va + 8UL) + 1UL; - *(u*)(*(u*)(va + 0UL) + vi * 24UL + 0UL) = 1UL; - *(u*)(*(u*)(va + 0UL) + vi * 24UL + 8UL) = vid; - *(u*)(*(u*)(va + 0UL) + vi * 24UL + 16UL) = vname; + *(u*)(*(u*)(va + 0UL) + vi * 64UL + 32UL) = 1UL; + *(u*)(*(u*)(va + 0UL) + vi * 64UL + 40UL) = vid; + *(u*)(*(u*)(va + 0UL) + vi * 64UL + 48UL) = vname; return 0UL; } +u zlalr_assoc(u vlc, u vi, u vt) { + u vp = 0; + u vlink = 0; + u vd = 0; + u vdir = 0; + u v7 = 0; + u v8 = 0; + u v9 = 0; + u v10 = 0; + u v11 = 0; + u v12 = 0; + u v13 = 0; + u v14 = 0; + u v15 = 0; + u v16 = 0; + u v17 = 0; + u v18 = 0; + u v19 = 0; + u v20 = 0; + u v21 = 0; + vp = 0UL; + vlink = vi + 32UL; +b1: vd = *(u*)vlink; + if (!vd) goto b7; + v7 = 0UL; +b8: if (!v7) goto b5; + v12 = (u)zalloc; + v13 = *(u*)(vlc + 0UL); + v14 = 64UL; + v15 = ((u(*)())v12)(v13, v14); + vd = v15; + *(u*)(vd + 40UL) = *(u*)(vt + 40UL); + *(u*)(vd + 48UL) = *(u*)(vt + 48UL); + *(u*)(vd + 56UL) = *(u*)(vt + 56UL); + v16 = (u)zrb_link; + v17 = vi + 32UL; + v18 = vlink; + v19 = vp; + v20 = vd + 0UL; + v21 = ((u(*)())v16)(v17, v18, v19, v20); + v21; + return vd; +b5: v8 = (u)zlalr_itemcmp; + v9 = vt; + v10 = vd; + v11 = ((u(*)())v8)(v9, v10); + vdir = v11; + if ((s)vdir >= (s)0UL) goto b12; + vlink = vd + 0UL + 16UL; + vp = vd + 0UL; +b10: goto b1; +b12: if ((s)vdir <= (s)0UL) goto b14; + vlink = vd + 0UL + 24UL; + vp = vd + 0UL; + goto b10; +b14: return 0UL; +b7: v7 = 1UL; + goto b8; +} u zlalr_compiler(u vc, u vpn, u verr) { - u v_lc[7] = {0}; + u v_lc[11] = {0}; u vlc = 0; u v5 = 0; u v6 = 0; @@ -26291,8 +26358,371 @@ u zlalr_compiler(u vc, u vpn, u verr) { v11; return 0UL; } +u zlalr_goto(u vlc, u vi) { + u vt = 0; + u va = 0; + u vseen = 0; + u vqueue = 0; + u vprod = 0; + u valt = 0; + u vsym = 0; + u vr[8] = {0}; + u vj = 0; + u v11 = 0; + u v12 = 0; + u v13 = 0; + u v14 = 0; + u v15 = 0; + u v16 = 0; + u v17 = 0; + u v18 = 0; + u v19 = 0; + u v20 = 0; + u v21 = 0; + u v22 = 0; + u v23 = 0; + u v24 = 0; + u v25 = 0; + u v26 = 0; + u v27 = 0; + u v28 = 0; + u v29 = 0; + u v30 = 0; + u v31 = 0; + u v32 = 0; + u v33 = 0; + u v34 = 0; + u v35 = 0; + u v36 = 0; + u v37 = 0; + u v38 = 0; + u v39 = 0; + u v40 = 0; + u v41 = 0; + u v42 = 0; + u v43 = 0; + u v44 = 0; + u v45 = 0; + u v46 = 0; + u v47 = 0; + u v48 = 0; + u v49 = 0; + u v50 = 0; + u v51 = 0; + u v52 = 0; + u v53 = 0; + v11 = (u)zlalr_mkitemset; + v12 = vlc; + v13 = ((u(*)())v11)(v12); + vseen = v13; + v14 = (u)zrb_first; + v15 = *(u*)(vi + 32UL); + v16 = ((u(*)())v14)(v15); + vt = v16; +b3: if (!vt) goto b9; + v17 = 0UL; +b10: if (!v17) goto b7; +b16: vt = vqueue; + if (!vt) goto b22; + v26 = 0UL; +b23: if (!v26) goto b20; + v43 = (u)zrb_first; + v44 = *(u*)(vi + 48UL); + v45 = ((u(*)())v43)(v44); + vsym = v45; +b45: if (!vsym) goto b51; + v46 = 0UL; +b52: if (!v46) goto b49; + return 0UL; +b49: v47 = (u)zlalr_memoset; + v48 = vlc; + v49 = *(u*)(vsym + 56UL); + v50 = ((u(*)())v47)(v48, v49); + *(u*)(vsym + 56UL) = v50; + v51 = (u)zrb_next; + v52 = vsym + 0UL; + v53 = ((u(*)())v51)(v52); + vsym = v53; + goto b45; +b51: v46 = 1UL; + goto b52; +b20: vqueue = *(u*)(vt + 32UL); + valt = *(u*)(*(u*)(*(u*)(*(u*)(vlc + 32UL) + *(u*)(vt + 40UL) * 8UL) + 48UL) + *(u*)(vt + 48UL) * 8UL); + if (*(u*)(vt + 56UL) != *(u*)(valt + 8UL)) goto b26; + goto b16; +b26: vsym = *(u*)(valt + 0UL) + *(u*)(vt + 56UL) * 64UL; + *(u*)((u)vr + 40UL) = *(u*)(vt + 40UL); + *(u*)((u)vr + 48UL) = *(u*)(vt + 48UL); + *(u*)((u)vr + 56UL) = *(u*)(vt + 56UL) + 1UL; + v27 = (u)zlalr_assoc; + v28 = vlc; + v29 = vseen; + v30 = (u)vr; + v31 = ((u(*)())v27)(v28, v29, v30); + va = v31; + if (!va) goto b30; + *(u*)(va + 32UL) = vqueue; + vqueue = va; +b28: v32 = (u)zlalr_linkout; + v33 = vlc; + v34 = vi + 48UL; + v35 = vsym; + v36 = (u)vr; + v37 = ((u(*)())v32)(v33, v34, v35, v36); + v37; + if (!*(u*)(vsym + 32UL)) goto b34; + goto b16; +b34: vprod = *(u*)(*(u*)(vlc + 32UL) + *(u*)(vsym + 40UL) * 8UL); + vj = 0UL; +b35: if (vj != *(u*)(vprod + 56UL)) goto b39; + goto b16; +b39: *(u*)((u)vr + 40UL) = *(u*)(vsym + 40UL); + *(u*)((u)vr + 48UL) = vj; + *(u*)((u)vr + 56UL) = 0UL; + v38 = (u)zlalr_assoc; + v39 = vlc; + v40 = vseen; + v41 = (u)vr; + v42 = ((u(*)())v38)(v39, v40, v41); + va = v42; + if (!va) goto b43; + *(u*)(va + 32UL) = vqueue; + vqueue = va; +b41: vj = vj + 1UL; + goto b35; +b43: goto b41; +b30: goto b28; +b22: v26 = 1UL; + goto b23; +b7: v18 = (u)zlalr_assoc; + v19 = vlc; + v20 = vseen; + v21 = vt; + v22 = ((u(*)())v18)(v19, v20, v21); + va = v22; + if (!va) goto b14; + *(u*)(va + 32UL) = vqueue; + vqueue = va; +b12: v23 = (u)zrb_next; + v24 = vt + 0UL; + v25 = ((u(*)())v23)(v24); + vt = v25; + goto b3; +b14: goto b12; +b9: v17 = 1UL; + goto b10; +} +u zlalr_itemcmp(u va, u vb) { + if ((s)*(u*)(va + 40UL) >= (s)*(u*)(vb + 40UL)) goto b3; + return -1UL; +b3: if ((s)*(u*)(va + 40UL) <= (s)*(u*)(vb + 40UL)) goto b5; + return 1UL; +b5: if ((s)*(u*)(va + 48UL) >= (s)*(u*)(vb + 48UL)) goto b7; + return -1UL; +b7: if ((s)*(u*)(va + 48UL) <= (s)*(u*)(vb + 48UL)) goto b9; + return 1UL; +b9: if ((s)*(u*)(va + 56UL) >= (s)*(u*)(vb + 56UL)) goto b11; + return -1UL; +b11: if ((s)*(u*)(va + 56UL) <= (s)*(u*)(vb + 56UL)) goto b13; + return 1UL; +b13: return 0UL; +} u zlalr_items(u vlc) { + u vi = 0; + u vinit_state[8] = {0}; + u v3 = 0; + u v4 = 0; + u v5 = 0; + u v6 = 0; + u v7 = 0; + u v8 = 0; + u v9 = 0; + u v10 = 0; + u v11 = 0; + u v12 = 0; + u v13 = 0; + u v14 = 0; + u v15 = 0; + v3 = (u)zlalr_mkitemset; + v4 = vlc; + v5 = ((u(*)())v3)(v4); + vi = v5; + v6 = (u)zlalr_assoc; + v7 = vlc; + v8 = vi; + v9 = (u)vinit_state; + v10 = ((u(*)())v6)(v7, v8, v9); + v10; + *(u*)(vlc + 64UL) = vi; + *(u*)(vlc + 72UL) = vi; +b3: vi = *(u*)(vlc + 72UL); + if (!vi) goto b9; + v11 = 0UL; +b10: if (!v11) goto b7; return 0UL; +b7: *(u*)(vlc + 72UL) = *(u*)(vi + 40UL); + v12 = (u)zlalr_goto; + v13 = vlc; + v14 = vi; + v15 = ((u(*)())v12)(v13, v14); + v15; + goto b3; +b9: v11 = 1UL; + goto b10; +} +u zlalr_itemsetcmp(u va, u vb) { + u vx = 0; + u vy = 0; + u vdir = 0; + u v5 = 0; + u v6 = 0; + u v7 = 0; + u v8 = 0; + u v9 = 0; + u v10 = 0; + u v11 = 0; + u v12 = 0; + u v13 = 0; + u v14 = 0; + u v15 = 0; + u v16 = 0; + u v17 = 0; + u v18 = 0; + u v19 = 0; + u v20 = 0; + u v21 = 0; + u v22 = 0; + u v23 = 0; + u v24 = 0; + u v25 = 0; + v5 = (u)zrb_first; + v6 = *(u*)(va + 32UL); + v7 = ((u(*)())v5)(v6); + vx = v7; + v8 = (u)zrb_first; + v9 = *(u*)(vb + 32UL); + v10 = ((u(*)())v8)(v9); + vy = v10; +b3: if (!vx) goto b13; + v12 = 0UL; +b14: if (!v12) goto b9; + if (!vy) goto b16; + v13 = 0UL; +b17: if (!v13) goto b9; + v11 = 1UL; +b11: if (!v11) goto b7; + return 0UL; +b7: if (!vx) goto b21; + v14 = 0UL; +b22: if (!v14) goto b19; + return -1UL; +b19: if (!vy) goto b26; + v15 = 0UL; +b27: if (!v15) goto b24; + return 1UL; +b24: v16 = (u)zlalr_itemcmp; + v17 = vx; + v18 = vy; + v19 = ((u(*)())v16)(v17, v18); + vdir = v19; + if (vdir == 0UL) goto b31; + return vdir; +b31: v20 = (u)zrb_next; + v21 = vx + 0UL; + v22 = ((u(*)())v20)(v21); + vx = v22; + v23 = (u)zrb_next; + v24 = vy + 0UL; + v25 = ((u(*)())v23)(v24); + vy = v25; + goto b3; +b26: v15 = 1UL; + goto b27; +b21: v14 = 1UL; + goto b22; +b9: v11 = 0UL; + goto b11; +b16: v13 = 1UL; + goto b17; +b13: v12 = 1UL; + goto b14; +} +u zlalr_linkout(u vlc, u vout, u vsym, u vt) { + u vp = 0; + u vlink = 0; + u vd = 0; + u vdir = 0; + u v8 = 0; + u v9 = 0; + u v10 = 0; + u v11 = 0; + u v12 = 0; + u v13 = 0; + u v14 = 0; + u v15 = 0; + u v16 = 0; + u v17 = 0; + u v18 = 0; + u v19 = 0; + u v20 = 0; + u v21 = 0; + u v22 = 0; + u v23 = 0; + u v24 = 0; + u v25 = 0; + u v26 = 0; + u v27 = 0; + u v28 = 0; + u v29 = 0; + u v30 = 0; + vp = 0UL; + vlink = vout; +b1: vd = *(u*)vlink; + if (!vd) goto b7; + v8 = 0UL; +b8: if (!v8) goto b5; + v13 = (u)zalloc; + v14 = *(u*)(vlc + 0UL); + v15 = 64UL; + v16 = ((u(*)())v13)(v14, v15); + vd = v16; + *(u*)(vd + 32UL) = *(u*)(vsym + 32UL); + *(u*)(vd + 40UL) = *(u*)(vsym + 40UL); + *(u*)(vd + 48UL) = *(u*)(vsym + 48UL); + v17 = (u)zlalr_mkitemset; + v18 = vlc; + v19 = ((u(*)())v17)(v18); + *(u*)(vd + 56UL) = v19; + v20 = (u)zrb_link; + v21 = vout; + v22 = vlink; + v23 = vp; + v24 = vd + 0UL; + v25 = ((u(*)())v20)(v21, v22, v23, v24); + v25; + v26 = (u)zlalr_assoc; + v27 = vlc; + v28 = *(u*)(vd + 56UL); + v29 = vt; + v30 = ((u(*)())v26)(v27, v28, v29); + v30; + return 0UL; +b5: v9 = (u)zlalr_pointcmp; + v10 = vsym; + v11 = vd; + v12 = ((u(*)())v9)(v10, v11); + vdir = v12; + if ((s)vdir >= (s)0UL) goto b12; + vlink = vd + 0UL + 16UL; + vp = vd + 0UL; +b10: goto b1; +b12: if ((s)vdir <= (s)0UL) goto b14; + vlink = vd + 0UL + 24UL; + vp = vd + 0UL; + goto b10; +b14: return 0UL; +b7: v8 = 1UL; + goto b8; } u zlalr_lookup(u vlc, u vname, u vnew) { u vp = 0; @@ -26358,6 +26788,55 @@ b14: vlink = vd + 0UL + 24UL; b7: v7 = 1UL; goto b8; } +u zlalr_memoset(u vlc, u vi) { + u vp = 0; + u vlink = 0; + u vd = 0; + u vdir = 0; + u v6 = 0; + u v7 = 0; + u v8 = 0; + u v9 = 0; + u v10 = 0; + u v11 = 0; + u v12 = 0; + u v13 = 0; + u v14 = 0; + u v15 = 0; + u v16 = 0; + vp = 0UL; + vlink = vlc + 56UL; +b1: vd = *(u*)vlink; + if (!vd) goto b7; + v6 = 0UL; +b8: if (!v6) goto b5; + v11 = (u)zrb_link; + v12 = vlc + 56UL; + v13 = vlink; + v14 = vp; + v15 = vi + 0UL; + v16 = ((u(*)())v11)(v12, v13, v14, v15); + v16; + *(u*)(vi + 40UL) = *(u*)(vlc + 72UL); + *(u*)(vlc + 72UL) = vi; + return vi; +b5: v7 = (u)zlalr_itemsetcmp; + v8 = vi; + v9 = vd; + v10 = ((u(*)())v7)(v8, v9); + vdir = v10; + if ((s)vdir >= (s)0UL) goto b12; + vlink = vd + 0UL + 16UL; + vp = vd + 0UL; +b10: goto b1; +b12: if ((s)vdir <= (s)0UL) goto b14; + vlink = vd + 0UL + 24UL; + vp = vd + 0UL; + goto b10; +b14: return vd; +b7: v6 = 1UL; + goto b8; +} u zlalr_mkalt(u vlc, u vp) { u va = 0; u v3 = 0; @@ -26388,6 +26867,19 @@ u zlalr_mkalt(u vlc, u vp) { *(u*)(vp + 56UL) = *(u*)(vp + 56UL) + 1UL; return va; } +u zlalr_mkitemset(u vlc) { + u vi = 0; + u v2 = 0; + u v3 = 0; + u v4 = 0; + u v5 = 0; + v2 = (u)zalloc; + v3 = *(u*)(vlc + 0UL); + v4 = 64UL; + v5 = ((u(*)())v2)(v3, v4); + vi = v5; + return vi; +} u zlalr_mkprod(u vlc) { u vp = 0; u v2 = 0; @@ -26452,6 +26944,17 @@ b5: v5 = (u)zlalr_mkalt; b7: v4 = 1UL; goto b8; } +u zlalr_pointcmp(u va, u vb) { + if ((s)*(u*)(va + 32UL) >= (s)*(u*)(vb + 32UL)) goto b3; + return -1UL; +b3: if ((s)*(u*)(va + 32UL) <= (s)*(u*)(vb + 32UL)) goto b5; + return 1UL; +b5: if ((s)*(u*)(va + 40UL) >= (s)*(u*)(vb + 40UL)) goto b7; + return -1UL; +b7: if ((s)*(u*)(va + 40UL) <= (s)*(u*)(vb + 40UL)) goto b9; + return 1UL; +b9: return 0UL; +} u zlalr_primary(u vlc, u va, u vpn) { u vv = 0; u vs = 0; diff --git a/lalr.om b/lalr.om @@ -1,16 +1,27 @@ -// The dragon book is a good reference. // Aho, A.V., Sethi, R. and Ullman, J.D. (2007) Compilers: Principles, techniques, and Tools. Reading, Mass: Addison-Wesley. struct lalr_item { + node: rbnode; + queue_next: *lalr_item; prod: int; alt: int; point: int; } +struct lalr_itemset { + node: rbnode; + items: *rbnode; + goto_next: *lalr_itemset; + goto_out: *rbnode; + mark: int; +} + struct lalr_point { + node: rbnode; term: int; id: int; name: *byte; + out: *lalr_itemset; } struct lalr_alt { @@ -38,6 +49,12 @@ struct lalr_compiler { prod: **lalr_prod; prod_len: int; prod_cap: int; + + sets: *rbnode; + root: *lalr_itemset; + goto_queue: *lalr_itemset; + + mark: int; } func lalr_compiler(c: *compiler, pn: *peg_node, err: *file) { @@ -282,7 +299,7 @@ func lalr_alt_nonterminal(lc: *lalr_compiler, a: *lalr_alt, s: *lalr_prod) { ensure_arr(lc.a, (&a.point) as **void, &a.point_cap, a.point_len + 1, sizeof(*a.point)); i = a.point_len; a.point_len = a.point_len + 1; - a.point[i].term = 1; + a.point[i].term = 0; a.point[i].id = s.id; a.point[i].name = s.name; } @@ -346,18 +363,352 @@ func lalr_show(lc: *lalr_compiler) { } } +func lalr_mkitemset(lc: *lalr_compiler): *lalr_itemset { + var i: *lalr_itemset; + i = alloc(lc.a, sizeof(*i)) as *lalr_itemset; + return i; +} + +func lalr_itemcmp(a: *lalr_item, b: *lalr_item): int { + if a.prod < b.prod { + return -1; + } else if a.prod > b.prod { + return 1; + } else if a.alt < b.alt { + return -1; + } else if a.alt > b.alt { + return 1; + } else if a.point < b.point { + return -1; + } else if a.point > b.point { + return 1; + } + return 0; +} + +func lalr_itemsetcmp(a: *lalr_itemset, b: *lalr_itemset): int { + var x: *lalr_item; + var y: *lalr_item; + var dir: int; + x = rb_first(a.items) as *lalr_item; + y = rb_first(b.items) as *lalr_item; + loop { + if !x && !y { + return 0; + } else if !x { + return -1; + } else if !y { + return 1; + } + dir = lalr_itemcmp(x, y); + if dir != 0 { + return dir; + } + x = rb_next(&x.node) as *lalr_item; + y = rb_next(&y.node) as *lalr_item; + } +} + +func lalr_assoc(lc: *lalr_compiler, i: *lalr_itemset, t: *lalr_item): *lalr_item { + var p: *rbnode; + var link: **rbnode; + var d: *lalr_item; + var dir: int; + p = nil; + link = &i.items; + loop { + d = (*link) as *lalr_item; + if !d { + break; + } + dir = lalr_itemcmp(t, d); + if dir < 0 { + link = &d.node.left; + p = &d.node; + } else if dir > 0 { + link = &d.node.right; + p = &d.node; + } else { + return nil; + } + } + d = alloc(lc.a, sizeof(*d)) as *lalr_item; + d.prod = t.prod; + d.alt = t.alt; + d.point = t.point; + rb_link(&i.items, link, p, &d.node); + return d; +} + func lalr_items(lc: *lalr_compiler) { - // CLOSURE(I) - // J = I - // for each [A->a.Bb] in J - // for each production B->z - // add [B->.z] to J - // GOTO(I, X) - // CLOSURE({[A->aX.b] such that [A->a.Xb] in I}) - // ITEMS(G) - // C = CLOSURE({[S'->.S]}) - // for each I in C - // for each symbol x - // if GOTO(I,x) is not empty - // add GOTO(I,x) to C + var i: *lalr_itemset; + var init_state: lalr_item; + + i = lalr_mkitemset(lc); + lalr_assoc(lc, i, &init_state); + lc.root = i; + lc.goto_queue = i; + + loop { + i = lc.goto_queue; + if !i { + break; + } + lc.goto_queue = i.goto_next; + lalr_goto(lc, i); + } +} + +func lalr_goto(lc: *lalr_compiler, i: *lalr_itemset) { + var t: *lalr_item; + var a: *lalr_item; + var seen: *lalr_itemset; + var queue: *lalr_item; + var prod: *lalr_prod; + var alt: *lalr_alt; + var sym: *lalr_point; + var r: lalr_item; + var j: int; + + seen = lalr_mkitemset(lc); + + // Queue up the items from the current state + t = rb_first(i.items) as *lalr_item; + loop { + if !t { + break; + } + a = lalr_assoc(lc, seen, t); + if a { + a.queue_next = queue; + queue = a; + } + t = rb_next(&t.node) as *lalr_item; + } + + loop { + t = queue; + if !t { + break; + } + queue = t.queue_next; + + alt = lc.prod[t.prod].alt[t.alt]; + if t.point == alt.point_len { + continue; + } + + // That symbol is the edge in the graph + sym = &alt.point[t.point]; + + r.prod = t.prod; + r.alt = t.alt; + r.point = t.point + 1; + + a = lalr_assoc(lc, seen, &r); + if a { + a.queue_next = queue; + queue = a; + } + + lalr_linkout(lc, &i.goto_out, sym, &r); + if sym.term { + continue; + } + + prod = lc.prod[sym.id]; + j = 0; + loop { + if j == prod.alt_len { + break; + } + + r.prod = sym.id; + r.alt = j; + r.point = 0; + + a = lalr_assoc(lc, seen, &r); + if a { + a.queue_next = queue; + queue = a; + } + + j = j + 1; + } + } + + sym = rb_first(i.goto_out) as *lalr_point; + loop { + if !sym { + break; + } + sym.out = lalr_memoset(lc, sym.out); + sym = rb_next(&sym.node) as *lalr_point; + } +} + +func lalr_pointcmp(a: *lalr_point, b: *lalr_point): int { + if a.term < b.term { + return -1; + } else if a.term > b.term { + return 1; + } else if a.id < b.id { + return -1; + } else if a.id > b.id { + return 1; + } + return 0; +} + +func lalr_linkout(lc: *lalr_compiler, out: **rbnode, sym: *lalr_point, t: *lalr_item) { + var p: *rbnode; + var link: **rbnode; + var d: *lalr_point; + var dir: int; + p = nil; + link = out; + loop { + d = (*link) as *lalr_point; + if !d { + break; + } + dir = lalr_pointcmp(sym, d); + if dir < 0 { + link = &d.node.left; + p = &d.node; + } else if dir > 0 { + link = &d.node.right; + p = &d.node; + } else { + return; + } + } + d = alloc(lc.a, sizeof(*d)) as *lalr_point; + d.term = sym.term; + d.id = sym.id; + d.name = sym.name; + d.out = lalr_mkitemset(lc); + rb_link(out, link, p, &d.node); + lalr_assoc(lc, d.out, t); +} + +func lalr_memoset(lc: *lalr_compiler, i: *lalr_itemset): *lalr_itemset { + var p: *rbnode; + var link: **rbnode; + var d: *lalr_itemset; + var dir: int; + p = nil; + link = &lc.sets; + loop { + d = (*link) as *lalr_itemset; + if !d { + break; + } + dir = lalr_itemsetcmp(i, d); + if dir < 0 { + link = &d.node.left; + p = &d.node; + } else if dir > 0 { + link = &d.node.right; + p = &d.node; + } else { + return d; + } + } + rb_link(&lc.sets, link, p, &i.node); + i.goto_next = lc.goto_queue; + lc.goto_queue = i; + return i; +} + +func lalr_showlr(lc: *lalr_compiler) { + lalr_showlr2(lc, lc.root); +} + +func lalr_showlr2(lc: *lalr_compiler, i: *lalr_itemset): int { + var t: *lalr_item; + var sym: *lalr_point; + var prod: *lalr_prod; + var alt: *lalr_alt; + var j: int; + var out: *file; + var k: int; + + if i.mark { + return i.mark; + } + lc.mark = lc.mark + 1; + i.mark = lc.mark; + + fputd(out, i.mark); + fputs(out, "{"); + + t = rb_first(i.items) as *lalr_item; + loop { + if !t { + break; + } + + prod = lc.prod[t.prod]; + alt = prod.alt[t.alt]; + + fputs(out, "["); + if prod.name { + fputs(out, prod.name); + } else { + fputd(out, prod.id); + } + + fputs(out, "->"); + k = 0; + loop { + if k == t.point { + fputs(out, "!"); + } + if k == alt.point_len { + break; + } + sym = &alt.point[k]; + if sym.name { + fputs(out, sym.name); + } else { + fputd(out, sym.id); + } + k = k + 1; + if k != alt.point_len && k != t.point { + fputc(out, ' '); + } + } + fputs(out, "]"); + + t = rb_next(&t.node) as *lalr_item; + + if t { + fputs(out, ","); + } + } + + fputs(out, "};\n"); + + sym = rb_first(i.goto_out) as *lalr_point; + loop { + if !sym { + break; + } + j = lalr_showlr2(lc, sym.out); + fputd(out, i.mark); + fputs(out, "->"); + fputd(out, j); + fputs(out, "["); + if sym.name { + fputs(out, sym.name); + } else { + fputd(out, sym.id); + } + fputs(out, "]"); + fputs(out, ";\n"); + sym = rb_next(&sym.node) as *lalr_point; + } + + return i.mark; }