@@ -373,10 +373,11 @@ def __floordiv__(self, rhs): return Expr('//', self, rhs)
373373 def __matmul__ (self , rhs ): return Expr ('@' , self , rhs )
374374
375375 def __or__ (self , rhs ):
376+ "Allow both P | Q, and P |'==>'| Q."
376377 if isinstance (rhs , Expression ) :
377378 return Expr ('|' , self , rhs )
378379 else :
379- return NotImplemented # So that InfixOp can handle it
380+ return PartialExpr ( rhs , self )
380381
381382 # Reverse operator overloads
382383 def __radd__ (self , lhs ): return Expr ('+' , lhs , self )
@@ -451,37 +452,34 @@ def arity(expression):
451452
452453# For operators that are not defined in Python, we allow new InfixOps:
453454
454- class InfixOp :
455- """Allow 'P |implies| Q, where P, Q are Exprs and implies is an InfixOp."""
456- def __init__ (self , op , lhs = None ): self .op , self .lhs = op , lhs
457- def __call__ (self , lhs , rhs ): return Expr (self .op , lhs , rhs )
458- def __or__ (self , rhs ): return Expr (self .op , self .lhs , rhs )
459- def __ror__ (self , lhs ): return InfixOp (self .op , lhs )
460- def __repr__ (self ): return "InfixOp('{}', {})" .format (self .op , self .lhs )
461-
462- infix_ops = (implies , rimplies , equiv ) = [InfixOp (o ) for o in ['==>' , '<==' , '<=>' ]]
455+ class PartialExpr :
456+ """Given 'P |'==>'| Q, first form PartialExpr('==>', P), then combine with Q."""
457+ def __init__ (self , op , lhs ): self .op , self .lhs = op , lhs
458+ def __or__ (self , rhs ): return Expr (self .op , self .lhs , rhs )
459+ def __repr__ (self ): return "PartialExpr('{}', {})" .format (self .op , self .lhs )
463460
464461def expr (x ):
465462 """Shortcut to create an Expression. x is a str in which:
466463 - identifiers are automatically defined as Symbols.
467- - ' ==>' is treated as an infix |implies |, as are all infix_ops
464+ - ==> is treated as an infix |'==>' |, as are <== and <=>.
468465 If x is already an Expression, it is returned unchanged. Example:
469466 >>> expr('P & Q ==> Q')
470467 ((P & Q) ==> Q)
471468 """
472469 if isinstance (x , str ):
473- return eval (expr_handle_infix_ops (x ),
474- defaultkeydict (Symbol , InfixOp = InfixOp ))
470+ return eval (expr_handle_infix_ops (x ), defaultkeydict (Symbol ))
475471 else :
476472 return x
477473
474+ infix_ops = '==> <== <=>' .split ()
475+
478476def expr_handle_infix_ops (x ):
479- """Given a str, return a new str with ' ==>' replaced by |InfixOp( '==>') |, etc.
477+ """Given a str, return a new str with ==> replaced by |'==>'|, etc.
480478 >>> expr_handle_infix_ops('P ==> Q')
481- "P |InfixOp( '==>', None) | Q"
479+ "P |'==>'| Q"
482480 """
483481 for op in infix_ops :
484- x = x .replace (op . op , '|' + str (op ) + '|' )
482+ x = x .replace (op , '|' + repr (op ) + '|' )
485483 return x
486484
487485class defaultkeydict (collections .defaultdict ):
0 commit comments