Skip to content

Instantly share code, notes, and snippets.

@achequisde
Last active August 26, 2022 19:41
Show Gist options
  • Save achequisde/17805bef55fdafb3d01c2a0b8ffe80cb to your computer and use it in GitHub Desktop.
Save achequisde/17805bef55fdafb3d01c2a0b8ffe80cb to your computer and use it in GitHub Desktop.
Reverse polish notation calculator
# calc.awk -- Reverse polish calculator
# void -> string
function usage() {
return instructions "\n" example
}
# number -> void
function push(value) {
STACK[SP] = value
SP++
}
# void -> number
function pop() {
SP--
return STACK[SP]
}
# string -> void
function op(symbol) {
# There's only one element on the stack
if (SP == 1) return
if (SP > 1) {
second = pop()
first = pop()
if (symbol == "+") result = first + second
if (symbol == "-") result = first - second
if (symbol == "*") result = first * second
if (symbol == "/") result = first / second
push(result)
}
}
# string -> bool
function isop(field) {
if (field ~ operator) return TRUE
return FALSE
}
BEGIN {
# Constants to simulate booleans
TRUE = 1
FALSE = 0
program = "calc.awk"
instructions = program " -- Accepted inputs: one or more NUMBERS separated with WHITESPACE followed by one or more OPERATORS (+, -, *, /)"
example = "EXAMPLE: 5 1 2 + * (which is equal to the number 15)"
# Regex
numbers = "[0-9]"
space = "\\s"
operator = "[+|\\-|*|/]"
expression = "((" number space ")+" operator ")+"
}
$0 ~ expression {
# Holds the current length of STACK, as awk's arrays are actually hash tables
SP = 0
# True when input is malformed and the last field is a number and not an operator
if (!isop($NF)) {
print "Invalid input (ERROR: line ends with a number, it must end with an operator)"
print ""
print usage()
next
}
for (i = 1; i <= NF; i++) {
if (isop($i)) op($i)
else push($i)
}
print pop()
}
$0 !~ expression {
print ""
print usage()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment