code: def expr(s):
      
      if isinstance(s, Expr): return s
      if isnumber(s): return Expr(s)
      ## Replace the alternative spellings of operators with canonical spellings
      s = s.replace('==>', '>>').replace('<==', '<<')
      s = s.replace('<=>', '%').replace('=/=', '^')
      ## Replace a symbol or number, such as 'P' with 'Expr("P")'
      s = re.sub(r'([a-zA-Z0-9_.]+)', r'Expr("\1")', s)
      ## Now eval the string.  (A security hole; do not use with an adversary.)
      return eval(s, {'Expr':Expr})
docs: Create an Expr representing a logic expression by parsing the input
      string. Symbols and numbers are automatically converted to Exprs.
      In addition you can use alternative spellings of these operators:
        'x ==> y'   parses as   (x >> y)    # Implication
        'x <== y'   parses as   (x << y)    # Reverse implication
        'x <=> y'   parses as   (x % y)     # Logical equivalence
        'x =/= y'   parses as   (x ^ y)     # Logical disequality (xor)
      But BE CAREFUL; precedence of implication is wrong. expr('P & Q ==> R & S')
      is ((P & (Q >> R)) & S); so you must use expr('(P & Q) ==> (R & S)').
      >>> expr('P <=> Q(1)')
      (P <=> Q(1))
      >>> expr('P & Q | ~R(x, F(x))')
      ((P & Q) | ~R(x, F(x)))