Mercurial > hg > index.cgi
comparison src/number.s @ 84:f959c92bc329
New first pass implementation of number parsing, untested
Rewrite number parsing using recently constructed infrastructure. The result
is untested.
author | William Astle <lost@l-w.ca> |
---|---|
date | Sun, 08 Oct 2023 00:17:20 -0600 |
parents | bb50ac9fdf37 |
children | 663d8e77b579 |
comparison
equal
deleted
inserted
replaced
83:a492441bfc56 | 84:f959c92bc329 |
---|---|
98 lbeq int32_mod ; do integer modulus | 98 lbeq int32_mod ; do integer modulus |
99 cmpb #valtype_float ; floating point? | 99 cmpb #valtype_float ; floating point? |
100 lbeq fps_mod ; floating point modulus | 100 lbeq fps_mod ; floating point modulus |
101 jmp TMERROR ; unsupported type | 101 jmp TMERROR ; unsupported type |
102 endc | 102 endc |
103 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; | |
104 ; Parse a number to either an integer or a floating point value | |
105 ; | |
106 ; First, identify any sign present. Then parse the remainder as an integer until either a decimal point, an exponential | |
107 ; indicator, or the value gets larger than 32 bits. If any of those eventualities happens, convert to floating point | |
108 ; and then continue parsing the number as floating point. The result will be stored to (Y). | |
109 val_parsenum lbeq SNERROR ; brif no numberr to parse | |
110 ldd zero ; zero out integer value accumulator | |
111 std fpa0extra | |
112 std fpa0extra+2 | |
113 std fpa0extra+4 | |
114 std fpa0extra+6 | |
115 sta fpa0extra12 ; zero out result sign to default positive | |
116 jsr curchar ; get current input character | |
117 bra val_parsenum1 ; parse flags | |
118 val_parsenum0 jsr nextchar ; get next input character | |
119 val_parsenum1 bcs val_parsenum5 ; brif digit | |
120 beq val_parsenum ; brif end of input | |
121 cmpa #'. ; decimal? | |
122 lbeq val_parsefloat ; switch to parsing floating point | |
123 cmpa #'- ; minus? | |
124 beq val_parsenum2 ; brif so | |
125 cmpa #tok_minus ; unary minus operator? | |
126 bne val_parsenum3 ; brif not | |
127 val_parsenum2 com fpa0extra12 ; invert current sign | |
128 bra val_parsenum0 ; go handle more stuff at the start of the number | |
129 val_parsenum3 cmpa #'+ ; unary +? | |
130 beq val_parsenum0 ; brif so - skip it | |
131 cmpa #tok_plus ; unary + operator? | |
132 beq val_parsenum0 ; brif so - skip it | |
133 val_parsenum4 lda fpa0extra4 ; is bit 7 of high byte set? | |
134 bpl val_parsenum4a ; brif not - no overflow | |
135 ldb fpa0extra12 ; do we want negative? | |
136 lbpl val_parsefloat ; brif not - we overflowed so convert to floating point | |
137 anda #0x7f ; lose sign bit then see if any other bits are set | |
138 ora fpa0extra5 | |
139 ora fpa0extra6 | |
140 ora fpa0extra7 | |
141 lbne val_parsefloat ; brif nonzero bits - too big for max negative 2's complement | |
142 val_parsenum4a lda fpa0extra12 ; do we want negative? | |
143 bpl val_parsenum4b ; brif not | |
144 ldd zero ; negate it | |
145 subd fpa0extra6 | |
146 std fpa0extra6 | |
147 ldd zero | |
148 sbcb fpa0extra5 | |
149 sbca fpa0extra4 | |
150 std fpa0extra4 | |
151 val_parsenum4b ldd fpa0extra6 ; copy value to result location | |
152 std val.int+2,y | |
153 ldd fpa0extra4 | |
154 std val.int,y | |
155 lda #valtype_int ; set value type to integer | |
156 sta val.type,y | |
157 rts | |
158 val_parsenum4c jsr nextchar ; fetch next character (after a digit) | |
159 bcs val_parsenum5 ; it's a digit | |
160 cmpa #'. ; decimal? | |
161 beq val_parsefloat ; brif so - handle floating point | |
162 cmpa #'E ; exponent? | |
163 beq val_parsefloat ; brif so - handle floating point | |
164 cmpa #'e ; exponent but lower case? | |
165 beq val_parsefloat ; brif so - handle floating point | |
166 bra val_parsenum4 ; unrecognized character - treat as end of number | |
167 val_parsenum5 suba #'0 ; offset digit to binary | |
168 pshs a ; save it for later addition | |
169 ldx fpa0extra4 ; save original value | |
170 stx fpa0extra8 | |
171 ldx fpa0extra6 | |
172 stx fpa0extra10 | |
173 lsl fpa0extra7 ; shift partial result left (times 2) | |
174 rol fpa0extra6 | |
175 rol fpa0extra5 | |
176 rol fpa0extra4 | |
177 rol fpa0extra3 | |
178 lsl fpa0extra7 ; shift partial result left (times 4) | |
179 rol fpa0extra6 | |
180 rol fpa0extra5 | |
181 rol fpa0extra4 | |
182 rol fpa0extra3 | |
183 ldd fpa0extra6 ; add in original value (time 5) | |
184 addd fpa0extra10 | |
185 std fpa0extra6 | |
186 ldd fpa0extra8 | |
187 adcb fpa0extra5 | |
188 adca fpa0extra4 | |
189 std fpa0extra4 | |
190 ldb fpa0extra3 | |
191 adcb #0 | |
192 stb fpa0extra3 | |
193 lsl fpa0extra7 ; shift partial result left (times 10) | |
194 rol fpa0extra6 | |
195 rol fpa0extra5 | |
196 rol fpa0extra4 | |
197 rol fpa0extra3 | |
198 ldd fpa0extra6 ; add in new digit | |
199 addb ,s+ | |
200 adca #0 | |
201 std fpa0extra6 | |
202 ldd fpa0extra4 ; and propagate carry | |
203 adcb #0 | |
204 adca #0 | |
205 std fpa0extra4 | |
206 ldb fpa0extra3 | |
207 adcb #0 | |
208 stb fpa0extra3 | |
209 beq val_parsenum4c ; go handle next digit if we didn't overflow past 32 bits | |
210 jsr nextchar ; eat the digit we just handled | |
211 val_parsefloat pshs y ; save destination pointer | |
212 lda #valtype_float ; set return type to floating point | |
213 sta val.type,y | |
214 ldx #fpa0extra ; point to integer accumulator | |
215 jsr fps_fromuint64 ; convert to floating point | |
216 clr fpa0extra11 ; zero out decimal counter | |
217 clr fpa0extra10 ; zero out decimal exponent counter | |
218 clr fpa0extra9 ; flag for decimal seen | |
219 jsr curchar ; fetch current character | |
220 bra val_parsefloat1 ; go handle character | |
221 val_parsefloat0 jsr nextchar ; fetch next character | |
222 val_parsefloat1 bcc val_parsefloat2 ; brif not digit | |
223 suba #'0 ; adjust digit to binary | |
224 sta fpa0extra3 ; save it for later (upper 3 bytes of 32 bit value already 0) | |
225 ldx ,s ; get destination value | |
226 jsr fps_mul10 ; do a quick multiply by 10 | |
227 ldx #fpa0extra ; convert digit to floating point | |
228 ldy #fpa1 | |
229 jsr fps_fromuint32 | |
230 ldu #fpa1 ; add digit to accumulated value | |
231 ldx ,s | |
232 leay ,x | |
233 jsr fps_add | |
234 lda fpa0extra11 ; update decimal counter | |
235 suba fpa0extra9 | |
236 sta fpa0extra11 | |
237 bra val_parsefloat0 ; go handle another digit | |
238 val_parsefloat2 cmpa #'. ; decimal? | |
239 bne val_parsefloat7 ; brif not | |
240 com fpa0extra9 ; flag for decimal | |
241 bne val_parsefloat0 ; brif not two decimals - keep parsing | |
242 val_parsefloat3 ldb fpa0extra10 ; fetch decimal exponent counter | |
243 subb fpa0extra11 ; subtract out decimal places provided | |
244 beq val_parsefloat6 ; brif no adjustment needed | |
245 stb fpa0extra9 ; save counter | |
246 bmi val_parsefloat5 ; brif negative exponent - need to do divisions | |
247 val_parsefloat4 ldx ,s ; point to destination value | |
248 jsr fps_mul10 ; multiply by 10 | |
249 dec fpa0extra9 ; done all of them? | |
250 bne val_parsefloat4 ; brif not | |
251 bra val_parsefloat6 | |
252 val_parsefloat5 ldx ,s ; point to destination value | |
253 jsr fps_div10 ; divide by 10 | |
254 inc fpa0extra9 ; done all of them? | |
255 bne val_parsefloat5 ; brif not | |
256 val_parsefloat6 puls y ; get back destination pointer | |
257 lda fpa0extra12 ; get desired sign | |
258 sta val.fpssign,y ; set in result | |
259 rts | |
260 val_parsefloat7 cmpa #'E ; decimal exponent? | |
261 beq val_parsefloat8 ; brif so | |
262 cmpa #'e ; decimal exponent, lower case edition? | |
263 bne val_parsefloat3 ; brif not - must be end of number | |
264 val_parsefloat8 clr fpa0extra9 ; set sign of exponent to positive | |
265 jsr nextchar ; fetch exponent character | |
266 bcs val_parsefloat11 ; brif digit | |
267 cmpa #'+ ; positive exponent? | |
268 beq val_parsefloat10 ; brif so - skip it | |
269 cmpa #tok_plus ; positive exponent, operator style? | |
270 beq val_parsefloat10 ; brif so - skip it | |
271 cmpa #'- ; negative exponent? | |
272 beq val_parsefloat9 ; brif so | |
273 cmpa #tok_minus ; negative exponent, operator style? | |
274 bne val_parsefloat3 ; brif not - must be end of exponent | |
275 val_parsefloat9 com fpa0extra9 ; set exponent to negative | |
276 val_parsefloat10 | |
277 jsr nextchar ; eat exponent sign | |
278 bcc val_parsefloat12 ; brif end of exponent - apply sign | |
279 val_parsefloat11 | |
280 suba #'0 ; binary-ize digit | |
281 sta fpa0extra8 ; save digit for later | |
282 lda #10 ; mutiply current decimal exponent by 10 | |
283 ldb fpa0extra10 ; get current exponent | |
284 mul | |
285 adca #0 ; set A if we overflowed *or* bit 7 of B is set | |
286 lbne OVERROR ; brif exponent overflow | |
287 addb fpa0extra8 ; add in digit | |
288 lbvs OVERROR ; brif exponent overflow | |
289 stb fpa0extra10 ; save new exponent | |
290 bra val_parsefloat10 ; go handle next exponent digit | |
291 val_parsefloat12 | |
292 ldb fpa0extra9 ; do we have a negative exponent? | |
293 beq val_parsefloat3 ; brif not, go adjust value by exponent and return | |
294 neg fpa0extra10 ; set base 10 exponent negative | |
295 bra val_parsefloat3 ; go adjust value by exponent and return | |
103 *pragmapop list | 296 *pragmapop list |