;; Assembly-based Compiler #3
;;
;;	To compile & run:  ./r ac ex1.ac

; Changes since #2:
;	Added symbol tables, but I'm hardly using them... I will be using
;	the table entries as tokens. For now, it's a mess.. it's getting
;	better though.
;
;	Fixed input-flushing when aborting on errors.

; BUGS
;	Nothing unintentional :)

; Register conventions:
;	EAX is top-of-stack / return value
;	ESP is stack pointer (C calling conventions)
;	All others are available; CALLEE SAVES

;---------------------------------------------------------------------
%include "asmmac.inc"
%include "io.inc"
%include "ctype.inc"
%include "scan.inc"
%include "parse.inc"
%include "symtab.inc"

;---------------------------------------------------------------------
SECTION .text
	global _start
	align 4
_start:
	pop eax		;Read command line
	cmp eax,1
	if e
	  mov eax,stdin
	  jmp short .2
	endif
	mov eax,5	;Open(ebx,"r") syscall
	mov ebx,[esp+4]
	mov ecx,0	;read-only
	int 80h
	or eax,eax
	if z
	  printf "Open error\n"
	  jmp halt
	endif
.2	mov [infd],eax

	call Compiler

halt:
	cmp dword [infd], stdin	;Flush input if reading from stdin
	if e			;do this by reading up to the next LF
	  repeat		;(it should be safe to assume we're in
	    call Getchar	; line-by-line mode)
	    cmp [look], byte 10
	  until e
	endif
	jmp short exit

;---------------------------------------------------------------------
; Compiler subroutines

SECTION .bss
	alignb 4
look	resd	1	;lookahead char
value	resd	1	;value
type	resd	1	;type of token
infd	resd	1	;input file descriptor

SECTION .text

; Getchar() -- read char from input file to [look]
	align 4
Getchar:
	push eax,ebx,ecx,edx
	mov eax,3	;Read(fd, buf, count) syscall
	mov ebx,[infd]
	mov ecx,look
	mov edx,1
	int 80h
	or eax,eax
	  jz .eof
	pop eax,ebx,ecx,edx
	ret
.eof
	;printf "EOF\n"
exit:	mov eax,1
	int 80h

;---------------------------------------------------------------------
Compiler:
	call Getchar	; Init

;jmp Test_Ident
;jmp Test_Lookup
;jmp Test_Scanner

;The real compiler:
	call Prologue
	call Block
	call Epilogue
	ret

Test_Ident:
.1	call Getname
	printf "got '%s'\n", [value]
	call IdentToken
	or eax,eax
	if nz
	  lea ebx,[eax+4]
	  printf "Matched symbol %d %s\n", eax, ebx
	else
	  printf "Unknown identifier '%s'\n", [value]
	endif
	jmp .1

Test_Lookup:
.1	call Getname
	printf "got '%s'\n", [value]
	call KeywordToken
	or eax,eax
	if nz
	  printf "Lookup returned %d %s\n", eax, eax
	else
	  printf "Lookup returned 0 - '%s' is not a keyword\n", [value]
	endif
	jmp .1

Test_Scanner:
.00	call Next
	mov ebx,[type]
	call [.tbl + ebx*4]
	jmp .00

.tbl	dd .0, .1, .2
.0	printf "\tNumber: %d\n", [value]
	ret
.1	printf "\tOperator: %c\n", [value]
	ret
.2	printf "\tIdent: '%s'\n", [value]
	ret

;---------------------------------------------------------------------
Prologue:
	printf "SECTION .text\n\tglobal _start\n_start:\n"
	ret

Epilogue:
	printf "\tMOV EAX,1\n\tINT 80h\n"
	ret
;---------------------------------------------------------------------
;END
