2 # vim: set fileencoding=utf8
3 # Created: April 5, 2008
6 # Extended Trinary Evaluator: Evaluates trinary expression containing unary
18 u
"?" : {False:"i01", None:"001", True:"111"}, # TOR
19 u
"?" : {False:"iii", None:"i00", True:"i01"}, # TAND
20 u
"?" : {False:"111", None:"100", True:"10i"}, # TNAND
21 u
"?" : {False:"10i", None:"00i", True:"111"}, # TNOR
23 # Alternate notation, sometimes easier to type
24 u
"+" : {False:"i01", None:"001", True:"111"},
25 u
"*" : {False:"iii", None:"i00", True:"i01"},
28 u
"?" : {False:"i01", None:"001", True:"111"}, # max
29 u
"?" : {False:"iii", None:"i00", True:"i01"}, # min
30 u
"?" : {False:"i01", None:"0i1", True:"11i"}, # exclusive max
34 def expr_dyadic(expression
, variables
):
35 ''' This function applies a dyatic function.
36 Recurses down string by calling expr_recurse.
38 if not expression
[0] in trit_char
:
39 first
= variables
[expression
[0]]
43 f_value
= trit_bool
[first
]
45 if len(expression
) == 1:
48 f_next
= expression
[1]
50 # found dyatic function. apply the function
51 if f_next
in dyadic_functions
:
52 f_apply
= dyadic_functions
[f_next
]
53 result
, next_expr
= expr_recurse(expression
[2:], variables
)
55 t_func
= Trits(f_apply
[f_value
])
56 t_sec
= Trits(trit_string
[result
])
57 return (evaluate_unary(t_func
, t_sec
))[0], next_expr
59 # found left paren. apply */AND
61 # first ( something ) => first AND something
63 # apply AND to 'first' variable
64 f_apply
= dyadic_functions
["*"]
65 t_func
= Trits(f_apply
[f_value
])
67 # grab the expr to apply AND next
68 result
, next_expr
= expr_recurse(expression
[2:], variables
)
69 if next_expr
[0] != ")":
70 raise ("Expected \")\", found \"%s\"" % (next_expr
[0])).encode("utf8")
72 # evaluate: first AND (something)
73 t_sec
= Trits(trit_string
[result
])
74 result
= (evaluate_unary(t_func
, t_sec
))[0]
75 next_expr
= next_expr
[1:]
77 # evaluate: (first AND something)(AND (next))*
78 while len(next_expr
) > 1:
79 t_func
= Trits(f_apply
[result
])
80 result
, next_expr
= expr_recurse(next_expr
, variables
)
81 t_sec
= Trits(trit_string
[result
])
82 result
= (evaluate_unary(t_func
, t_sec
))[0]
84 return result
, next_expr
86 elif f_next
.isalpha():
89 # grab function to use and grab the name of the second variable
90 f_apply
= dyadic_functions
["*"]
91 second
= variables
[f_next
]
93 # apply * to 'first' variable and parse second to trit
94 t_func
= Trits(f_apply
[f_value
])
95 t_sec
= Trits(trit_string
[trit_bool
[second
]])
97 # apply first * second, return (result, remaining expression string)
98 return (evaluate_unary(t_func
, t_sec
))[0], expression
[2:]
101 return (f_value
, expression
[1:])
103 def expr_unary(expression
, variables
):
105 while expression
[count
] in unary_functions
:
108 func
= expression
[:count
]
111 result
, next
= expr_recurse(expression
[count
:], variables
)
113 return ((e
.evaluate(Trits(trit_string
[result
])))[0], next
)
115 def expr_recurse(expression
, variables
):
116 if expression
[0] in unary_functions
:
117 return expr_unary(expression
, variables
)
118 elif expression
[0].isalpha():
119 return expr_dyadic(expression
, variables
)
120 elif expression
[0].isdigit():
121 return expr_dyadic(expression
, variables
)
122 elif expression
[0] == "(":
123 expression
= expression
[1:]
124 result
, next
= expr_recurse(expression
, variables
)
126 raise ("Expected \")\", found \"%s\"" % (next
[0])).encode("utf8")
129 f_apply
= dyadic_functions
["*"]
131 # evaluate: (result)(AND (next))*
133 t_func
= Trits(f_apply
[result
])
134 result
, next
= expr_recurse(next
, variables
)
135 t_sec
= Trits(trit_string
[result
])
136 result
= (evaluate_unary(t_func
, t_sec
))[0]
140 raise ("Unexpected character found \"%s\"" % (expression
[0])).encode("utf8")
142 def trinary_eval(expression
, variables
):
143 u
'''Evaluates trinary expression. Unary and Dyadic functions supported:
144 Unary: /, ?, ?, ¬, ?, ?, ?, ?, ?, ?
145 Dyadic: see 'dyadic_functions' module global
146 expression: String containing expression to evalutate
147 variables: dictionary of variables and their values
148 returns: The result of evaluating the expression.
150 >>> print trinary_eval("//A+B", {"A" : "i01", "B" : "1"})
152 >>> print trinary_eval("//A+B", {"A" : "1", "B" : "0"})
154 >>> print trinary_eval("//A+B", {"A" : "i", "B" : "0"})
156 >>> print trinary_eval("//A+B", {"A" : "0", "B" : "0"})
158 >>> print trinary_eval("//A+B", {"A" : "0", "B" : "1"})
160 >>> print trinary_eval("/(A+/B*C)",{"A":"0","B":"0","C":"1"})
162 >>> print trinary_eval("A?(/B*C)",{"A":"0","B":"0","C":"1"})
164 >>> print trinary_eval("A?(/B?C)",{"A":"0","B":"0","C":"1"})
171 if len(variables
[i
]) > max_len
:
172 max_len
= len(variables
[i
])
175 result
, lo
= expr_recurse(expression
, variables
)
176 return trit_string
[result
]
182 for i
in range(max_len
):
185 if len(variables
[j
]) > 1:
186 func_vars
[j
] = variables
[j
][i
]
188 func_vars
[j
] = variables
[j
]
189 tmp
, lo
= expr_recurse(expression
, func_vars
)
190 result
+= trit_string
[tmp
]
195 if __name__
== "__main__":
205 line
= unicode(sys
.stdin
.readline(), "utf8")
211 assignments
= line
.split(",")
212 for a
in assignments
:
213 name
, value
= a
.split("=")
216 print "i is reserved, cannot be used as a variable name"
219 if not k
in trit_char
:
220 print u
"%s, not a valid value" % (k
)
223 print u
"Assigning %s to %s" % (name
, value
)
224 variables
[name
] = value
227 for k
, v
in variables
.iteritems():
228 print u
"%s: %s" % (k
, v
)
229 elif line
in trit_char
:
233 print trinary_eval(line
, variables
)
235 print "An error occured:"
236 traceback
.print_exc()