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 bracket-token?/eax: boolean <- bracket-token? curr-token
42 compare bracket-token?, 0/false
43 {
44 break-if-!=
45 parse-atom curr-token, _out, trace
46 break $parse-sexpression:type-check
47 }
48
49 var open-paren?/eax: boolean <- open-paren-token? curr-token
50 compare open-paren?, 0/false
51 {
52 break-if-=
53 var curr/esi: (addr handle cell) <- copy _out
54 $parse-sexpression:list-loop: {
55 allocate-pair curr
56 var curr-addr/eax: (addr cell) <- lookup *curr
57 var left/ecx: (addr handle cell) <- get curr-addr, left
58 {
59 var close-paren?/eax: boolean <- parse-sexpression tokens, left, trace
60 compare close-paren?, 0/false
61 break-if-!= $parse-sexpression:list-loop
62 }
63
64 curr <- get curr-addr, right
65 loop
66 }
67 break $parse-sexpression:type-check
68 }
69
70 var close-paren?/eax: boolean <- close-paren-token? curr-token
71 compare close-paren?, 0/false
72 {
73 break-if-=
74 trace-higher trace
75 return 1/true
76 }
77
78 var stream-storage: (stream byte 0x40)
79 var stream/edx: (addr stream byte) <- address stream-storage
80 write stream, "unexpected token "
81 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data
82 var curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah
83 rewind-stream curr-token-data
84 write-stream stream, curr-token-data
85 trace trace, "error", stream
86 }
87 trace-higher trace
88 return 0/false
89 }
90
91 fn parse-atom _curr-token: (addr cell), _out: (addr handle cell), trace: (addr trace) {
92 trace-text trace, "read", "parse atom"
93 var curr-token/ecx: (addr cell) <- copy _curr-token
94 var curr-token-data-ah/eax: (addr handle stream byte) <- get curr-token, text-data
95 var _curr-token-data/eax: (addr stream byte) <- lookup *curr-token-data-ah
96 var curr-token-data/esi: (addr stream byte) <- copy _curr-token-data
97 trace trace, "read", curr-token-data
98
99 var number-token?/eax: boolean <- number-token? curr-token
100 compare number-token?, 0/false
101 {
102 break-if-=
103 rewind-stream curr-token-data
104 var _val/eax: int <- parse-decimal-int-from-stream curr-token-data
105 var val/ecx: int <- copy _val
106 var val-float/xmm0: float <- convert val
107 allocate-number _out
108 var out/eax: (addr handle cell) <- copy _out
109 var out-addr/eax: (addr cell) <- lookup *out
110 var dest/edi: (addr float) <- get out-addr, number-data
111 copy-to *dest, val-float
112 {
113 var stream-storage: (stream byte 0x40)
114 var stream/ecx: (addr stream byte) <- address stream-storage
115 write stream, "=> number "
116 print-number out-addr, stream, 0/no-trace
117 trace trace, "read", stream
118 }
119 return
120 }
121
122
123 allocate-symbol _out
124 var out/eax: (addr handle cell) <- copy _out
125 var out-addr/eax: (addr cell) <- lookup *out
126 var curr-token-data-ah/ecx: (addr handle stream byte) <- get curr-token, text-data
127 var dest-ah/edx: (addr handle stream byte) <- get out-addr, text-data
128 copy-object curr-token-data-ah, dest-ah
129 {
130 var stream-storage: (stream byte 0x40)
131 var stream/ecx: (addr stream byte) <- address stream-storage
132 write stream, "=> symbol "
133 print-symbol out-addr, stream, 0/no-trace
134 trace trace, "read", stream
135 }
136 }