1
0
mirror of https://github.com/hsoft/collapseos.git synced 2024-11-28 01:38:05 +11:00
collapseos/apps/zasm/parse.asm

176 lines
3.5 KiB
NASM
Raw Normal View History

2019-05-11 11:19:34 +10:00
; Parse the decimal char at A and extract it's 0-9 numerical value. Put the
; result in A.
;
; On success, the carry flag is reset. On error, it is set.
parseDecimalDigit:
; First, let's see if we have an easy 0-9 case
cp '0'
ret c ; if < '0', we have a problem
sub a, '0' ; our value now is valid if it's < 10
cp 10 ; on success, C is set, which is the opposite
; of what we want
ccf ; invert C flag
ret
2019-05-10 05:55:29 +10:00
2019-05-11 11:19:34 +10:00
; Parse string at (HL) as a decimal value and return value in IX under the
2019-05-15 03:53:12 +10:00
; same conditions as parseLiteral.
2019-05-11 11:19:34 +10:00
parseDecimal:
push hl
push de
push bc
2019-05-11 11:19:34 +10:00
ld ix, 0
.loop:
ld a, (hl)
cp 0
jr z, .end ; success!
call parseDecimalDigit
jr c, .error
2019-05-11 11:19:34 +10:00
; Now, let's add A to IX. First, multiply by 10.
ld d, ixh ; we need a copy of the initial copy for later
ld e, ixl
add ix, ix ; x2
add ix, ix ; x4
add ix, ix ; x8
add ix, de ; x9
add ix, de ; x10
add a, ixl
jr nc, .nocarry
inc ixh
.nocarry:
ld ixl, a
2019-05-11 11:19:34 +10:00
; We didn't bother checking for the C flag at each step because we
; check for overflow afterwards. If ixh < d, we overflowed
ld a, ixh
cp d
jr c, .error ; carry is set? overflow
2019-05-11 11:19:34 +10:00
inc hl
jr .loop
.error:
call JUMP_UNSETZ
.end:
pop bc
pop de
pop hl
ret
2019-05-11 11:19:34 +10:00
; Parse string at (HL) as a hexadecimal value and return value in IX under the
2019-05-15 03:53:12 +10:00
; same conditions as parseLiteral.
2019-05-11 11:19:34 +10:00
parseHexadecimal:
2019-05-15 03:53:12 +10:00
call hasHexPrefix
ret nz
2019-05-10 11:21:08 +10:00
push hl
2019-05-11 11:19:34 +10:00
xor a
ld ixh, a
inc hl ; get rid of "0x"
2019-05-10 11:21:08 +10:00
inc hl
2019-05-11 11:19:34 +10:00
call strlen
cp 3
jr c, .single
cp 5
jr c, .double
; too long, error
jr .error
.double:
call JUMP_PARSEHEXPAIR ; moves HL to last char of pair
jr c, .error
inc hl ; now HL is on first char of next pair
ld ixh, a
.single:
call JUMP_PARSEHEXPAIR
jr c, .error
ld ixl, a
cp a ; ensure Z
2019-05-10 11:21:08 +10:00
jr .end
2019-05-11 11:19:34 +10:00
.error:
2019-05-10 11:21:08 +10:00
call JUMP_UNSETZ
.end:
pop hl
ret
2019-05-11 11:19:34 +10:00
; Sets Z if (HL) has a '0x' or '0X' prefix.
hasHexPrefix:
ld a, (hl)
2019-05-11 11:19:34 +10:00
cp '0'
ret nz
push hl
inc hl
ld a, (hl)
2019-05-11 11:19:34 +10:00
cp 'x'
jr z, .end
cp 'X'
2019-05-10 05:55:29 +10:00
.end:
pop hl
ret
2019-05-11 11:19:34 +10:00
2019-05-15 03:53:12 +10:00
; Parse string at (HL) and, if it is a char literal, sets Z and return
; corresponding value in IXL. Clears IXH.
;
; 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 ixh, a ; A is zero, take advantage of that
dec hl
dec hl
ld a, (hl)
ld ixl, a
cp a ; ensure Z
.end:
pop hl
ret
; Parses the string at (HL) and returns the 16-bit value in IX. The string
; can be a decimal literal (1234), a hexadecimal literal (0x1234) or a char
; literal ('X').
;
2019-05-11 11:19:34 +10:00
; 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.
2019-05-15 03:53:12 +10:00
parseLiteral:
call parseCharLiteral
ret z
call parseHexadecimal
ret z
jp parseDecimal
2019-05-11 11:19:34 +10:00
; Parse string in (HL) and return its numerical value whether its a number
; literal or a symbol. Returns value in IX.
; Sets Z if number or symbol is valid, unset otherwise.
parseNumberOrSymbol:
2019-05-15 03:53:12 +10:00
call parseLiteral
2019-05-11 11:19:34 +10:00
ret z
call zasmIsFirstPass
ret z ; first pass? we don't care about the value,
; return success.
2019-05-11 11:19:34 +10:00
; Not a number. Try symbol
call symFind
ret nz ; not found
; Found! index in A, let's fetch value
2019-05-11 11:19:34 +10:00
push de
call symGetVal
; value in DE. We need it in IX
2019-05-11 11:19:34 +10:00
ld ixh, d
ld ixl, e
pop de
cp a ; ensure Z
2019-05-10 05:55:29 +10:00
ret