56 lines
1.7 KiB
Smalltalk
56 lines
1.7 KiB
Smalltalk
[:repeat |
|
|
expr := Stdin
|
|
request:'Enter boolean expression (name variables a,b,c...):'
|
|
defaultAnswer:'a|b'.
|
|
ast := Parser parseExpression:expr inNameSpace:nil onError:repeat.
|
|
"
|
|
ensure that only boolean logic operations are inside (sandbox)
|
|
"
|
|
(ast messageSelectors asSet
|
|
conform:[:each | #( '|' '&' 'not' 'xor:' '==>' ) includes:each])
|
|
ifFalse:repeat.
|
|
] valueWithRestart.
|
|
|
|
"
|
|
extract variables from the AST as a collection
|
|
(i.e. if user entered 'a & (b | x)', we get #('a' 'b' 'x')
|
|
"
|
|
varNames := StringCollection streamContents:[:s | ast variableNodesDo:[:each | s nextPut:each name]].
|
|
|
|
"
|
|
generate code for a block (aka lambda) to evaluate it; this makes a string like:
|
|
[:a :b :x | a & (b | x) ]
|
|
"
|
|
code := '[' , ((varNames collect:[:nm | ':',nm]) asString), ' | ' , expr , ']'.
|
|
|
|
"
|
|
eval the code, to get the block
|
|
"
|
|
func := Parser evaluate:code.
|
|
|
|
'Truth table for %s:\n' printf:{expr} on:Stdout.
|
|
'===================\n' printf:{} on:Stdout.
|
|
(varNames,{' result'}) do:[:each | '|%6s' printf:{each} on:Stdout].
|
|
Stdout cr.
|
|
Stdout next:(varNames size + 1)*7 put:$-.
|
|
Stdout cr.
|
|
|
|
"
|
|
now print with all combinations
|
|
"
|
|
allCombinationsDo :=
|
|
[:remainingVars :valuesIn :func |
|
|
remainingVars isEmpty ifTrue:[
|
|
valuesIn do:[:each | '|%6s' printf:{each}on:Stdout].
|
|
'|%6s\n' printf:{ func valueWithArguments:valuesIn} on:Stdout.
|
|
] ifFalse:[
|
|
#(false true) do:[:each |
|
|
allCombinationsDo value:(remainingVars from:2)
|
|
value:(valuesIn copyWith:each)
|
|
value:func.
|
|
].
|
|
].
|
|
].
|
|
|
|
allCombinationsDo value:varNames value:#() value:func
|