2019-05-14 15:26:29 -04:00
|
|
|
; Parse expression in string at (HL) and returns the result in IX.
|
|
|
|
; We expect (HL) to be disposable: we mutate it to avoid having to make a copy.
|
|
|
|
; Sets Z on success, unset on error.
|
|
|
|
parseExpr:
|
2019-05-18 21:06:31 -04:00
|
|
|
; Before we evaluate an expression, we first try for a regular number or
|
|
|
|
; symbol. We do this because parsing expressions can mess up some values
|
|
|
|
; with its splitting logic. For example '-' is going to end up '\0'.
|
|
|
|
call parseNumberOrSymbol
|
|
|
|
ret z
|
2019-05-14 16:38:19 -04:00
|
|
|
push de
|
2019-05-14 15:26:29 -04:00
|
|
|
push hl
|
2019-05-17 22:22:10 -04:00
|
|
|
call _parseExpr
|
2019-05-14 16:38:19 -04:00
|
|
|
pop hl
|
2019-05-17 22:22:10 -04:00
|
|
|
pop de
|
|
|
|
ret
|
|
|
|
|
|
|
|
_parseExpr:
|
|
|
|
ld a, '+'
|
|
|
|
call _findAndSplit
|
|
|
|
jp z, _applyPlus
|
2019-05-14 16:38:19 -04:00
|
|
|
ld a, '-'
|
2019-05-17 22:22:10 -04:00
|
|
|
call _findAndSplit
|
|
|
|
jp z, _applyMinus
|
2019-05-18 15:17:56 -04:00
|
|
|
ld a, '*'
|
|
|
|
call _findAndSplit
|
|
|
|
jp z, _applyMult
|
2019-05-18 21:06:31 -04:00
|
|
|
ret ; failure
|
2019-05-17 22:22:10 -04:00
|
|
|
|
|
|
|
; Given a string in (HL) and a separator char in A, return a splitted string,
|
|
|
|
; that is, the same (HL) string but with the found A char replaced by a null
|
|
|
|
; char. DE points to the second part of the split.
|
|
|
|
; Sets Z if found, unset if not found.
|
|
|
|
_findAndSplit:
|
|
|
|
push hl
|
2019-05-17 09:50:11 -04:00
|
|
|
call findchar
|
2019-05-17 22:22:10 -04:00
|
|
|
jr nz, .end ; nothing found
|
|
|
|
; Alright, we have our char and we're pointing at it. Let's replace it
|
|
|
|
; with a null char.
|
2019-05-14 15:26:29 -04:00
|
|
|
xor a
|
|
|
|
ld (hl), a ; + changed to \0
|
|
|
|
inc hl
|
2019-05-17 22:22:10 -04:00
|
|
|
ex de, hl ; DE now points to the second part of the split
|
|
|
|
cp a ; ensure Z
|
|
|
|
.end:
|
|
|
|
pop hl ; HL is back to the start
|
2019-05-14 16:38:19 -04:00
|
|
|
ret
|
|
|
|
|
2019-05-17 22:22:10 -04:00
|
|
|
; parse expression on the left (HL) and the right (DE) and put the results in
|
|
|
|
; DE (left) and IX (right)
|
|
|
|
_resolveLeftAndRight:
|
2019-05-14 16:38:19 -04:00
|
|
|
call parseExpr
|
2019-05-14 15:26:29 -04:00
|
|
|
ret nz ; return immediately if error
|
2019-05-17 22:22:10 -04:00
|
|
|
; Now we have parsed everything to the left and we have its result in
|
|
|
|
; IX. What we need to do now is the same thing on (DE) and then apply
|
|
|
|
; the + operator. Let's save IX somewhere and parse this.
|
|
|
|
ex hl, de ; right expr now in HL
|
2019-05-14 16:38:19 -04:00
|
|
|
push ix
|
2019-05-17 22:22:10 -04:00
|
|
|
pop de ; numeric left expr result in DE
|
|
|
|
jp parseExpr
|
|
|
|
|
|
|
|
; Parse expr in (HL) and expr in (DE) and apply + operator to both sides.
|
|
|
|
; Put result in IX.
|
|
|
|
_applyPlus:
|
|
|
|
call _resolveLeftAndRight
|
|
|
|
ret nz
|
|
|
|
; Good! let's do the math! IX has our right part, DE has our left one.
|
2019-05-14 15:26:29 -04:00
|
|
|
add ix, de
|
2019-05-17 22:22:10 -04:00
|
|
|
cp a ; ensure Z
|
|
|
|
ret
|
|
|
|
|
|
|
|
; Same as _applyPlus but with -
|
|
|
|
_applyMinus:
|
|
|
|
call _resolveLeftAndRight
|
|
|
|
ret nz
|
2019-05-14 16:38:19 -04:00
|
|
|
push ix
|
|
|
|
pop hl
|
2019-05-17 22:22:10 -04:00
|
|
|
ex de, hl
|
2019-05-18 15:17:56 -04:00
|
|
|
scf \ ccf
|
2019-05-14 16:38:19 -04:00
|
|
|
sbc hl, de
|
|
|
|
push hl
|
|
|
|
pop ix
|
2019-05-17 22:22:10 -04:00
|
|
|
cp a ; ensure Z
|
|
|
|
ret
|
|
|
|
|
|
|
|
_applyMult:
|
|
|
|
call _resolveLeftAndRight
|
|
|
|
ret nz
|
|
|
|
push ix \ pop bc
|
|
|
|
call multDEBC
|
|
|
|
push hl \ pop ix
|
2019-05-14 16:38:19 -04:00
|
|
|
cp a ; ensure Z
|
2019-05-14 15:26:29 -04:00
|
|
|
ret
|