#!/usr/bin/env awk -f # an evaluator of code BEGIN { # prec array contains the precedence order of operators prec["="] = 1 prec["+"] = prec["-"] = 2 prec["*"] = prec["/"] = 3 prec["^"] = 4 # rigth array contains operators which are right associative right["="] = right["^"] = 1 pc = 0 split("", code) split("", mem) split("", var) printf "> " } { line = $0 parse() run() printf "> " } function scan() { ptok = tok sub(/^[ \t]+/, "", line) if (match(line, /^[0-9]([.0-9]*(e[+-]*)*[0-9])*/)) { tok = "d" substr(line, 1, RLENGTH) } else if (match(line, /^([][}{)(,+-=?:]|[*\/รท\^])/)) { tok = substr(line, 1, RLENGTH) } else if (match(line, /^[A-Za-z_][A-Za-z_0-9]*/)) { tok = "v" substr(line, 1, RLENGTH) } else if (match(line, /^"(\\.|[^\\"])*"/)) { tok = "s" substr(line, 2, RLENGTH-2) } else { tok = "b" substr(line, 1, 1) } line = substr(line, RLENGTH+1) return RLENGTH } # TODO: unary operators function parse( stack, sl, i) { i = length(code) while (scan() > 0) { if (tok == "(") { stack[++sl] = tok } else if (tok == ")") { while (sl && stack[sl] != "(") code[i++] = stack[sl--] sl-- } else if (tok in prec) { if (tok == "=" && ptok ~ /^v/) sub(/^v/, "p", code[i-1]) # mutate var to pointer for assign # Test precedence against stack, or associativity if same precedence while (sl && (prec[tok] < prec[stack[sl]] || prec[tok] == prec[stack[sl]] && !(stack[sl] in right))) { code[i++] = stack[sl--] } stack[++sl] = tok } else { code[i++] = tok } } while (sl) code[i++] = stack[sl--] # for (j = 0; j < i; j++) printf("%s ", code[j]); print "" } # TODO: if, while, function function run( c, i, l, t) { cl = length(code) ml = length(mem) while (pc < cl) { c = code[pc] if (c == "+") { mem[--ml] = mem[ml-1] + mem[ml] } else if (c == "-") { mem[--ml] = mem[ml-1] - mem[ml] } else if (c == "*") { mem[--ml] = mem[ml-1] * mem[ml] } else if (c == "/") { mem[--ml] = mem[ml-1] / mem[ml] } else if (c == "^") { mem[--ml] = mem[ml-1] ^ mem[ml] } else if (c == "=") { var[substr(mem[ml-1], 2)] = mem[ml] mem[--ml] = mem[ml] } else if (c ~ /^p/) { mem[++ml] = c } else if (c ~ /^v/) { mem[++ml] = var[substr(c, 2)] } else if (c ~ /^[d]/) { mem[++ml] = 0 + substr(c, 2) } printf "c" pc ": " c; for (i = 1; i <= ml; i++) printf ", " i ":" mem[i]; print "" for (i in var) print "var[" i "]=" var[i] pc++ } print mem[ml] var["_"] = mem[ml--] # for (i = ml; j in mem; i++) delete mem[i] }