kolibrios-fun/programs/other/calcplus/parser.inc

395 lines
7.1 KiB
PHP
Raw Normal View History

macro test_err
{ local ..not_error
cmp [error_n], 0
je ..not_error
ret
..not_error:
}
macro set_err err
{
mov [error_n], err
ret
}
; ---------------------------
proc parse
mov [exp_pos], 0
stdcall skip_spaces
mov ebx, exp
add ebx, [exp_pos]
cmp [ebx], byte 0
je .null_exp
mov [exp_lvl], 0
mov [error_n], 0
stdcall parse_lvl0
ret
.null_exp:
mov eax, 0
ret
endp
; ---------------------------
proc parse_lvl0 uses ebx ecx
test_err
stdcall parse_lvl1
test_err
@@:
mov ebx, exp
add ebx, [exp_pos]
cmp [ebx], byte 0
je .end
cmp [ebx], byte ")"
je .brk_end
inc [exp_pos]
cmp [ebx], byte "+"
jne .not_add
mov ecx, eax
stdcall parse_lvl1
test_err
add eax, ecx
jmp @b
.not_add:
cmp [ebx], byte "-"
jne .unexp_char
mov ecx, eax
stdcall parse_lvl1
test_err
sub ecx, eax
mov eax, ecx
jmp @b
.brk_end:
cmp [exp_lvl], 0
jne @f
set_err 3
@@:
dec [exp_lvl]
.end:
ret
.unexp_char:
set_err 4
endp
; ---------------------------
proc parse_lvl1 uses ebx ecx edx
test_err
stdcall parse_lvl2
test_err
@@:
mov ebx, exp
add ebx, [exp_pos]
cmp [ebx], byte 0
je .end
cmp [ebx], byte "*"
jne .not_mul
inc [exp_pos]
mov ecx, eax
stdcall parse_lvl2
test_err
imul ecx, eax
mov eax, ecx
jmp @b
.not_mul:
cmp [ebx], byte "/"
je .div_or_mod
cmp [ebx], byte "%"
je .div_or_mod
jmp .end
.div_or_mod:
inc [exp_pos]
mov ecx, eax
stdcall parse_lvl2
test_err
cmp eax, 0
jne .not_null
set_err 1
.not_null:
xchg ecx, eax
cdq
div ecx
cmp [ebx], byte "%"
je .mod
jmp @b
.mod:
mov eax, edx
jmp @b
.end:
ret
endp
; ---------------------------
proc parse_lvl2 uses ebx ecx edx
test_err
stdcall parse_lvl3
test_err
@@:
mov ebx, exp
add ebx, [exp_pos]
cmp [ebx], byte 0
je .end
cmp [ebx], byte "^"
jne .end
inc [exp_pos]
mov ecx, eax
stdcall parse_lvl2
test_err
stdcall c_power
jmp @b
.end:
ret
endp
; ---------------------------
proc parse_lvl3 uses ebx ecx edx
test_err
stdcall skip_spaces
mov ebx, exp
add ebx, [exp_pos]
cmp [ebx], byte 48
jl @f
cmp [ebx], byte 57
jg @f
stdcall parse_lvl4
jmp .end
@@:
cmp [ebx], byte 97
jl @f
cmp [ebx], byte 122
jg @f
jmp .parse_func
@@:
inc [exp_pos]
cmp [ebx], byte "("
jne @f
inc [exp_lvl]
stdcall parse_lvl0
test_err
mov ebx, exp
add ebx, [exp_pos]
cmp [ebx], byte ")"
je .brk_ok
set_err 2
.brk_ok:
inc [exp_pos]
jmp .end
@@:
cmp [ebx], byte "+"
jne @f
stdcall parse_lvl3
test_err
jmp .end
@@:
cmp [ebx], byte "-"
jne .unexp_char
stdcall parse_lvl3
test_err
neg eax
.end:
stdcall skip_spaces
ret
.unexp_char:
set_err 4
.parse_func:
mov ecx, 0
mov dl, 0
@@:
cmp [ebx], byte 97
jl @f
cmp [ebx], byte 122
jg @f
cmp dl, 4
je .unexp_char
shl ecx, 8
mov cl, [ebx]
inc dl
inc ebx
inc [exp_pos]
jmp @b
@@:
cmp ecx, "cni"
je @f
cmp ecx, "ced"
je @f
cmp ecx, "sba"
je @f
cmp ecx, "rqs"
je @f
jmp .unexp_char
@@:
stdcall skip_spaces
mov ebx, exp
add ebx, [exp_pos]
cmp [ebx], byte "("
jne .unexp_char
inc [exp_lvl]
inc [exp_pos]
stdcall parse_lvl0
test_err
mov ebx, exp
add ebx, [exp_pos]
cmp [ebx], byte ")"
je @f
set_err 2
@@:
inc [exp_pos]
stdcall skip_spaces
cmp ecx, "cni"
jne @f
inc eax
jmp .f_end
@@:
cmp ecx, "ced"
jne @f
dec eax
jmp .f_end
@@:
cmp ecx, "sba"
jne @f
mov ecx, eax
shr ecx, 31
cmp cl, 1
jne .f_end
not eax
inc eax
jmp .f_end
@@:
cmp ecx, "rqs"
jne @f
imul eax, eax
jmp .f_end
@@:
jmp .unexp_char
.f_end:
ret
endp
; ---------------------------
proc parse_lvl4 uses ebx ecx
stdcall skip_spaces
stdcall parse_lvl5
stdcall skip_spaces
@@:
mov ebx, exp
add ebx, [exp_pos]
cmp [ebx], byte 0
je .end
cmp [ebx], byte "^"
jne .end
inc [exp_pos]
stdcall skip_spaces
mov ecx, eax
mov ebx, exp
add ebx, [exp_pos]
cmp [ebx], byte 48
jl .unexp_char
cmp [ebx], byte 57
jg .unexp_char
stdcall parse_lvl4
stdcall c_power
jmp @b
.end:
ret
.unexp_char:
set_err 4
endp
; ---------------------------
proc parse_lvl5 uses ebx ecx
sub eax, eax
sub ecx, ecx
mov ebx, exp
add ebx, [exp_pos]
@@:
cmp [ebx], byte 0
je @f
cmp [ebx], byte 48
jl @f
cmp [ebx], byte 57
jg @f
imul eax, 10
mov cl, [ebx]
add eax, ecx
sub eax, 48
inc ebx
inc [exp_pos]
jmp @b
@@:
ret
endp
; ---------------------------
proc skip_spaces uses ebx
mov ebx, exp
add ebx, [exp_pos]
@@:
cmp [ebx], byte " "
jne @f
inc ebx
inc [exp_pos]
jmp @b
@@:
ret
endp
; ---------------------------
proc c_power uses ebx
mov ebx, eax
mov eax, 1
@@:
cmp ebx, 0
je @f
imul eax, ecx
dec ebx
jmp @b
@@:
ret
endp
; ---------------------------
proc convert_to_str uses ebx ecx edx esi edi, _num, _str
mov eax, [_num]
mov esi, [_str]
mov edi, 0
mov ecx, eax
and ecx, 1 shl 31
cmp ecx, 0
je @f
mov [esi], byte "-"
inc esi
inc edi
not eax
inc eax
@@:
mov ebx, 10
xor ecx, ecx
@@:
xor edx, edx
div ebx
push edx
inc ecx
inc edi
cmp eax, 0
jne @b
@@:
pop eax
add al, "0"
mov [esi], al
inc esi
loop @b
mov [esi], byte 0
mov eax, edi
ret
endp