- BASIC interpreter
- 27 Feb 2010 08:54:30 pm
- Last edited by Will_W on 28 Feb 2010 01:40:47 am; edited 1 time in total
It parses the real number from the string at hl
returns:
hl = end if string +1
de = start of string
OP1 = real number in TI-FP
hasn't been tested yet.
Code:
returns:
hl = end if string +1
de = start of string
OP1 = real number in TI-FP
hasn't been tested yet.
Code:
ParseRealOP1: ;the first char is '.' , 'EE' , '-' , or a digit
push hl
ld a,6fh
cp (hl)
ld a,0 ;can't use xor a because it doesn't preserve flags
jp z, ParseRealNegative
ld a,0-80h
ParseRealNegative:
inc hl ;
add a,80h
ld (8478h),a ;the sign byte
ld b,80 ;keep track of the exponent- 80 is 0
ld c,14 ;the number of digits that fit into significand
ParseRealExponent: ;takes care of values with zeros at the front
ld a,(hl)
cp 3Bh;tee, the small 'E'
jp nz,ParseRealExponentLoop
call ParseRealEE
;now fill the mantisa with 10,00,00,00,00,00,00,00,00
ex de,hl
ld hl,8479h ;the exponent byte of OP1
ld (hl),b ;
inc hl
ld (hl),10h
ex de,hl; now de is the significand
inc de; de++, de points to significand of OP1++
ld c,12
jp ParseRealFinishFillSignificand;it does the filling
ParseRealExponentLoop:
ld a,(hl)
cp 3Ah;'.'
jp z,ParseRealExponentNeg
cp 3Bh;'EE'
jp z,ZeroOP1QuitEE ;0Exx is always 0
call TokenToInt
jp c,ZeroOP1Quit ;so "000000" evaluates to 0
jp nz,ParseExponentFinish;break the loop if a non 0 digit
inc hl
jp ParseRealExponentLoop
ParseRealExponentNeg:
inc hl
dec b
jp c,ParseRealErrorOverflow;you just HAD to put that many 0's
ld a,(hl)
cp 3Bh; 'EE'
jp z,ZeroOP1QuitEE
call TokenToInt
jp c,ZeroOP1Quit
jp z,ParseRealExponentNeg
ParseExponentFinish:;hl points to fist sig fig
push hl
ld a, 80h
and b
rlca
ld e, a ; if b >= 80h, e = 1, else 0
ParseExponentFinishLoop:
inc hl
ld (hl),a
call TokenToInt
jp c, ParseExponentFinishNotAnInt
add a,e
ld b,a ;increment exponent if necessary
jp c, ParseRealErrorOverflow
jp ParseExponentFinishLoop
ParseExponentFinishNotAnInt:
cp 0Ah ; '.' minus 30h
jp nz,ParseExponentFinishEE
dec e
jp c,ParseRealSyntaxError;two '.'
jp ParseExponentFinishLoop
ParseExponentFinishEE:
cp 0Bh ; 'EE' minus 30h
call z,ParseRealEE
ParseExponentFinishEnd:
ld hl,8479h ;the exponent byte of OP1
ld (hl),b ;
ex de,hl; now de is the exponent byte of OP1
inc de; de++, de points to significand of OP1
pop hl
ParseRealLoop:;hl points to first sigfig
ld a,(hl)
call TokenToInt
jp c, ParseRealNotAnInt
ex de,hl
rld
ex de,hl
inc hl
dec c
jp z,ParseRealFinish
bit 0,c
jp z,ParseRealLoop
inc e
jp ParseRealLoop
ParseRealNotAnInt:
cp 0Bh ;'EE' minus 30h
jp nz,ParseRealFinish
inc hl;there will always be one digit after, so we can add 2
inc hl;if there weren't, it would have errored earlier
ld a,(hl)
call TokenToInt
jp c,ParseRealFinish
inc hl
jp ParseRealFinish
ParseRealFinish:
xor a
bit 7,c
jp z,ParseRealFinishFillSignificandLoop
rld ;if c is odd, then it needs one more rotate
dec c
ParseRealFinishFillSignificand:
xor a
ParseRealFinishFillSignificandLoop:
dec c;c might already be 0
jp c,ParseRealFinishEnd;so I used jp c instead of jp z
dec c
inc de
ld (de),a
jp ParseRealFinishFillSignificandLoop
ParseRealFinishEnd:
pop de;de = start of real, hl = end of real + 1
ret;I hope I didn't forget anything.
;OP1 should now contain the real in TI-FP format
ParseRealEE:; in, hl = pointer to 'EE' out, b is adjusted and hl points to the character after the "E##"
; push de;I feel like using them, so save them
inc hl ;hl points to letter after the 'EE'
ld a,(hl)
cp 6fh
jp nz,ParseRealEEPos
inc hl ;hl points to the fist digit after 'EE'
ParseRealEENeg:
ld a,(hl)
call TokenToInt
jp c,ParseRealSyntaxError ;
ld e,a
inc hl ;hl points to second digit, or digit after
ld a,(hl)
call TokenToInt
jp c, ParseRealEENeg1
ld d,a
ParseRealEENeg10:
inc hl ;hl points to digit after
ld a,e
add a,a ;x2
add a,a ;x4
add a,e ;x5
add a,a ;x10
sub b
neg ;b-a
ld b,a ;
ld e,d
ParseRealEENeg1:
ld a,e
sub b
neg ;b-a
ld b,a
ld a,(hl)
call TokenToInt
jp nc, ParseRealSyntaxError;if there are 3 digits after 'EE'
; pop de
ret
ParseRealPos:
call TokenToInt
jp c,ParseRealSyntaxError
ld e,a
inc hl ;hl points to second digit, or digit after
ld a,(hl)
call TokenToInt
jp c, ParseRealEEPos1
ld d,a
ParseRealEEPos10:
inc hl ;hl points to digit after
ld a,e
add a,a
add a,a
add a,e
add a,a ;x10
add a,b
ld b,a
ld e,d
ParseRealEEPos1:
ld a,e
add a,b
ld b,a
ld a,(hl)
call TokenToInt
jp nc, ParseRealSyntaxError
; pop de
ret
ZeroOP1QuitEE:
inc hl
ld a,(hl)
call TokenToInt
jp c, ParseRealSyntaxError
inc hl
ld a,(hl)
call TokenToInt
jp c, ZeroOP1Quit
inc hl
ld a,(hl)
call TokenToInt
jp nc, ParseRealSyntaxError
ZeroOP1Quit:;hl = end of real+1, no errors detected
push hl
xor a
ld hl,8479h
ld (hl),80h
inc hl
ld (hl),a
ld de,847Bh
ld bc,7 ;size of the significand
ldir
pop hl;end of real+1
pop de;start of real
ret
;returns a = int or carry if not
TokenToInt:
cp 39h
jp nc, Return_C ;return carry if it's not an int
sub 30h
ret ;also returns carry if not an int token
Return_C:
scf
ret