/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
* *
* CODEGEN.SLC Rowan Crowe <rowan#sensation'net'au> *
* *
* Simple calculator demonstration, supports addition, subtraction, *
* multiplication, division, and bracketing. *
* *
* This is similar to CALC.MOO supplied in COMPIxxx.ZIP downloadable via *
* http://www.rowan.sensation.net.au/slc.html , except that it doesn't *
* parse the line into an array prior to evaluating it. *
* *
* The code could still be a lot neater by not relying on using global *
* variables across several functions. *
* *
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
extern int itostr()
extern int strtoui()
extern int input()
extern int puts()
extern int putc()
extern int isdigit()
extern int isalpha()
extern int tinymeminit()
extern int malloc()
extern int free()
extern void abort()
define REG_AX 0
define REG_BX 1
define OP_PUSHREG 0
define OP_POPREG 1
define OP_ADDREG 2
define OP_SUBREG 3
define OP_DIVREG 4
define OP_MULREG 5
global int errno
global char *p
global int errorflag
global int locallabel
int evaluate () {
compare()
}
int compare () {
int t
add_subtract()
while ((*p != 0) && ((*p == '=' && *(p+1) == '=') || (*p == '<') || (*p == '>'))) {
if (*p == '<') {
p = p + 1
puts("\tpush\tax\n")
add_subtract()
puts("\tpop\tbx\n\tcmp\tax,bx\n\tmov\tax,-1\n")
t = locallabel
locallabel = locallabel + 1
puts("\tjl\tLL")
puts(itostr("1234567", locallabel))
puts("\n\tinc\tax\nLL")
puts(itostr("1234567", locallabel))
puts(":\n")
}
if (*p == '>') {
p = p + 1
puts("\tpush\tax\n")
add_subtract()
puts("\tpop\tbx\n\tcmp\tax,bx\n\tmov\tax,-1\n")
t = locallabel
locallabel = locallabel + 1
puts("\tjg\tLL")
puts(itostr("1234567", locallabel))
puts("\n\tinc\tax\nLL")
puts(itostr("1234567", locallabel))
puts(":\n")
}
}
}
int add_subtract() {
divide_multiply()
while ((*p != 0) && ((*p == '+') || (*p == '-'))) {
if (*p == '+') {
p = p + 1
puts("\tpush\tax\n")
divide_multiply()
puts("\tpop\tbx\n\tadd\tax,bx\n")
}
if (*p == '-') {
p = p + 1
puts("\tpush\tax\n")
divide_multiply()
puts("\tmov\tbx,ax\n\tpop\tax\n\tsub\tax,bx\n")
}
}
}
int divide_multiply() {
bracket()
while ( (*p != 0) && ( (*p == '/') || (*p == '*') ) ) {
if (*p == '/') {
p = p + 1
puts("\tpush\tax\n")
bracket()
puts("\tmov\tbx,ax\n\tpop\tax\n\tdiv\tbx\n")
}
if (*p == '*') {
p = p + 1
puts("\tpush\tax\n")
bracket()
puts("\tmov\tbx,ax\n\tpop\tax\n\tmul\tbx\n")
}
}
}
int bracket() {
int rv
remove_whitespace()
if (isdigit(*p) || isalpha(*p)) {
fetchname()
return
}
switch(*p) {
case '(' {
p = p + 1
rv = add_subtract()
if (*p != ')') {
puts("syntax error: expected ')' closing bracket\n")
errorflag = 1
return 0
} else {
p = p + 1
remove_whitespace()
return rv
}
}
case '-' {
p = p + 1
if (isdigit(*p)) {
puts("-")
puts(fetchname())
}
}
case else {
puts("syntax error: unexpected token '")
putc(*p)
puts("'\n")
*p = '0'
errorflag = 1
return 0
}
}
}
int fetchname() {
puts("\tmov\tax,")
while ((isdigit(*p) || isalpha(*p)) && *p != 0) {
putc(*p)
p = p + 1
}
puts("\n")
remove_whitespace()
}
int fetchnumber() {
char *tmpbuf
char *d
if ((tmpbuf = malloc(20)) == -1) {
puts("memory allocation failed.\n")
abort(0)
}
d = tmpbuf
while (isdigit(*p) && *p != 0) {
*d = *p
p = p + 1
d = d + 1
}
*d = 0
remove_whitespace()
free(tmpbuf)
puts(strtoui(tmpbuf))
}
void remove_whitespace() {
while (*p == ' ') {
p = p + 1
}
}
void add_peep(int opcode, int parm1, int parm2) {
}
int main() {
int rv
char *origp
int exitnow
if ((rv = tinymeminit(4096)) == -1) {
puts("memory init failed.\n")
abort(0)
}
if ((p = malloc(51)) == -1) {
puts("memory allocation failed.\n")
abort(0)
}
origp = p
exitnow = 0
locallabel = 0
while (exitnow == 0) {
p = origp
errorflag = 0
puts("> ")
rv = input(p, 50)
puts("\n; ")
puts(p)
puts("\n")
if (*p != 0) {
rv = evaluate()
if (errorflag == 0) {
puts("\n")
}
} else {
exitnow = 1
}
}
puts("\nBye!\n")
free(p) /* ignore return value */
return 0
}
|