#!/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 split("", code) split("", mem) printf "> " } { line = $0; parse(); run(); printf "> " } function scan() { sub(/^[ \t]+/, "", line) # print "# line: '" line "'" if (match(line, /^[.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) } # cnum += RLENGTH line = substr(line, RLENGTH+1) # print "# scan: RLENGTH=" RLENGTH 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) { # 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: assign function run( c, i, l, t) { cl = length(code) ml = length(mem) i = 0 while (i < cl) { c = code[i] 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 { mem[++ml] = 0 + substr(c, 2) } i++ } print mem[ml] for (i = ml; i in mem; i++) delete mem[i] }