summaryrefslogtreecommitdiff
path: root/ev
blob: 9b35b507537174e540232841fa179574ce57bc17 (plain)
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]
}