lep.py
'''\
Logical Expression Parser.
Parses logical expression into an object tree and generates a truth table
covering all combinations of detected input variables.
Example: (a | not b) & not (c | not d)
The example above would generate a truth table for the 16 possible input
combinations for a, b, c, and d. (Assuming each could be true or false.)
Test run:
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
command: main
args: 1
Main:
source: (not a | b) & not (not c & d)
Parse...
expr.NOT:
term.name: a (NEW)
expr.t1: a
expr.t1: NOT a
expr.op: OR
term.name: b (NEW)
expr.t2: b
term.expr: (NOT a OR b)
expr.t1: (NOT a OR b)
expr.op: AND
expr.NOT:
expr.NOT:
term.name: c (NEW)
expr.t1: c
expr.t1: NOT c
expr.op: AND
term.name: d (NEW)
expr.t2: d
term.expr: (NOT c AND d)
expr.t1: (NOT c AND d)
expr.t2: NOT (NOT c AND d)
Terms...
['a', 'c', 'b', 'd']
expression: ((NOT a OR b) AND NOT (NOT c AND d))
Truth Table:
| a c b d | OUT
0: False False False False = True
1: True False False False = False
2: False True False False = True
3: True True False False = False
4: False False True False = True
5: True False True False = True
6: False True True False = True
7: True True True False = True
8: False False False True = False
9: True False False True = False
10: False True False True = True
11: True True False True = False
12: False False True True = False
13: True False True True = False
14: False True True True = True
15: True True True True = True
--
done: <type 'tuple'> (2)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'''
from sys import stdout, stderr, argv
from lep_objects import *
from lep_parser import *
ListToString = lambda lst: reduce(lambda acc,s: acc+s, lst, '')
samples = []
samples.append('not foo and not bar')
samples.append('(a | b) & not (a & b)')
samples.append('(a & not b) | (not a & b)')
samples.append('(a and not b) or (not a and b)')
samples.append('(not a | b) & not (not c & d)')
samples.append('(foo and bar) xor not (boo or far)')
samples.append('not ((not (foo & not bar) | not (foo & baz)) | ((bar & zip) | not (foo | zip)))')
sample_text = samples[0]
def gen_truth_table (expr, terms):
print 'Truth Table:'
ns = []
for ix in range(len(terms)):
ns.append('%-5s ' % terms[ix].n)
s = ListToString(ns)
h1 = ' | %s | =' % s
h2 = '---|--%s-|------' % ('-' * len(s))
print h1
print h2
for bx in range(2 ** len(terms)):
ts = []
for ix in range(len(terms)):
terms[ix].v = True if (bx & (2 ** ix)) else False
ts.append('%-5s ' % terms[ix].v)
v = expr()
print '%3d| %s = %-5s' % (bx, ListToString(ts), v)
print h2
print
def do_test (*args):
print 'Test:'
print 'test/parameters: %d' % len(args)
txt = args[0] if 0 < len(args) else sample_text
src = source(txt)
print 'parse: "%s"' % src
try:
expr = parse_expression(src)
except Exception as e:
print e
raise
print 'terms: %s' % src.lib.keys()
ts = []
for t in src.lib.values():
ts.append(t)
print map(lambda t: str(t), ts)
print
print 'expression: %s' % expr
gen_truth_table(expr, ts)
return [src, expr, ts]
def do_main (*args):
print 'main/parameters: %d' % len(args)
txt = args[0] if 0 < len(args) else sample_text
return [None, txt]
def dispatch (command, *args):
print 'command: %s' % cmd
print 'arguments: %d' % len(args)
if command == 'test': return do_test(*args)
if command == 'main': return do_main(*args)
return [None, command, args]
if __name__ == '__main__':
print 'autorun: %s' % argv[0]
cmd = argv[1] if 1 < len(argv) else ''
etc = argv[2:] if 2 < len(argv) else [sample_text]
obj = dispatch(cmd, *etc)
print ''
print 'exit/type: %s (length: %d)' % (type(obj), len(obj))
'''eof'''