;---------------------------------------------------------------------
; Expression Parser

SECTION .text

;---------------------------------------------------------------------
gen_Push:
	printf "\tPUSH EAX\t;push\n"
	ret

gen_Const:
	printf "\tMOV EAX,%d\t;const\n", eax
	ret
;---------------------------------------------------------------------
FnArgs:
.1	call Expr
	call Skipwhite
	cmp [look], byte ','
	if e
	  call Getchar
	  call Skipwhite
	endif
	cmp [look], byte ')'
	  je .end
	call gen_Push
	jmp short .1
.end	ret
;---------------------------------------------------------------------
FnCall:
	push dword [value]
	Match '('
	call Skipwhite
	cmp [look], byte ')'
	if ne
	  call FnArgs
	endif
	Match ')'
	pop eax
	printf "\tCALL %s\t\t;function call\n", eax
	ret
;---------------------------------------------------------------------
Ident:
	call Getname
				;TBD: IdentToken()
	call Skipwhite
.1	cmp [look], byte '('
	if e
	  call FnCall
	else
	  printf "\tMOV EAX,[%s]\t;var\n", [value]
	endif
	ret
;---------------------------------------------------------------------
Factor:
	mov eax,[look]
	cmp al,'('
	if e
	  Match '('
	  call Expr
	  Match ')'
	else
	  call isalpha
	  if nz
	    call Ident
	  else
	    call Getnum
	    mov eax,[value]
	    call gen_Const
	  endif
	endif
	ret
;---------------------------------------------------------------------
SignedFactor:
	mov al,[look]
	cmp al,'-'		;TBD: do this for all addops
	pushf
	if e
	  call Getchar
	  call Skipwhite
	endif
	call Factor
	popf
	if e			;only do this for '-'
	  printf "\tNEG EAX\n"
	endif
	ret
;---------------------------------------------------------------------
_Mul:	printf "\tPOP EBX\t\t;'*'\n\tMUL EBX\n"
	ret

_Div:	printf "\tPOP EBX\t\t;'/'\n\tXOR EDX,EDX\n\tDIV EBX\n"
	ret

_And:	printf "\tPOP EBX\t\t;'&'\n\tAND EAX,EBX\n"
	ret

mulops:	dd '*', _Mul
	dd '/', _Div
	dd '&', _And
	dd 0
;---------------------------------------------------------------------
Term1:
	push ebx,edx
.1	mov edx,mulops
	mov eax,[look]
.2	mov ebx,[edx]
	or ebx,ebx
	  jz .end
	cmp al,bl
	  je .match
	add edx,byte 8
	  jmp short .2
.match	call _Match
	call gen_Push
	call Factor
	call [edx+4]
	  jmp short .1
.end	pop ebx,edx
	ret

Term:
	call Factor
	jmp Term1

FirstTerm:
	call SignedFactor
	jmp Term1
;---------------------------------------------------------------------
_Add:	printf "\tPOP EBX\t\t;'+'\n\tADD EAX,EBX\n"
	ret

_Sub:	printf "\tPOP EBX\t\t;'-'\n\tSUB EAX,EBX\n\tNEG EAX\n"
	ret	;highly suboptimal :)

_Or:	printf "\tPOP EBX\t\t;'|'\n\tOR EAX,EBX\n"
	ret

_Xor:	printf "\tPOP EBX\t\t;'~'\n\tXOR EAX,EBX\n"
	ret

addops:	dd '+', _Add
	dd '-', _Sub
	dd '|', _Or
	dd '~', _Xor
	dd 0
;---------------------------------------------------------------------
; SignedTerm()	-- Handles unary operators
;	TBD: match +, |, ~ (these are no-ops)
;
SignedTerm:
.1	cmp byte [look],'-'
	jne .2
	  call Getchar
	  call Getnum		;should call Term..?
	  neg eax
	  call gen_Const
	  ret
.2	jmp Term
;---------------------------------------------------------------------
Expr:
	push ebx,edx
	call FirstTerm
.1	mov edx,addops
	mov eax,[look]
.2	mov ebx,[edx]
	or ebx,ebx
	  jz .end
	cmp al,bl
	  je .match
	add edx,byte 8
	  jmp short .2
.match	call _Match
	call gen_Push
	call Term
	call [edx+4]
	  jmp short .1
.end	pop ebx,edx
	ret
;---------------------------------------------------------------------
Assign:
	push dword [value]	;TBD: tokenize the identifier
	Match '='
	call Expr
	pop eax
	printf "\tMOV [%s],EAX\t;assignment\n", eax
	ret
;---------------------------------------------------------------------
Statement:
				;(assuming type=ident)
	call Skipwhite
	cmp [look], byte '='
	if e
	  call Assign
	else
	  cmp [look], byte '('
	  if e
	    call FnCall
	  else
	    printf "ERROR: Expected assignment or function call\n"
	    jmp halt
	  endif
	endif
	ret
;---------------------------------------------------------------------
Statements:
	call Next			;expect BEGIN
	call KeywordToken
	cmp eax, keywords.begin		;(assuming type=keyword)
	if ne
	  printf "ERROR: Expected BEGIN\n"
	  jmp halt
	endif

	begin				;expect statement(s) then END
	  call Next
	  call KeywordToken
	  cmp eax, keywords.end		;(assuming type=keyword)
	  				;TBD: handle int/ident/operators
	while ne
	  call Statement
	wend
	ret
;---------------------------------------------------------------------
Declarations:
.1	call Skipwhite
	cmp [look], byte ';'
	  je .end
	call Getname
	call AddIdent
	jmp short .1
.end	call Getchar
	ret
;---------------------------------------------------------------------
Block:
	call Declarations
;	Postlabel(Name)
	jmp Statements
;---------------------------------------------------------------------
;END
