mirror of
https://github.com/hsoft/collapseos.git
synced 2024-11-27 12:18:07 +11:00
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:
parent
7274dccbe7
commit
8d46895dd3
@ -12,6 +12,7 @@
|
|||||||
|
|
||||||
jp basStart
|
jp basStart
|
||||||
|
|
||||||
|
.inc "lib/util.asm"
|
||||||
.inc "lib/parse.asm"
|
.inc "lib/parse.asm"
|
||||||
.equ BAS_RAMSTART USER_RAMSTART
|
.equ BAS_RAMSTART USER_RAMSTART
|
||||||
.inc "basic/main.asm"
|
.inc "basic/main.asm"
|
||||||
|
@ -1,6 +1,3 @@
|
|||||||
; *** Requirements ***
|
|
||||||
; None
|
|
||||||
;
|
|
||||||
; *** Code ***
|
; *** Code ***
|
||||||
|
|
||||||
; Parse the decimal char at A and extract it's 0-9 numerical value. Put the
|
; 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
|
; Parse string at (HL) as a decimal value and return value in IX under the
|
||||||
; same conditions as parseLiteral.
|
; same conditions as parseLiteral.
|
||||||
; Sets Z on success, unset on error.
|
; 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:
|
parseDecimal:
|
||||||
push hl
|
push hl
|
||||||
|
|
||||||
ld a, (hl)
|
ld a, (hl)
|
||||||
add a, 0xff-'9' ; maps '0'-'9' onto 0xf6-0xff
|
add a, 0xff-'9' ; maps '0'-'9' onto 0xf6-0xff
|
||||||
sub 0xff-9 ; maps to 0-9 and carries if not a digit
|
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
|
exx ; preserve bc, hl, de
|
||||||
ld h, 0
|
ld h, 0
|
||||||
ld l, a ; load first digit in without multiplying
|
ld l, a ; load first digit in without multiplying
|
||||||
ld b, 3 ; Carries can only occur for decimals >=5 in length
|
ld b, 3 ; Carries can only occur for decimals >=5 in length
|
||||||
jr c, .end
|
|
||||||
|
|
||||||
.loop:
|
.loop:
|
||||||
exx
|
exx
|
||||||
inc hl
|
inc hl
|
||||||
ld a, (hl)
|
ld a, (hl)
|
||||||
exx
|
exx
|
||||||
|
|
||||||
; inline parseDecimalDigit
|
; inline parseDecimalDigit
|
||||||
add a, 0xff-'9' ; maps '0'-'9' onto 0xf6-0xff
|
add a, 0xff-'9' ; maps '0'-'9' onto 0xf6-0xff
|
||||||
sub 0xff-9 ; maps to 0-9 and carries if not a digit
|
sub 0xff-9 ; maps to 0-9 and carries if not a digit
|
||||||
|
|
||||||
jr c, .end
|
jr c, .end
|
||||||
|
|
||||||
add hl, hl ; x2
|
add hl, hl ; x2
|
||||||
ld d, h
|
ld d, h
|
||||||
ld e, l ; de is x2
|
ld e, l ; de is x2
|
||||||
@ -74,4 +74,9 @@ parseDecimal:
|
|||||||
push hl \ pop ix
|
push hl \ pop ix
|
||||||
exx ; restore original de and bc
|
exx ; restore original de and bc
|
||||||
pop hl
|
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
|
||||||
|
@ -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
|
; Copy string from (HL) in (DE), that is, copy bytes until a null char is
|
||||||
; encountered. The null char is also copied.
|
; encountered. The null char is also copied.
|
||||||
; HL and DE point to the char right after the null char.
|
; HL and DE point to the char right after the null char.
|
||||||
|
@ -195,6 +195,9 @@ parseNumberOrSymbol:
|
|||||||
; matter that we didn't find our symbol. Return success anyhow.
|
; matter that we didn't find our symbol. Return success anyhow.
|
||||||
; Otherwise return error. Z is already unset, so in fact, this is the
|
; Otherwise return error. Z is already unset, so in fact, this is the
|
||||||
; same as jumping to zasmIsFirstPass
|
; 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
|
jp zasmIsFirstPass
|
||||||
|
|
||||||
.returnPC:
|
.returnPC:
|
||||||
|
@ -29,13 +29,6 @@ isLineEnd:
|
|||||||
cp '\'
|
cp '\'
|
||||||
ret
|
ret
|
||||||
|
|
||||||
; Sets Z is A is ' ' '\t'
|
|
||||||
isSep:
|
|
||||||
cp ' '
|
|
||||||
ret z
|
|
||||||
cp 0x09
|
|
||||||
ret
|
|
||||||
|
|
||||||
; Sets Z is A is ' ', ',', ';', CR, LF, or null.
|
; Sets Z is A is ' ', ',', ';', CR, LF, or null.
|
||||||
isSepOrLineEnd:
|
isSepOrLineEnd:
|
||||||
call isSep
|
call isSep
|
||||||
|
@ -100,29 +100,11 @@ testLiteral:
|
|||||||
call nexttest
|
call nexttest
|
||||||
ret
|
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:
|
testDecimal:
|
||||||
|
|
||||||
; test valid cases. We loop through tblDecimalValid for our cases
|
; test valid cases. We loop through tblDecimalValid for our cases
|
||||||
ld b, 2
|
ld b, 5
|
||||||
ld hl, tblDecimalValid
|
ld hl, .valid
|
||||||
|
|
||||||
.loop1:
|
.loop1:
|
||||||
push hl ; --> lvl 1
|
push hl ; --> lvl 1
|
||||||
@ -147,8 +129,8 @@ testDecimal:
|
|||||||
call nexttest
|
call nexttest
|
||||||
|
|
||||||
; test invalid cases. We loop through tblDecimalInvalid for our cases
|
; test invalid cases. We loop through tblDecimalInvalid for our cases
|
||||||
ld b, 3
|
ld b, 4
|
||||||
ld hl, tblDecimalInvalid
|
ld hl, .invalid
|
||||||
|
|
||||||
.loop2:
|
.loop2:
|
||||||
call parseDecimal
|
call parseDecimal
|
||||||
@ -159,6 +141,34 @@ testDecimal:
|
|||||||
call nexttest
|
call nexttest
|
||||||
ret
|
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:
|
nexttest:
|
||||||
ld a, (testNum)
|
ld a, (testNum)
|
||||||
inc a
|
inc a
|
||||||
|
Loading…
Reference in New Issue
Block a user