Skip to content

Commit 10a5314

Browse files
committed
add lr parser
Signed-off-by: Shaw Summa <[email protected]>
1 parent 09b73bc commit 10a5314

File tree

22 files changed

+994
-237
lines changed

22 files changed

+994
-237
lines changed

js.txt

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
{
2+
action: [
3+
Map { 'S' => 's1', 'X' => 's2', 'a' => 's3', 'b' => 's4' },
4+
Map { '$' => 'acc' },
5+
Map { 'X' => 's5', 'a' => 's6', 'b' => 's7' },
6+
Map { 'X' => 's8', 'a' => 's3', 'b' => 's4' },
7+
Map { 'b' => 'r3', 'a' => 'r3' },
8+
Map { '$' => 'r1' },
9+
Map { 'X' => 's9', 'a' => 's6', 'b' => 's7' },
10+
Map { '$' => 'r3' },
11+
Map { 'b' => 'r2', 'a' => 'r2' },
12+
Map { '$' => 'r2' }
13+
],
14+
goTo: [
15+
Map { 'S' => 1, 'X' => 2 },
16+
Map {},
17+
Map { 'X' => 5 },
18+
Map { 'X' => 8 },
19+
Map {},
20+
Map {},
21+
Map { 'X' => 9 },
22+
Map {},
23+
Map {},
24+
Map {}
25+
]
26+
}

lua.txt

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
{
2+
go_to = [
3+
{
4+
S = 2
5+
X = 3
6+
}
7+
{
8+
}
9+
{
10+
X = 6
11+
}
12+
{
13+
X = 9
14+
}
15+
{
16+
}
17+
{
18+
}
19+
{
20+
X = 10
21+
}
22+
{
23+
}
24+
{
25+
}
26+
{
27+
}
28+
]
29+
action = [
30+
{
31+
S = s2
32+
b = s5
33+
a = s4
34+
X = s3
35+
}
36+
{
37+
$ = acc
38+
}
39+
{
40+
b = s8
41+
a = s7
42+
X = s6
43+
}
44+
{
45+
b = s5
46+
a = s4
47+
X = s9
48+
}
49+
{
50+
a = r4
51+
b = r4
52+
}
53+
{
54+
$ = r2
55+
}
56+
{
57+
b = s8
58+
a = s7
59+
X = s10
60+
}
61+
{
62+
$ = r4
63+
}
64+
{
65+
a = r3
66+
b = r3
67+
}
68+
{
69+
$ = r3
70+
}
71+
]
72+
}

makefile

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
# Must be a GCC or Clang
33
CC ?= cc
44

5-
OPT ?= -O3 -ffast-math -flto -DNDEBUG
5+
OPT ?= -O3 -fno-math-errno -fno-trapping-math -flto -DNDEBUG
66

77
EXE ?=
88

@@ -19,15 +19,10 @@ LIBM_FLAGS := ${LIBM_${LIBM}}
1919
BASE_CFLAGS := ${OPT} -Ivendor/tree-sitter/lib/include -Ivendor/mimalloc/include -Ivendor/tree-sitter/lib/src ${CFLAGS}
2020
BASE_LDFLAGS := ${OPT} ${LDFLAGS} ${LIBM_FLAGS}
2121

22-
# mimalloc
23-
24-
# BASE_LDFLAGS += -lSynchronization
25-
MI_PRIM_SRC := vendor/mimalloc/src/prim/unix/prim.c
26-
2722
# object files and depends
2823
MAIN_SRCS = main/minivm.c
2924
VM_SRCS := $(shell find vm | grep \\.c)
30-
MI_SRCS := ${MI_PRIM_SRC} vendor/mimalloc/src/alloc-posix.c vendor/mimalloc/src/alloc-aligned.c vendor/mimalloc/src/alloc.c vendor/mimalloc/src/arena.c vendor/mimalloc/src/bitmap.c vendor/mimalloc/src/heap.c vendor/mimalloc/src/init.c vendor/mimalloc/src/libc.c vendor/mimalloc/src/options.c vendor/mimalloc/src/os.c vendor/mimalloc/src/page.c vendor/mimalloc/src/random.c vendor/mimalloc/src/segment-map.c vendor/mimalloc/src/segment.c vendor/mimalloc/src/stats.c
25+
# MI_SRCS := vendor/mimalloc/src/prim/prim.c vendor/mimalloc/src/alloc-posix.c vendor/mimalloc/src/alloc-aligned.c vendor/mimalloc/src/alloc.c vendor/mimalloc/src/arena.c vendor/mimalloc/src/bitmap.c vendor/mimalloc/src/heap.c vendor/mimalloc/src/init.c vendor/mimalloc/src/libc.c vendor/mimalloc/src/options.c vendor/mimalloc/src/os.c vendor/mimalloc/src/page.c vendor/mimalloc/src/random.c vendor/mimalloc/src/segment-map.c vendor/mimalloc/src/segment.c vendor/mimalloc/src/stats.c
3126
TS_SRCS += vendor/tree-sitter/lib/src/alloc.c vendor/tree-sitter/lib/src/get_changed_ranges.c vendor/tree-sitter/lib/src/language.c vendor/tree-sitter/lib/src/lexer.c vendor/tree-sitter/lib/src/node.c vendor/tree-sitter/lib/src/parser.c vendor/tree-sitter/lib/src/query.c vendor/tree-sitter/lib/src/stack.c vendor/tree-sitter/lib/src/subtree.c vendor/tree-sitter/lib/src/tree_cursor.c vendor/tree-sitter/lib/src/tree.c vendor/tree-sitter/lib/src/wasm_store.c
3227
IC_SRCS := vendor/isocline/src/isocline.c
3328
MAIN_SRCS += ${VM_SRCS} ${TS_SRCS} ${IC_SRCS} ${MI_SRCS}

test/lua/parser/lr1.js

Lines changed: 208 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,208 @@
1+
function first(G, A) {
2+
let result = new Set
3+
let visited = new Set
4+
let stack = [A]
5+
while (stack.length > 0) {
6+
let X = stack.pop()
7+
if (visited.has(X)) continue
8+
visited.add(X)
9+
if (!/^[A-Z]/.test(X) || X === '$') {
10+
result.add(X)
11+
continue
12+
}
13+
for (let i = 0; i < G.length; i++) {
14+
let r = G[i]
15+
if (r[0] === X && r[1] !== X) {
16+
stack.push(r[1])
17+
}
18+
}
19+
}
20+
return result
21+
}
22+
23+
function closure(G, items) {
24+
let stack = items.slice()
25+
let state = items.slice()
26+
let visited = new Set
27+
while (true) {
28+
if (stack.length === 0) break
29+
let item = stack.shift()
30+
let key = item.rule + ',' + item.dot + ',' + item.lookahead
31+
if (visited.has(key)) {
32+
continue
33+
}
34+
visited.add(key)
35+
state.push(item)
36+
let r = G[item.rule]
37+
let X1 = r[item.dot + 1]
38+
let X2 = r[item.dot + 2]
39+
for (let i = 0; i < G.length; i++) {
40+
if (G[i][0] !== X1) continue
41+
let ls = item.dot + 2 === r.length
42+
? new Set([item.lookahead])
43+
: union(first(G, X1), first(G, X2))
44+
for (let lookahead of ls) {
45+
let nitem = {
46+
rule: i,
47+
dot: 0,
48+
lookahead,
49+
next: -1,
50+
index: -1,
51+
}
52+
stack.push(nitem)
53+
}
54+
}
55+
}
56+
return state
57+
}
58+
59+
function union(A, B) {
60+
// :(
61+
return new Set(Array.from(A).concat(Array.from(B)))
62+
}
63+
64+
class States {
65+
static key(items) {
66+
return items.map(item => {
67+
return item.rule + ',' + item.dot + ',' + item.lookahead
68+
}).sort().join('_')
69+
}
70+
constructor(G) {
71+
this.G = G
72+
this.states = []
73+
this._stateKeys = new Map
74+
}
75+
add(items) {
76+
let key = States.key(items)
77+
78+
let i = this._stateKeys.get(key)
79+
if (i !== undefined) return i
80+
i = this.states.length
81+
this.states.push(items)
82+
this._stateKeys.set(key, i)
83+
return i
84+
}
85+
has(items) {
86+
return this._stateKeys.has(States.key(items))
87+
}
88+
}
89+
90+
function groupNext(G, state) {
91+
let groups = new Map
92+
for (let i = 0; i < state.length; i++) {
93+
let s = state[i]
94+
let rule = G[s.rule]
95+
if (s.dot + 1 >= rule.length) continue
96+
let X0 = rule[0]
97+
let X1 = rule[s.dot + 1]
98+
let gs = groups.get(X1)
99+
if (gs == null) gs = []
100+
gs.push({
101+
rule: s.rule,
102+
dot: s.dot + 1,
103+
lookahead: s.lookahead,
104+
index: i,
105+
next: -1,
106+
})
107+
groups.set(X1, gs)
108+
}
109+
return groups
110+
}
111+
112+
function itemSets(G) {
113+
let states = new States(G)
114+
let I0 = closure(G, [{ rule: 0, dot: 0, lookahead: '$', index: 0, next: -1 }])
115+
let i0 = states.add(I0)
116+
let stack = [I0]
117+
while (true) {
118+
if (stack.length === 0) break
119+
let I = stack.shift()
120+
let groups = groupNext(G, I)
121+
for (let T of Array.from(groups.keys()).sort()) {
122+
let gs = groups.get(T)
123+
let J = closure(G, gs)
124+
if (!states.has(J)) stack.push(J)
125+
let j = states.add(J)
126+
for (let si = 0; si < gs.length; si++) {
127+
let g = gs[si]
128+
I[g.index].next = j
129+
}
130+
}
131+
}
132+
return states.states
133+
}
134+
135+
function createTable(G, states) {
136+
let action = Array(states.length).fill(null).map(x => new Map)
137+
let goTo = Array(states.length).fill(null).map(x => new Map)
138+
139+
for (let i = 0; i < states.length; i++) {
140+
let I = states[i]
141+
for (let j = 0; j < I.length; j++) {
142+
let item = I[j]
143+
if (item.rule === 0 && item.dot + 1 === G[item.rule].length && item.lookahead === '$') {
144+
action[i].set('$', 'acc')
145+
} else if (item.dot + 1 === G[item.rule].length) {
146+
let a = item.lookahead
147+
action[i].set(a, 'r' + item.rule)
148+
} else {
149+
let a = G[item.rule][item.dot + 1]
150+
action[i].set(a, 's' + item.next)
151+
}
152+
let A = G[item.rule][item.dot + 1]
153+
if (/^[A-Z]/.test(A)) {
154+
goTo[i].set(A, item.next)
155+
}
156+
}
157+
}
158+
return { action, goTo }
159+
}
160+
161+
function parse(G, { action, goTo }, input) {
162+
let firstSymbol = G[0][0]
163+
let offset = 0
164+
let stack = [0]
165+
let nodes = []
166+
let lookahead = input[0]
167+
168+
while (true) {
169+
let state = stack[stack.length - 1]
170+
let a = action[state].get(lookahead)
171+
if (a === undefined) throw new Error(`no action for state: ${state} lookahead: ${lookahead}`)
172+
let n = Number(a.slice(1))
173+
if (/^s/.test(a)) {
174+
nodes.push({ symbol: lookahead, offset })
175+
stack.push(n)
176+
lookahead = input[++offset]
177+
} else if (/^r/.test(a)) {
178+
let symbol = G[n][0]
179+
let arity = G[n].length - 1
180+
let children = Array(arity)
181+
for (let i = 0; i < arity; i++) {
182+
children[arity - 1 - i] = nodes.pop()
183+
stack.pop()
184+
}
185+
nodes.push({ symbol, children })
186+
187+
state = stack[stack.length - 1]
188+
let gt = goTo[state].get(symbol)
189+
if (gt === undefined) throw new Error(`undefined goto for state=${state} symbol=${symbol}`)
190+
stack.push(gt)
191+
} else if (a === 'acc') {
192+
return { symbol: firstSymbol, children: nodes }
193+
} else {
194+
throw new Error(`unexpected value for action ${a}`)
195+
}
196+
}
197+
}
198+
199+
let grammar = [
200+
[ "S", "S" ],
201+
[ "S", "X", "X" ],
202+
[ "X", "a", "X" ],
203+
[ "X", "b" ]
204+
]
205+
let sets = itemSets(grammar)
206+
// console.log(sets)
207+
let tab = createTable(grammar, sets)
208+
console.log(tab)

0 commit comments

Comments
 (0)