1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
|
#!/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]
}
|