86 lines
2.7 KiB
Plaintext
86 lines
2.7 KiB
Plaintext
import "./dynamic" for Struct
|
|
import "./ioutil" for Input
|
|
import "./seq" for Stack
|
|
import "./str" for Str
|
|
|
|
var Variable = Struct.create("Variable", ["name", "value"])
|
|
|
|
// use integer constants as bools don't support bitwise operators
|
|
var FALSE = 0
|
|
var TRUE = 1
|
|
|
|
var expr = ""
|
|
var variables = []
|
|
|
|
var isOperator = Fn.new { |op| "&|!^".contains(op) }
|
|
|
|
var isVariable = Fn.new { |s| variables.map { |v| v.name }.contains(s) }
|
|
|
|
var evalExpression = Fn.new {
|
|
var stack = Stack.new()
|
|
for (e in expr) {
|
|
var v
|
|
if (e == "T") {
|
|
v = TRUE
|
|
} else if (e == "F") {
|
|
v = FALSE
|
|
} else if (isVariable.call(e)) {
|
|
var vs = variables.where { |v| v.name == e }.toList
|
|
if (vs.count != 1) Fiber.abort("Can only be one variable with name %(e).")
|
|
v = vs[0].value
|
|
} else if (e == "&") {
|
|
v = stack.pop() & stack.pop()
|
|
} else if (e == "|") {
|
|
v = stack.pop() | stack.pop()
|
|
} else if (e == "!") {
|
|
v = (stack.pop() == TRUE) ? FALSE : TRUE
|
|
} else if (e == "^") {
|
|
v = stack.pop() ^ stack.pop()
|
|
} else {
|
|
Fiber.abort("Non-conformant character %(e) in expression")
|
|
}
|
|
stack.push(v)
|
|
}
|
|
if (stack.count != 1) Fiber.abort("Something went wrong!")
|
|
return stack.peek()
|
|
}
|
|
|
|
var setVariables // recursive
|
|
setVariables = Fn.new { |pos|
|
|
var vc = variables.count
|
|
if (pos > vc) Fiber.abort("Argument cannot exceed %(vc).")
|
|
if (pos == vc) {
|
|
var vs = variables.map { |v| (v.value == TRUE) ? "T" : "F" }.toList
|
|
var es = (evalExpression.call() == TRUE) ? "T" : "F"
|
|
System.print("%(vs.join(" ")) %(es)")
|
|
return
|
|
}
|
|
variables[pos].value = FALSE
|
|
setVariables.call(pos + 1)
|
|
variables[pos].value = TRUE
|
|
setVariables.call(pos + 1)
|
|
}
|
|
|
|
System.print("Accepts single-character variables (except for 'T' and 'F',")
|
|
System.print("which specify explicit true or false values), postfix, with")
|
|
System.print("&|!^ for and, or, not, xor, respectively; optionally")
|
|
System.print("seperated by spaces or tabs. Just enter nothing to quit.")
|
|
|
|
while (true) {
|
|
expr = Input.text("\nBoolean expression: ")
|
|
if (expr == "") return
|
|
expr = Str.upper(expr).replace(" ", "").replace("\t", "")
|
|
variables.clear()
|
|
for (e in expr) {
|
|
if (!isOperator.call(e) && !"TF".contains(e) && !isVariable.call(e)) {
|
|
variables.add(Variable.new(e, FALSE))
|
|
}
|
|
}
|
|
if (variables.isEmpty) return
|
|
var vs = variables.map { |v| v.name }.join(" ")
|
|
System.print("\n%(vs) %(expr)")
|
|
var h = vs.count + expr.count + 2
|
|
System.print("=" * h)
|
|
setVariables.call(0)
|
|
}
|