001   0000             ; MSX BASIC JSON Parser

002   0000             ; by Ricardo Bittencourt 2017

003   0000             

004   0000                     output  json.bin

005   0000             

006   0000                     org     0D000h - 7

007   CFF9             

008   CFF9             ; ----------------------------------------------------------------

009   CFF9             ; MSX bios

010   CFF9             

011   CFF9             usrtab          equ     0F39Ah  ; Callbacks for USR functions

012   CFF9             valtyp          equ     0F663h  ; Type of argument in DAC

013   CFF9             dac             equ     0F7F6h  ; Accumulator for MSX BASIC

014   CFF9             dsctmp          equ     0F698h  ; Temporary string descriptor

015   CFF9             type_mismatch   equ     0406Dh  ; Type mismatch error handler

016   CFF9             error_handler   equ     0406Fh  ; Generic BASIC error handler

017   CFF9             illegal_fcall   equ     00005h  ; Error code for Illegal function call

018   CFF9             

019   CFF9             ; ----------------------------------------------------------------

020   CFF9             ; BIN header

021   CFF9             

022   CFF9 FE                  db      0FEh

023   CFFA 00 D0               dw      start_bin

024   CFFC F8 D2               dw      end_bin - 1

025   CFFE 00 D0               dw      start_bin

026   D000             

027   D000             ; ----------------------------------------------------------------

028   D000             ; Initialization.

029   D000             

030   D000             start_bin: 

031   D000 21 11 D0            ld      hl, set_json_start

032   D003 22 9A F3            ld      (usrtab + 0), hl

033   D006 21 2F D0            ld      hl, get_json_type

034   D009 22 9C F3            ld      (usrtab + 2), hl

035   D00C 23                  inc     hl

036   D00D 22 9E F3            ld      (usrtab + 4), hl

037   D010 C9                  ret

038   D011             

039   D011                     assert (get_json_type == get_json_value + 1)

040   D011             

041   D011             ; ----------------------------------------------------------------

042   D011             ; Set json start

043   D011             

044   D011             set_json_start: 

045   D011                     ; Check for integer argument

046   D011 3A 63 F6            ld      a, (valtyp)

047   D014 FE 02               cp      2

048   D016 C2 6D 40            jp      nz, type_mismatch

049   D019                     ; Set json start

050   D019 2A F8 F7            ld      hl, (dac + 2)

051   D01C 22 F3 D2            ld      (json_start), hl

052   D01F                     ; Check for valid json.

053   D01F CD CD D1            call    check_json

054   D022                     ; Return 0=error, -1=success

055   D022 3F                  ccf

056   D023 ED 62               sbc     hl, hl

057   D025 38 03               jr      c, return_integer

058   D027 22 F3 D2            ld      (json_start), hl

059   D02A             return_integer: 

060   D02A 22 F8 F7            ld      (dac + 2), hl

061   D02D C9                  ret

062   D02E             

063   D02E             ; ----------------------------------------------------------------

064   D02E             ; Get json token type

065   D02E             

066   D02E             get_json_value: 

067   D02E                     ; Alternate entry point, set token type as non-zero.

068   D02E 3E                  db      03Eh

069   D02F             get_json_type: 

070   D02F                     ; Set token type as zero.

071   D02F AF                  xor     a

072   D030             get_json_action: 

073   D030 32 F8 D2            ld      (get_action), a

074   D033                     ; Check for string argument

075   D033 3A 63 F6            ld      a, (valtyp)

076   D036 FE 03               cp      3

077   D038 C2 6D 40            jp      nz, type_mismatch

078   D03B                     ; Check if json start was set

079   D03B 2A F3 D2            ld      hl, (json_start)

080   D03E 7C                  ld      a, h

081   D03F B5                  or      l

082   D040 28 6A               jr      z, ifc_error

083   D042                     ; Save sentinel

084   D042 E5                  push    hl

085   D043 DD 2A F8 F7         ld      ix, (dac + 2)

086   D047 DD 4E 00            ld      c, (ix)

087   D04A DD 6E 01            ld      l, (ix + 1)

088   D04D DD 66 02            ld      h, (ix + 2)

089   D050 54                  ld      d, h

090   D051 5D                  ld      e, l

091   D052 06 00               ld      b, 0

092   D054 09                  add     hl, bc

093   D055 7E                  ld      a, (hl)

094   D056 22 F6 D2            ld      (sentinel_pos), hl

095   D059 32 F5 D2            ld      (sentinel), a

096   D05C 70                  ld      (hl), b

097   D05D                     ; Start parsing

098   D05D D9                  exx

099   D05E E1                  pop     hl

100   D05F D9                  exx

101   D060 EB                  ex      de, hl

102   D061 CD 94 D0            call    parse_token_main

103   D064 47                  ld      b, a

104   D065                     ; Restore sentinel

105   D065 2A F6 D2            ld      hl, (sentinel_pos)

106   D068 3A F5 D2            ld      a, (sentinel)

107   D06B 77                  ld      (hl), a

108   D06C                     ; Check for error

109   D06C CB 78               bit     7, b

110   D06E 20 3C               jr      nz, ifc_error

111   D070                     ; Check for string action

112   D070 3A F8 D2            ld      a, (get_action)

113   D073 B7                  or      a

114   D074 3E 02               ld      a, 2

115   D076 20 08               jr      nz, get_string

116   D078                     ; Return an integer

117   D078 26 00               ld      h, 0

118   D07A 68                  ld      l, b

119   D07B             return_valtyp: 

120   D07B 32 63 F6            ld      (valtyp), a

121   D07E 18 AA               jr      return_integer

122   D080             

123   D080             ; ----------------------------------------------------------------

124   D080             ; Get json value as a string

125   D080             

126   D080             get_string: 

127   D080                     ; Return a string

128   D080 B8                  cp      b

129   D081 30 29               jr      nc, ifc_error

130   D083 3C                  inc     a

131   D084 21 98 F6            ld      hl, dsctmp

132   D087 18 F2               jr      return_valtyp

133   D089             

134   D089             ; ----------------------------------------------------------------

135   D089             

136   D089             parse_end_collection: 

137   D089 23                  inc     hl

138   D08A D9                  exx

139   D08B 7B                  ld      a, e

140   D08C B2                  or      d

141   D08D 1B                  dec     de

142   D08E C2 B9 D1            jp      nz, skip_whitespace_exx

143   D091 C1                  pop     bc

144   D092 D9                  exx

145   D093                     ; Fall through to parse_token_main_exx

146   D093             

147   D093             ; ----------------------------------------------------------------

148   D093             

149   D093             parse_token_main_exx: 

150   D093 D9                  exx

151   D094             parse_token_main: 

152   D094 CD BA D1            call    skip_whitespace

153   D097 B7                  or      a

154   D098 23                  inc     hl

155   D099 28 16               jr      z, parse_identify

156   D09B FE 23               cp      '#'

157   D09D 28 39               jr      z, parse_position

158   D09F FE 24               cp      '$'

159   D0A1 CA 33 D1            jp      z, parse_value

160   D0A4 FE 26               cp      '&'

161   D0A6 CA 3E D1            jp      z, parse_key

162   D0A9             parse_return_error: 

163   D0A9 3E FF               ld      a, 255

164   D0AB C9                  ret

165   D0AC             ifc_error: 

166   D0AC 1E 05               ld      e, illegal_fcall

167   D0AE C3 6F 40            jp      error_handler

168   D0B1             

169   D0B1             ; ----------------------------------------------------------------

170   D0B1             

171   D0B1             parse_identify: 

172   D0B1 D9                  exx

173   D0B2 3A F8 D2            ld      a, (get_action)

174   D0B5 B7                  or      a

175   D0B6 C2 87 D1            jp      nz, parse_string

176   D0B9 CD BA D1            call    skip_whitespace

177   D0BC 01 01 07            ld      bc, 7 * 256 + 1

178   D0BF 11 D7 D2            ld      de, identifiers

179   D0C2 EB                  ex      de, hl

180   D0C3             1: 

181   D0C3 BE                  cp      (hl)

182   D0C4 28 0F               jr      z, 2f

183   D0C6 0C                  inc     c

184   D0C7 23                  inc     hl

185   D0C8 10 F9               djnz    1b

186   D0CA EB                  ex      de, hl

187   D0CB E5                  push    hl

188   D0CC CD 28 D2            call    check_number

189   D0CF E1                  pop     hl

190   D0D0 3F                  ccf

191   D0D1 9F                  sbc     a, a

192   D0D2 E6 04               and     4

193   D0D4 C9                  ret

194   D0D5             2: 

195   D0D5 EB                  ex      de, hl

196   D0D6 79                  ld      a, c

197   D0D7 C9                  ret

198   D0D8             

199   D0D8             ; ----------------------------------------------------------------

200   D0D8             

201   D0D8             parse_position: 

202   D0D8 11 00 00            ld      de, 0

203   D0DB CD BA D1            call    skip_whitespace

204   D0DE CD CF D2            call    check_digit

205   D0E1 30 C6               jr      nc, parse_return_error

206   D0E3             1: 

207   D0E3 CD CF D2            call    check_digit

208   D0E6 30 11               jr      nc, parse_fetch

209   D0E8 D6 30               sub     '0'

210   D0EA 4B                  ld      c, e

211   D0EB 42                  ld      b, d

212   D0EC EB                  ex      de, hl

213   D0ED 29                  add     hl, hl

214   D0EE 29                  add     hl, hl

215   D0EF 09                  add     hl, bc

216   D0F0 29                  add     hl, hl

217   D0F1 4F                  ld      c, a

218   D0F2 06 00               ld      b, 0

219   D0F4 09                  add     hl, bc

220   D0F5 EB                  ex      de, hl

221   D0F6 23                  inc     hl

222   D0F7 18 EA               jr      1b

223   D0F9             

224   D0F9             ; ----------------------------------------------------------------

225   D0F9             

226   D0F9             parse_fetch: 

227   D0F9 CD B9 D1            call    skip_whitespace_exx

228   D0FC FE 7B               cp      '{'

229   D0FE 28 19               jr      z, parse_object

230   D100 FE 5B               cp      '['

231   D102 20 A5               jr      nz, parse_return_error

232   D104             1: 

233   D104 CD 89 D0            call    parse_end_collection

234   D107 CD 06 D2            call    check_anything

235   D10A 38 0B               jr      c, parse_fail

236   D10C CD BA D1            call    skip_whitespace

237   D10F FE 5D               cp      ']'

238   D111 28 04               jr      z, parse_fail

239   D113 FE 2C               cp      ','

240   D115 28 ED               jr      z, 1b

241   D117             parse_fail: 

242   D117 AF                  xor     a

243   D118 C9                  ret

244   D119             

245   D119             ; ----------------------------------------------------------------

246   D119             

247   D119             parse_object: 

248   D119 CD 89 D0            call    parse_end_collection

249   D11C CD 21 D1            call    parse_next_item

250   D11F 18 F8               jr      parse_object

251   D121             

252   D121             ; ----------------------------------------------------------------

253   D121             

254   D121             parse_next_item: 

255   D121 CD 02 D2            call    check_key_value

256   D124 38 0A               jr      c, parse_not_found

257   D126 CD BA D1            call    skip_whitespace

258   D129 FE 7D               cp      '}'

259   D12B 28 03               jr      z, parse_not_found

260   D12D FE 2C               cp      ','

261   D12F C8                  ret     z

262   D130             parse_not_found: 

263   D130 E1                  pop     hl

264   D131 AF                  xor     a

265   D132 C9                  ret

266   D133             

267   D133             ; ----------------------------------------------------------------

268   D133             

269   D133             compare_fail    equ     parse_not_found

270   D133             

271   D133             ; ----------------------------------------------------------------

272   D133             

273   D133             parse_value: 

274   D133 CD B9 D1            call    skip_whitespace_exx

275   D136 CD F4 D1            call    check_key

276   D139 38 DC               jr      c, parse_fail

277   D13B C3 93 D0            jp      parse_token_main_exx

278   D13E             

279   D13E             ; ----------------------------------------------------------------

280   D13E             

281   D13E             parse_key: 

282   D13E CD B9 D1            call    skip_whitespace_exx

283   D141 FE 7B               cp      '{'

284   D143 C2 93 D0            jp      nz, parse_token_main_exx

285   D146 CD CA D1            call    skip_whitespace_next

286   D149 D9                  exx

287   D14A             1: 

288   D14A CD 59 D1            call    compare_key

289   D14D 38 E4               jr      c, parse_value

290   D14F CD B9 D1            call    skip_whitespace_exx

291   D152 CD 21 D1            call    parse_next_item

292   D155 23                  inc     hl

293   D156 D9                  exx

294   D157 18 F1               jr      1b

295   D159             

296   D159             ; ----------------------------------------------------------------

297   D159             

298   D159             compare_key: 

299   D159                     ; Returns CF=key found, NC=key not found

300   D159 E5                  push    hl

301   D15A CD B9 D1            call    skip_whitespace_exx

302   D15D E5                  push    hl

303   D15E D9                  exx

304   D15F D1                  pop     de

305   D160 1A                  ld      a, (de)

306   D161 FE 22               cp      '"'

307   D163 20 CB               jr      nz, compare_fail

308   D165 13                  inc     de

309   D166             1: 

310   D166 7E                  ld      a, (hl)

311   D167 B7                  or      a

312   D168 28 15               jr      z, 2f

313   D16A FE 23               cp      '#'

314   D16C 28 11               jr      z, 2f

315   D16E FE 26               cp      '&'

316   D170 28 0D               jr      z, 2f

317   D172 FE 24               cp      '$'

318   D174 28 09               jr      z, 2f

319   D176 EB                  ex      de, hl

320   D177 BE                  cp      (hl)

321   D178 EB                  ex      de, hl

322   D179 20 B5               jr      nz, compare_fail

323   D17B 23                  inc     hl

324   D17C 13                  inc     de

325   D17D 18 E7               jr      1b

326   D17F             2: 

327   D17F 1A                  ld      a, (de)

328   D180 FE 22               cp      '"'

329   D182 20 AC               jr      nz, compare_fail

330   D184 C1                  pop     bc

331   D185             compare_success: 

332   D185 37                  scf

333   D186 C9                  ret

334   D187             

335   D187             ; ----------------------------------------------------------------

336   D187             

337   D187             json_error      equ     compare_success

338   D187             

339   D187             ; ----------------------------------------------------------------

340   D187             

341   D187             parse_string: 

342   D187 CD BA D1            call    skip_whitespace

343   D18A FE 7B               cp      '{'

344   D18C CA 17 D1            jp      z, parse_fail

345   D18F FE 5B               cp      '['

346   D191 CA 17 D1            jp      z, parse_fail

347   D194 FE 22               cp      '"'

348   D196 28 16               jr      z, parse_string_literal

349   D198 22 99 F6            ld      (dsctmp + 1), hl

350   D19B E5                  push    hl

351   D19C CD 06 D2            call    check_anything

352   D19F             parse_string_common: 

353   D19F B7                  or      a

354   D1A0 D1                  pop     de

355   D1A1 ED 52               sbc     hl, de

356   D1A3 7C                  ld      a, h

357   D1A4 C6 FF               add     a, 255

358   D1A6 9F                  sbc     a, a

359   D1A7 B5                  or      l

360   D1A8 32 98 F6            ld      (dsctmp), a

361   D1AB 3E 03               ld      a, 3

362   D1AD C9                  ret

363   D1AE             

364   D1AE             ; ----------------------------------------------------------------

365   D1AE             

366   D1AE             parse_string_literal: 

367   D1AE 23                  inc     hl

368   D1AF 22 99 F6            ld      (dsctmp + 1), hl

369   D1B2 E5                  push    hl

370   D1B3 CD 97 D2            call    check_contents_no_inc

371   D1B6 2B                  dec     hl

372   D1B7 18 E6               jr      parse_string_common

373   D1B9             

374   D1B9             ; ----------------------------------------------------------------

375   D1B9             

376   D1B9             skip_whitespace_exx: 

377   D1B9 D9                  exx

378   D1BA             skip_whitespace: 

379   D1BA 7E                  ld      a, (hl)

380   D1BB FE 20               cp      32

381   D1BD 28 0B               jr      z, skip_whitespace_next

382   D1BF FE 0A               cp      10

383   D1C1 28 07               jr      z, skip_whitespace_next

384   D1C3 FE 0D               cp      13

385   D1C5 28 03               jr      z, skip_whitespace_next

386   D1C7 FE 09               cp      9

387   D1C9 C0                  ret     nz

388   D1CA             skip_whitespace_next: 

389   D1CA 23                  inc     hl

390   D1CB 18 ED               jr      skip_whitespace

391   D1CD             

392   D1CD             ; ----------------------------------------------------------------

393   D1CD             

394   D1CD             check_json: 

395   D1CD CD BA D1            call    skip_whitespace

396   D1D0 FE 5B               cp      '['

397   D1D2 CA 73 D2            jp      z, check_array

398   D1D5 FE 7B               cp      '{'

399   D1D7 20 AC               jr      nz, json_error

400   D1D9                     ; Fall through to check_object

401   D1D9             

402   D1D9             ; ----------------------------------------------------------------

403   D1D9             

404   D1D9             check_object: 

405   D1D9                     ; HL must be pointing to '{'

406   D1D9 CD CA D1            call    skip_whitespace_next

407   D1DC FE 7D               cp      '}'

408   D1DE 28 20               jr      z, check_success

409   D1E0             check_object_key: 

410   D1E0 CD 02 D2            call    check_key_value

411   D1E3 D8                  ret     c

412   D1E4 CD BA D1            call    skip_whitespace

413   D1E7 FE 7D               cp      '}'

414   D1E9 28 15               jr      z, check_success

415   D1EB FE 2C               cp      ','

416   D1ED 20 96               jr      nz, json_error

417   D1EF CD CA D1            call    skip_whitespace_next

418   D1F2 18 EC               jr      check_object_key

419   D1F4             

420   D1F4             ; ----------------------------------------------------------------

421   D1F4             

422   D1F4             check_key: 

423   D1F4 CD 91 D2            call    check_string

424   D1F7 D8                  ret     c

425   D1F8 CD BA D1            call    skip_whitespace

426   D1FB FE 3A               cp      ':'

427   D1FD 28 01               jr      z, check_success

428   D1FF 37                  scf

429   D200             check_success: 

430   D200 23                  inc     hl

431   D201 C9                  ret

432   D202             

433   D202             ; ----------------------------------------------------------------

434   D202             

435   D202             check_key_value: 

436   D202 CD F4 D1            call    check_key

437   D205 D8                  ret     c

438   D206                     ; Fall through to check_anything

439   D206             

440   D206             ; ----------------------------------------------------------------

441   D206             

442   D206             check_anything: 

443   D206 CD BA D1            call    skip_whitespace

444   D209 FE 7B               cp      '{'

445   D20B 28 CC               jr      z, check_object

446   D20D FE 5B               cp      '['

447   D20F 28 62               jr      z, check_array

448   D211 FE 22               cp      '"'

449   D213 CA 91 D2            jp      z, check_string

450   D216 FE 74               cp      't'

451   D218 11 E3 D2            ld      de, token_true

452   D21B 28 4B               jr      z, check_string_literal

453   D21D FE 66               cp      'f'

454   D21F 11 E8 D2            ld      de, token_false

455   D222 28 44               jr      z, check_string_literal

456   D224 FE 6E               cp      'n'

457   D226 28 3D               jr      z, check_null

458   D228                     ; Fall through to check_number

459   D228             

460   D228             ; ----------------------------------------------------------------

461   D228             

462   D228             check_number: 

463   D228 FE 2D               cp      '-'

464   D22A 20 02               jr      nz, 2f

465   D22C 23                  inc     hl

466   D22D 7E                  ld      a, (hl)

467   D22E             2: 

468   D22E FE 30               cp      '0'

469   D230 20 04               jr      nz, 3f

470   D232 23                  inc     hl

471   D233 7E                  ld      a, (hl)

472   D234 18 04               jr      check_fraction

473   D236             3: 

474   D236 CD 58 D2            call    check_digit_sequence

475   D239 D8                  ret     c

476   D23A                     ; Fall through to check_fraction

477   D23A             

478   D23A             ; ----------------------------------------------------------------

479   D23A             

480   D23A             check_fraction: 

481   D23A FE 2E               cp      '.'

482   D23C 20 05               jr      nz, check_scientific

483   D23E 23                  inc     hl

484   D23F CD 58 D2            call    check_digit_sequence

485   D242 D8                  ret     c

486   D243                     ; Fall through to check_scientific

487   D243             

488   D243             ; ----------------------------------------------------------------

489   D243             

490   D243             check_scientific: 

491   D243 F6 20               or      32

492   D245 FE 65               cp      'e'

493   D247 28 02               jr      z, 1f

494   D249 B7                  or      a

495   D24A C9                  ret

496   D24B             1: 

497   D24B 23                  inc     hl

498   D24C 7E                  ld      a, (hl)

499   D24D FE 2B               cp      '+'

500   D24F 20 02               jr      nz, 2f

501   D251 EE 06               xor     6

502   D253             2: 

503   D253 FE 2D               cp      '-'

504   D255 20 01               jr      nz, check_digit_sequence

505   D257 23                  inc     hl

506   D258                     ; Fall through to check_digit_sequence

507   D258             

508   D258             ; ----------------------------------------------------------------

509   D258             

510   D258             check_digit_sequence: 

511   D258                     ; Returns CF=not a digit sequence, NC=digit sequence

512   D258 CD CF D2            call    check_digit

513   D25B D2 85 D1            jp      nc, json_error

514   D25E             1: 

515   D25E 23                  inc     hl

516   D25F CD CF D2            call    check_digit

517   D262 38 FA               jr      c, 1b

518   D264 C9                  ret

519   D265             

520   D265             ; ----------------------------------------------------------------

521   D265             

522   D265             check_null: 

523   D265 11 EE D2            ld      de, token_null

524   D268             check_string_literal: 

525   D268 1A                  ld      a, (de)

526   D269 B7                  or      a

527   D26A C8                  ret     z

528   D26B BE                  cp      (hl)

529   D26C C2 85 D1            jp      nz, json_error

530   D26F 23                  inc     hl

531   D270 13                  inc     de

532   D271 18 F5               jr      check_string_literal

533   D273             

534   D273             ; ----------------------------------------------------------------

535   D273             

536   D273             check_array: 

537   D273                     ; HL must be pointing to '['

538   D273 CD CA D1            call    skip_whitespace_next

539   D276 FE 5D               cp      ']'

540   D278 CA 00 D2            jp      z, check_success

541   D27B             check_array_next: 

542   D27B CD 06 D2            call    check_anything

543   D27E D8                  ret     c

544   D27F CD BA D1            call    skip_whitespace

545   D282 FE 5D               cp      ']'

546   D284 CA 00 D2            jp      z, check_success

547   D287 FE 2C               cp      ','

548   D289 C2 85 D1            jp      nz, json_error

549   D28C CD CA D1            call    skip_whitespace_next

550   D28F 18 EA               jr      check_array_next

551   D291             

552   D291             ; ----------------------------------------------------------------

553   D291             

554   D291             check_string: 

555   D291 FE 22               cp      '"'

556   D293 C2 85 D1            jp      nz, json_error

557   D296                     ; Fall through to check_contents

558   D296             

559   D296             ; ----------------------------------------------------------------

560   D296             

561   D296             check_contents: 

562   D296 23                  inc     hl

563   D297             check_contents_no_inc: 

564   D297 7E                  ld      a, (hl)

565   D298 FE 22               cp      '"'

566   D29A CA 00 D2            jp      z, check_success

567   D29D FE 5C               cp      '\\'

568   D29F 28 02               jr      z, check_escape

569   D2A1 18 F3               jr      check_contents

570   D2A3             

571   D2A3             ; ----------------------------------------------------------------

572   D2A3             

573   D2A3             check_escape: 

574   D2A3 23                  inc     hl

575   D2A4 7E                  ld      a, (hl)

576   D2A5 EB                  ex      de, hl

577   D2A6 01 08 00            ld      bc, 8

578   D2A9 21 DB D2            ld      hl, string_escapes

579   D2AC ED B1               cpir

580   D2AE EB                  ex      de, hl

581   D2AF 28 E5               jr      z, check_contents

582   D2B1 FE 75               cp      'u'

583   D2B3 C2 85 D1            jp      nz, json_error

584   D2B6 06 04               ld      b, 4

585   D2B8             1: 

586   D2B8 23                  inc     hl

587   D2B9 CD C3 D2            call    check_hex_digit

588   D2BC D2 85 D1            jp      nc, json_error

589   D2BF 10 F7               djnz    1b

590   D2C1 18 D3               jr      check_contents

591   D2C3             

592   D2C3             ; ----------------------------------------------------------------

593   D2C3             

594   D2C3             check_hex_digit: 

595   D2C3 CD CF D2            call    check_digit

596   D2C6 D8                  ret     c

597   D2C7 F6 20               or      32

598   D2C9                     ; Fall through to check_hex_lower

599   D2C9             

600   D2C9             check_hex_lower: 

601   D2C9                     ; Returns CF=digit, NC=non-digit

602   D2C9 FE 67               cp      'f' + 1

603   D2CB D0                  ret     nc

604   D2CC C6 9F               add     a, 256 - 'a'

605   D2CE C9                  ret

606   D2CF             

607   D2CF             check_digit: 

608   D2CF 7E                  ld      a, (hl)

609   D2D0                     ; Returns CF=digit, NC=non-digit

610   D2D0 FE 3A               cp      '9' + 1

611   D2D2 D0                  ret     nc

612   D2D3 FE 30               cp      '0'

613   D2D5 3F                  ccf

614   D2D6 C9                  ret

615   D2D7             

616   D2D7             ; ----------------------------------------------------------------

617   D2D7             ; Constants

618   D2D7             

619   D2D7             identifiers:     db      '{["0tfn'

619   D2D7 7B5B223074666E

620   D2DE 225C2F6272  escapes_cont:    db      '"\/br'

621   D2E3 7472756500  token_true:      db      'true', 0

622   D2E8             token_false:     db      'false', 0

622   D2E8 66616C736500

623   D2EE 6E756C6C00  token_null:      db      'null', 0

624   D2F3             string_escapes  equ     escapes_cont - 3

625   D2F3             

626   D2F3             ; ----------------------------------------------------------------

627   D2F3             ; Variables

628   D2F3             

629   D2F3 00 00       json_start:      dw      0

630   D2F5 00          sentinel:        db      0

631   D2F6 00 00       sentinel_pos:    dw      0

632   D2F8 00          get_action:      db      0

633   D2F9             

634   D2F9             ; ----------------------------------------------------------------

635   D2F9             

636   D2F9             end_bin: 

637   D2F9             

638   D2F9                     end

639   D2F9             

640   D2F9