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.
This commit is contained in:
parent
15628da7de
commit
d0f031939f
@ -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.
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user