Commit | Line | Data |
---|---|---|
59038a10 C |
1 | require types.fs |
2 | require printer.fs | |
3 | ||
4 | \ Drop a char off the front of string by advancing the addr and | |
5 | \ decrementing the length, and fetch next char | |
6 | : adv-str ( str-addr str-len -- str-addr str-len char ) | |
7 | swap 1+ swap 1- | |
8 | dup 0= if 0 ( eof ) | |
9 | else over c@ endif ; | |
10 | ||
59038a10 C |
11 | : mal-digit? ( char -- flag ) |
12 | dup [char] 9 <= if | |
13 | [char] 0 >= | |
14 | else | |
15 | drop 0 | |
16 | endif ; | |
17 | ||
18 | : char-in-str? ( char str-addr str-len ) | |
19 | rot { needle } | |
bf6a574e C |
20 | false -rot |
21 | over + swap ?do | |
22 | i c@ needle = if drop true leave endif | |
23 | loop ; | |
24 | ||
25 | : sym-char? ( char -- flag ) | |
26 | s\" \n\r\t\000[]{}()'\"`,; " char-in-str? 0= ; | |
27 | ||
28 | : skip-spaces ( str-addr str-len char -- str-addr str-len non-space-char ) | |
29 | begin | |
30 | begin | |
31 | dup s\" \n\r\t, " char-in-str? | |
32 | while ( str-addr str-len space-char ) | |
33 | drop adv-str | |
34 | repeat | |
35 | dup [char] ; = if | |
36 | drop | |
37 | begin | |
38 | adv-str s\" \n\r\000" char-in-str? | |
39 | until | |
40 | adv-str false | |
59038a10 | 41 | else |
bf6a574e | 42 | true |
59038a10 C |
43 | endif |
44 | until ; | |
45 | ||
59038a10 C |
46 | defer read-form ( str-addr str-len -- str-addr str-len mal-obj ) |
47 | ||
48 | : read-int ( str-addr str-len digit-char -- str-addr str-len non-digit-char mal-int ) | |
49 | 0 { int } | |
7412ebc6 JM |
50 | 0 { neg } |
51 | dup [char] - = if drop adv-str 1 to neg endif | |
59038a10 C |
52 | begin ( str-addr str-len digit-char ) |
53 | [char] 0 - int 10 * + to int ( str-addr str-len ) | |
54 | adv-str dup mal-digit? 0= ( str-addr str-len digit-char ) | |
55 | until | |
7412ebc6 | 56 | neg if 0 int - to int endif |
59038a10 C |
57 | int MalInt. ; |
58 | ||
168fb5dc | 59 | : read-symbol-str ( str-addr str-len sym-char -- str-addr str-len char sym-addr sym-len ) |
59038a10 | 60 | new-str { sym-addr sym-len } |
168fb5dc | 61 | begin ( str-addr str-len sym-char ) |
59038a10 C |
62 | sym-addr sym-len rot str-append-char to sym-len to sym-addr |
63 | adv-str dup sym-char? 0= | |
64 | until | |
65 | sym-addr sym-len ; | |
66 | ||
168fb5dc C |
67 | : read-string-literal ( in-addr in-len quote-char -- in-addr in-len mal-string ) |
68 | new-str { out-addr out-len } | |
69 | drop \ drop leading quote | |
70 | begin ( in-addr in-len ) | |
71 | adv-str over 0= if | |
580c4eef | 72 | 2drop 0 0 s\" expected '\"', got EOF" ...throw-str |
168fb5dc C |
73 | endif |
74 | dup [char] " <> | |
75 | while | |
76 | dup [char] \ = if | |
77 | drop adv-str | |
78 | dup [char] n = if drop 10 endif | |
79 | dup [char] r = if drop 13 endif | |
80 | endif | |
81 | out-addr out-len rot str-append-char to out-len to out-addr | |
82 | repeat | |
83 | drop adv-str \ skip trailing quote | |
84 | out-addr out-len MalString. ; | |
85 | ||
9da223a3 | 86 | : read-list ( str-addr str-len open-paren-char close-paren-char |
c05d35e8 | 87 | -- str-addr str-len non-paren-char mal-list ) |
9da223a3 C |
88 | here { close-char old-here } |
89 | drop adv-str | |
90 | begin ( str-addr str-len char ) | |
91 | skip-spaces ( str-addr str-len non-space-char ) | |
92 | over 0= if | |
580c4eef C |
93 | drop 2drop 0 0 s" ', got EOF" |
94 | close-char pad ! pad 1 | |
95 | s" expected '" ...throw-str | |
9da223a3 C |
96 | endif |
97 | dup close-char <> | |
98 | while ( str-addr str-len non-space-non-paren-char ) | |
99 | read-form , | |
100 | repeat | |
101 | drop adv-str | |
bf6a574e | 102 | old-here here>MalList ; |
59038a10 | 103 | |
794bfca1 C |
104 | s" deref" MalSymbol. constant deref-sym |
105 | s" quote" MalSymbol. constant quote-sym | |
106 | s" quasiquote" MalSymbol. constant quasiquote-sym | |
107 | s" splice-unquote" MalSymbol. constant splice-unquote-sym | |
108 | s" unquote" MalSymbol. constant unquote-sym | |
109 | ||
168fb5dc | 110 | : read-wrapped ( buf-addr buf-len quote-char sym-addr sym-len -- buf-addr buf-len char mal-list ) |
69972a83 | 111 | here { old-here } |
794bfca1 | 112 | , ( buf-addr buf-len char ) |
69972a83 | 113 | read-form , ( buf-addr buf-len char ) |
c05d35e8 | 114 | old-here here>MalList ; |
168fb5dc C |
115 | |
116 | : read-form2 ( str-addr str-len char -- str-addr str-len char mal-obj ) | |
bf6a574e | 117 | skip-spaces |
7412ebc6 | 118 | dup [char] - = 3 pick 1 + c@ mal-digit? and if read-int else |
bf6a574e C |
119 | dup mal-digit? if read-int else |
120 | dup [char] ( = if [char] ) read-list else | |
121 | dup [char] [ = if [char] ] read-list MalVector new tuck MalVector/list ! else | |
122 | dup [char] { = if [char] } read-list MalMap new tuck MalMap/list ! else | |
123 | dup [char] " = if read-string-literal else | |
124 | dup [char] : = if drop adv-str read-symbol-str MalKeyword. else | |
794bfca1 C |
125 | dup [char] @ = if drop adv-str deref-sym read-wrapped else |
126 | dup [char] ' = if drop adv-str quote-sym read-wrapped else | |
127 | dup [char] ` = if drop adv-str quasiquote-sym read-wrapped else | |
bf6a574e C |
128 | dup [char] ~ = if |
129 | drop adv-str | |
794bfca1 C |
130 | dup [char] @ = if drop adv-str splice-unquote-sym read-wrapped |
131 | else unquote-sym read-wrapped | |
bf6a574e C |
132 | endif |
133 | else | |
134 | dup [char] ^ = if | |
135 | drop adv-str | |
136 | read-form { meta } read-form { obj } | |
137 | meta mal-nil conj | |
138 | obj swap conj | |
139 | s" with-meta" MalSymbol. swap conj | |
140 | else | |
141 | read-symbol-str | |
142 | 2dup s" true" str= if 2drop mal-true | |
143 | else 2dup s" false" str= if 2drop mal-false | |
144 | else 2dup s" nil" str= if 2drop mal-nil | |
168fb5dc | 145 | else |
bf6a574e | 146 | MalSymbol. |
7412ebc6 | 147 | endif endif endif endif endif endif endif endif endif endif endif endif endif endif endif ; |
59038a10 C |
148 | ' read-form2 is read-form |
149 | ||
150 | : read-str ( str-addr str-len - mal-obj ) | |
168fb5dc | 151 | over c@ read-form { obj } drop 2drop obj ; |