From d0f031939f918223a1b0b31a1885ec3a40789011 Mon Sep 17 00:00:00 2001 From: Virgil Dupras Date: Sun, 29 Dec 2019 19:47:19 -0500 Subject: [PATCH] lib/parse: make parseLiteral a little tighter Sub-parsers are seldom used by themselves, except for parseDecimal. I'm tightening the code of this unit for two reasons: 1. Optimization 2. Upcoming API change where HL won't be preserved anymore, but will point to char following the last parse char. This will allow us to simplify lib/expr. --- apps/README.md | 2 + apps/lib/parse.asm | 132 ++++++++++++++++++++------------------------- 2 files changed, 59 insertions(+), 75 deletions(-) diff --git a/apps/README.md b/apps/README.md index 6be1999..e227fca 100644 --- a/apps/README.md +++ b/apps/README.md @@ -74,6 +74,8 @@ There are decimal, hexadecimal and binary literals. A "straight" number is parsed as a decimal. Hexadecimal literals must be prefixed with `0x` (`0xf4`). Binary must be prefixed with `0b` (`0b01100110`). +A decimal literal cannot start with `0`, with the exception of the `0` literal. + Decimals and hexadecimal are "flexible". Whether they're written in a byte or a word, you don't need to prefix them with zeroes. Watch out for overflow, however. diff --git a/apps/lib/parse.asm b/apps/lib/parse.asm index 505cdb5..103c005 100644 --- a/apps/lib/parse.asm +++ b/apps/lib/parse.asm @@ -140,15 +140,11 @@ parseDecimal: pop hl ; <-- lvl 1, orig jp unsetZ -; Parse string at (HL) as a hexadecimal value and return value in DE under the -; same conditions as parseLiteral. +; Parse string at (HL) as a hexadecimal value without the "0x" prefix and +; return value in DE. +; Sets Z on success. parseHexadecimal: - call hasHexPrefix - ret nz push hl - ld d, 0 - inc hl ; get rid of "0x" - inc hl call strlen cp 3 jr c, .single @@ -182,29 +178,12 @@ parseHexadecimal: pop hl ret -; Sets Z if (HL) has a '0x' prefix. -hasHexPrefix: - ld a, (hl) - cp '0' - ret nz - push hl - inc hl - ld a, (hl) - cp 'x' - pop hl - ret - -; Parse string at (HL) as a binary value (0b010101) and return value in E. -; D is always zero. +; Parse string at (HL) as a binary value (010101) without the "0b" prefix and +; return value in E. D is always zero. ; Sets Z on success. parseBinaryLiteral: - call hasBinPrefix - ret nz push bc push hl - ld d, 0 - inc hl ; get rid of "0b" - inc hl call strlen or a jr z, .error ; empty, error @@ -237,49 +216,6 @@ parseBinaryLiteral: pop bc ret -; Sets Z if (HL) has a '0b' prefix. -hasBinPrefix: - ld a, (hl) - cp '0' - ret nz - push hl - inc hl - ld a, (hl) - cp 'b' - pop hl - ret - -; Parse string at (HL) and, if it is a char literal, sets Z and return -; corresponding value in E. D is always zero. -; -; A valid char literal starts with ', ends with ' and has one character in the -; middle. No escape sequence are accepted, but ''' will return the apostrophe -; character. -parseCharLiteral: - ld a, 0x27 ; apostrophe (') char - cp (hl) - ret nz - - push hl - inc hl - inc hl - cp (hl) - jr nz, .end ; not ending with an apostrophe - inc hl - ld a, (hl) - or a ; cp 0 - jr nz, .end ; string has to end there - ; Valid char, good - ld d, a ; A is zero, take advantage of that - dec hl - dec hl - ld a, (hl) - ld e, a - cp a ; ensure Z -.end: - pop hl - ret - ; Parses the string at (HL) and returns the 16-bit value in DE. The string ; can be a decimal literal (1234), a hexadecimal literal (0x1234) or a char ; literal ('X'). @@ -287,11 +223,57 @@ parseCharLiteral: ; As soon as the number doesn't fit 16-bit any more, parsing stops and the ; number is invalid. If the number is valid, Z is set, otherwise, unset. parseLiteral: - call parseCharLiteral - ret z - call parseHexadecimal - ret z - call parseBinaryLiteral - ret z + ld de, 0 ; pre-fill + ld a, (hl) + cp 0x27 ; apostrophe + jr z, .char + cp '0' + jr z, .hexOrBin jp parseDecimal +; Parse string at (HL) and, if it is a char literal, sets Z and return +; corresponding value in E. D is always zero. +; +; A valid char literal starts with ', ends with ' and has one character in the +; middle. No escape sequence are accepted, but ''' will return the apostrophe +; character. +.char: + push hl + inc hl + inc hl + cp (hl) + jr nz, .charEnd ; not ending with an apostrophe + inc hl + ld a, (hl) + or a ; cp 0 + jr nz, .charEnd ; string has to end there + ; Valid char, good + dec hl + dec hl + ld e, (hl) + cp a ; ensure Z +.charEnd: + pop hl + ret + +.hexOrBin: + inc hl + ld a, (hl) + inc hl ; already place it for hex or bin + cp 'x' + jr z, .hex + cp 'b' + jr z, .bin + ; special case: single '0'. set Z if we hit have null terminating. + or a +.hexOrBinEnd: + dec hl \ dec hl ; replace HL + ret ; Z already set + +.hex: + call parseHexadecimal + jr .hexOrBinEnd + +.bin: + call parseBinaryLiteral + jr .hexOrBinEnd