Simple 4 operations calculator ...
# usage: print calc("5 * (1 + 2) * 5 + 7")
# reads and update s[0]
# return the first token
function next_token(s, t) {
sub(/^[[:space:]]*/,"", s[0])
if (match(s[0], /^[()]/) ||
match(s[0], /^[-+]?[0-9]+(\.[0-9]+)*/) ||
match(s[0], /^[-+*/]/)) {
t = substr(s[0], RSTART, RLENGTH)
s[0] = substr(s[0], RLENGTH+1)
return t
} else {
return ""
}
}
# read input and performs the shuting-yard algorithm
# result is in postfixed
# return the length of the postfixed array
function s_y( input, postfixed ,len, stack, head, op, s, token, pre) {
# precedence table
pre["+"]=pre["-"]=1
pre["*"]=pre["/"]=2
pre["("]=0
s[0] = input
while (token = next_token(s)) {
if (token ~ /^[-+]?[0-9]+(\.[0-9]+)*/) {
postfixed[++len] = token
} else if (token ~ /[-+/*]/) {
while ((head > 0) && (pre[token] <= pre[stack[head]])) {
postfixed[++len] = stack[head]
head-=1
}
stack[++head] = token
} else if (token ~ /[(]/) {
stack[++head] = token
} else if (token ~ /[)]/) {
while ((head > 0) && (stack[head] != "(")) {
postfixed[++len] = stack[head]
head -= 1
}
if (head == 0) {
print "Syntax Error"
return 0
} else {
head -= 1
}
}
}
while ((head > 0)) { postfixed[++len] = stack[head--] }
return len
}
#eval the postfixed operation
function eval(postfixed, len, stack, ptr, i) {
for (i=1; i<=len; i++) {
if (postfixed[i] == "-") {
ptr-=1
stack[ptr] = stack[ptr] - stack[ptr+1]
} else if (postfixed[i] == "+") {
ptr-=1
stack[ptr] = stack[ptr] + stack[ptr+1]
} else if (postfixed[i] == "*") {
ptr-=1
stack[ptr] = stack[ptr] * stack[ptr+1]
} else if (postfixed[i] == "/") {
ptr-=1
stack[ptr] = stack[ptr] / stack[ptr+1]
} else {
stack[++ptr] = postfixed[i]
}
}
return stack[ptr]
}
function calc(input, postfixed, len) {
len = s_y(input, postfixed)
return eval(postfixed,len)
}
BEGIN {
print calc("5.4 * (1 + -2) * 5 + 7")
}