lib/parse: decimal ending with a whitespace are now valid

Also, make empty strings be parsed as invalid by parseDecimal.
This commit is contained in:
Virgil Dupras 2019-11-13 21:14:29 -05:00
parent 7274dccbe7
commit 8d46895dd3
6 changed files with 57 additions and 38 deletions

View File

@ -12,6 +12,7 @@
jp basStart
.inc "lib/util.asm"
.inc "lib/parse.asm"
.equ BAS_RAMSTART USER_RAMSTART
.inc "basic/main.asm"

View File

@ -1,6 +1,3 @@
; *** Requirements ***
; None
;
; *** Code ***
; Parse the decimal char at A and extract it's 0-9 numerical value. Put the
@ -15,31 +12,34 @@
; Parse string at (HL) as a decimal value and return value in IX under the
; same conditions as parseLiteral.
; Sets Z on success, unset on error.
; To parse successfully, all characters following HL must be digits and those
; digits must form a number that fits in 16 bits. To end the number, both \0
; and whitespaces (0x20 and 0x09) are accepted. There must be at least one
; digit in the string.
parseDecimal:
push hl
ld a, (hl)
ld a, (hl)
add a, 0xff-'9' ; maps '0'-'9' onto 0xf6-0xff
sub 0xff-9 ; maps to 0-9 and carries if not a digit
jr c, .error ; not a digit on first char? error
exx ; preserve bc, hl, de
ld h, 0
ld l, a ; load first digit in without multiplying
ld b, 3 ; Carries can only occur for decimals >=5 in length
jr c, .end
.loop:
exx
inc hl
ld a, (hl)
exx
; inline parseDecimalDigit
add a, 0xff-'9' ; maps '0'-'9' onto 0xf6-0xff
sub 0xff-9 ; maps to 0-9 and carries if not a digit
jr c, .end
add hl, hl ; x2
ld d, h
ld e, l ; de is x2
@ -74,4 +74,9 @@ parseDecimal:
push hl \ pop ix
exx ; restore original de and bc
pop hl
ret
ret z
; A is not 0? Ok, but if it's a space, we're happy too.
jp isSep
.error:
pop hl
jp unsetZ

View File

@ -1,3 +1,10 @@
; Sets Z is A is ' ' or '\t'
isSep:
cp ' '
ret z
cp 0x09
ret
; Copy string from (HL) in (DE), that is, copy bytes until a null char is
; encountered. The null char is also copied.
; HL and DE point to the char right after the null char.

View File

@ -195,6 +195,9 @@ parseNumberOrSymbol:
; matter that we didn't find our symbol. Return success anyhow.
; Otherwise return error. Z is already unset, so in fact, this is the
; same as jumping to zasmIsFirstPass
; however, before we do, load IX with zero. Returning dummy non-zero
; values can have weird consequence (such as false overflow errors).
ld ix, 0
jp zasmIsFirstPass
.returnPC:

View File

@ -29,13 +29,6 @@ isLineEnd:
cp '\'
ret
; Sets Z is A is ' ' '\t'
isSep:
cp ' '
ret z
cp 0x09
ret
; Sets Z is A is ' ', ',', ';', CR, LF, or null.
isSepOrLineEnd:
call isSep

View File

@ -100,29 +100,11 @@ testLiteral:
call nexttest
ret
; 2b int, 6b str, null-padded
tblDecimalValid:
.dw 99
.db "99", 0, 0, 0, 0
.dw 65535
.db "65535", 0
; 7b strings, null-padded
tblDecimalInvalid:
; TODO: make a null string parse as an invalid decimal
; null string is invalid
;.db 0, 0, 0, 0, 0, 0, 0
; too big, 5 chars
.db "65536", 0, 0
.db "99999", 0, 0
; too big, 6 chars with rightmost chars being within bound
.db "111111", 0
testDecimal:
; test valid cases. We loop through tblDecimalValid for our cases
ld b, 2
ld hl, tblDecimalValid
ld b, 5
ld hl, .valid
.loop1:
push hl ; --> lvl 1
@ -147,8 +129,8 @@ testDecimal:
call nexttest
; test invalid cases. We loop through tblDecimalInvalid for our cases
ld b, 3
ld hl, tblDecimalInvalid
ld b, 4
ld hl, .invalid
.loop2:
call parseDecimal
@ -159,6 +141,34 @@ testDecimal:
call nexttest
ret
; 2b int, 6b str, null-padded
.valid:
.dw 99
.db "99", 0, 0, 0, 0
.dw 65535
.db "65535", 0
; Space is also accepted as a number "ender"
.dw 42
.db "42 x", 0, 0
; Tab too
.dw 42
.db "42", 0x09, 'x', 0, 0
; A simple "0" works too!
.dw 0
.db '0', 0, 0, 0, 0, 0
; 7b strings, null-padded
.invalid:
; null string is invalid
.db 0, 0, 0, 0, 0, 0, 0
; too big, 5 chars
.db "65536", 0, 0
.db "99999", 0, 0
; too big, 6 chars with rightmost chars being within bound
.db "111111", 0
nexttest:
ld a, (testNum)
inc a