https://github.com/akkartik/mu/blob/main/shell/parse.mu
1 fn parse-input tokens: (addr stream cell), out: (addr handle cell), trace: (addr trace) {
2 rewind-stream tokens
3 var empty?/eax: boolean <- stream-empty? tokens
4 compare empty?, 0/false
5 {
6 break-if-=
7 error trace, "nothing to parse"
8 return
9 }
10 var close-paren?/eax: boolean <- parse-sexpression tokens, out, trace
11 {
12 compare close-paren?, 0/false
13 break-if-=
14 error trace, "')' is not a valid expression"
15 return
16 }
17 {
18 var empty?/eax: boolean <- stream-empty? tokens
19 compare empty?, 0/false
20 break-if-!=
21 error trace, "unexpected tokens at end; only type in a single expression at a time"
22 }
23 }
24
25
26 fn parse-sexpression tokens: (addr stream cell), _out: (addr handle cell), trace: (addr trace) -> _/eax: boolean {
27 trace-text trace, "read", "parse"
28 trace-lower trace
29 var curr-token-storage: cell
30 var curr-token/ecx: (addr cell) <- address curr-token-storage
31 var empty?/eax: boolean <- stream-empty? tokens
32 compare empty?, 0/false
33 {
34 break-if-=
35 error trace, "end of stream; never found a balancing ')'"
36 return 1/true
37 }
38 read-from-stream tokens, curr-token
39 $parse-sexpression:type-check: {
40
41 var quote-token?/eax: boolean <- quote-token? curr-token
42 compare quote-token?, 0/false
43 {
44 break-if-=
45 var out/edi: (addr handle cell) <- copy _out
46 allocate-pair out
47 var out-addr/eax: (addr cell) <- lookup *out
48 var left-ah/ecx: (addr handle cell) <- get out-addr, left
49 new-symbol left-ah, "'"
50 var right-ah/ecx: (addr handle cell) <- get out-addr, right
51 var result/eax: boolean <- parse-sexpression tokens, right-ah, trace
52 return result
53 }
54
55 var bracket-token?/eax: boolean <- bracket-token? curr-token
56 compare bracket-token?, 0/false
57 {
58 break-if-!=
59 parse-atom curr-token, _out, trace
60 break $parse-sexpression:type-check
61 }
62
63 var open-paren?/eax: boolean <- open-paren-token? curr-token
64 compare open-paren?, 0/false
65 {
66 break-if-=
67 var curr/esi: (addr handle cell) <- copy _out
68 $parse-sexpression:list-loop: {
69 allocate-pair curr
70 var curr-addr/eax: (addr cell) <- lookup *curr
71 var left/ecx: (addr handle cell) <- get curr-addr, left
72 {
73 var close-paren?/eax: boolean <- parse-sexpression tokens, left, trace
74 compare close-paren?, 0/false
75 break-if-!= $parse-sexpression:list-loop
76 }
77
78 curr <- get curr-addr, right
79 loop
80 }
81 break $parse-sexpression:type-check
82 }
83
84 var close-paren?/eax: boolean <- close-paren-token? curr-token
85 compare close-paren?, 0/false
86 {
87 break-if-=
88 trace-higher trace
89 return 1/true
90 }
91
92 var stream-storage: (stream byte 0x40)
93 var stream/edx: (addr stream byte) <- address stream-storage
94 write stream, "unexpected token "
95 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data
96 var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah
97 rewind-stream curr-token-data
98 write-stream stream, curr-token-data
99 trace trace, "error", stream
100 }
101 trace-higher trace
102 return 0/false
103 }
104
105 fn parse-atom _curr-token: (addr cell), _out: (addr handle cell), trace: (addr trace) {
106 trace-text trace, "read", "parse atom"
107 var curr-token/ecx: (addr cell) <- copy _curr-token
108 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data
109 var _curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah
110 var curr-token-data/esi: (addr stream byte) <- copy _curr-token-data
111 trace trace, "read", curr-token-data
112
113 var number-token?/eax: boolean <- number-token? curr-token
114 compare number-token?, 0/false
115 {
116 break-if-=
117 rewind-stream curr-token-data
118 var _val/eax: int <- parse-decimal-int-from-stream curr-token-data
119 var val/ecx: int <- copy _val
120 var val-float/xmm0: float <- convert val
121 allocate-number _out
122 var out/eax: (addr handle cell) <- copy _out
123 var out-addr/eax: (addr cell) <- lookup *out
124 var dest/edi: (addr float) <- get out-addr, number-data
125 copy-to *dest, val-float
126 {
127 var stream-storage: (stream byte 0x40)
128 var stream/ecx: (addr stream byte) <- address stream-storage
129 write stream, "=> number "
130 print-number out-addr, stream, 0/no-trace
131 trace trace, "read", stream
132 }
133 return
134 }
135
136
137 allocate-symbol _out
138 var out/eax: (addr handle cell) <- copy _out
139 var out-addr/eax: (addr cell) <- lookup *out
140 var curr-token-data-ah/ecx: (addr handle stream byte) <- get curr-token, text-data
141 var dest-ah/edx: (addr handle stream byte) <- get out-addr, text-data
142 copy-object curr-token-data-ah, dest-ah
143 {
144 var stream-storage: (stream byte 0x40)
145 var stream/ecx: (addr stream byte) <- address stream-storage
146 write stream, "=> symbol "
147 print-symbol out-addr, stream, 0/no-trace
148 trace trace, "read", stream
149 }
150 }