114 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
			
		
		
	
	
			114 lines
		
	
	
	
		
			2.5 KiB
		
	
	
	
		
			Python
		
	
	
	
	
	
| # BNF
 | |
| # expression -> bool ( ( '|' | '&' | '^' ) bool )*
 | |
| # bool       -> '0' | '1'
 | |
| 
 | |
| def tokenize(xs):
 | |
|     result = []
 | |
|     for c in xs:
 | |
|         if c == '0':
 | |
|             result.append(0)
 | |
|         elif c == '1':
 | |
|             result.append(1)
 | |
|         elif c in "&|^":
 | |
|             result.append(c)
 | |
|         else:
 | |
|             raise Exception("Unexpected token, \"{}\"".format(c))
 | |
|     return result
 | |
| 
 | |
| class Parser(object):
 | |
|     def __init__(self, tokens):
 | |
|         self.tokens = tokens
 | |
|         self.i = 0
 | |
| 
 | |
|     def prev(self):
 | |
|         return self.tokens[self.i - 1]
 | |
| 
 | |
|     def curr(self):
 | |
|         return self.tokens[self.i]
 | |
| 
 | |
|     def match(self, xs):
 | |
|         if self.exhausted():
 | |
|             return False
 | |
|         if (self.curr() in xs):
 | |
|             self.consume()
 | |
|             return True
 | |
|         return False
 | |
| 
 | |
|     def consume(self):
 | |
|         result = self.curr()
 | |
|         self.i += 1
 | |
|         return result
 | |
| 
 | |
|     def exhausted(self):
 | |
|         return self.i >= len(self.tokens)
 | |
| 
 | |
| def recursive_descent(tokens):
 | |
|     parser = Parser(tokens)
 | |
|     return parse_expression(parser)
 | |
| 
 | |
| def parse_expression(parser):
 | |
|     lhs = parse_bool(parser)
 | |
|     while parser.match(['|', '&', '^']):
 | |
|         op = parser.prev()
 | |
|         rhs = parse_expression(parser)
 | |
|         lhs = [op, lhs, rhs]
 | |
|     return lhs
 | |
| 
 | |
| def parse_bool(parser):
 | |
|     if parser.curr() == 0:
 | |
|         parser.consume()
 | |
|         return False
 | |
|     elif parser.curr() == 1:
 | |
|         parser.consume()
 | |
|         return True
 | |
|     else:
 | |
|         raise Exception("Unexpected token: {}".format(parser.curr()))
 | |
| 
 | |
| def f(expr, result):
 | |
|     tokens = tokenize(expr)
 | |
|     tree = recursive_descent(tokens)
 | |
|     return do_f(tree, result)
 | |
| 
 | |
| def do_f(tree, result):
 | |
|     if type(tree) == bool:
 | |
|         if tree == result:
 | |
|             return 1
 | |
|         else:
 | |
|             return 0
 | |
| 
 | |
|     op, lhs, rhs = tree[0], tree[1], tree[2]
 | |
|     truth_tables = {
 | |
|         True: {
 | |
|             '|': [
 | |
|                 (True, True),
 | |
|                 (True, False),
 | |
|                 (False, True),
 | |
|             ],
 | |
|             '&': [
 | |
|                 (True, True),
 | |
|             ],
 | |
|             '^': [
 | |
|                 (True, False),
 | |
|                 (False, True),
 | |
|             ],
 | |
|         },
 | |
|         False: {
 | |
|             '|': [
 | |
|                 (False, False),
 | |
|             ],
 | |
|             '&': [
 | |
|                 (False, False),
 | |
|                 (True, False),
 | |
|                 (False, True),
 | |
|             ],
 | |
|             '^': [
 | |
|                 (True, True),
 | |
|                 (False, False),
 | |
|             ],
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     return sum([do_f(lhs, x) * do_f(rhs, y) for x, y in truth_tables[result][op]])
 | |
| 
 | |
| print(f("1^0|0|1", False))
 | |
| print(f("1|0|1|1", False))
 |