summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorptmcg <ptmcg@9bf210a0-9d2d-494c-87cf-cfb32e7dff7b>2013-09-14 12:21:13 +0000
committerptmcg <ptmcg@9bf210a0-9d2d-494c-87cf-cfb32e7dff7b>2013-09-14 12:21:13 +0000
commit2ef4170799835f86b1a82385df340a57673779a7 (patch)
tree556ac54acfe1e34e28ea42641319af3737f465cf
parent455707b40fff2ce15967ef380097b0cd8fc228fc (diff)
downloadpyparsing-2ef4170799835f86b1a82385df340a57673779a7.tar.gz
Fix Python 2.x/3.x compatibility (now that Pyparsing 2.0.x includes Python 2.6+ compatibility) - also fix bug with expressions that consist solely of a single term with no operations; and reorg class hierarchy for better DRY
git-svn-id: svn://svn.code.sf.net/p/pyparsing/code/trunk@257 9bf210a0-9d2d-494c-87cf-cfb32e7dff7b
-rw-r--r--src/examples/simpleBool.py124
1 files changed, 69 insertions, 55 deletions
diff --git a/src/examples/simpleBool.py b/src/examples/simpleBool.py
index 0688787..5f355b7 100644
--- a/src/examples/simpleBool.py
+++ b/src/examples/simpleBool.py
@@ -6,83 +6,97 @@
#
# In this example, parse actions associated with each
# operator expression will "compile" the expression
-# into BoolOperand subclass objects, which can then
+# into BoolXXX class instances, which can then
# later be evaluated for their boolean value.
#
# Copyright 2006, by Paul McGuire
+# Updated 2013-Sep-14 - improved Python 2/3 cross-compatibility
#
+from pyparsing import infixNotation, opAssoc, Keyword, Word, alphas
-from pyparsing import *
-
+# define classes to be built at parse time, as each matching
+# expression type is parsed
class BoolOperand(object):
def __init__(self,t):
+ self.label = t[0]
+ self.value = eval(t[0])
+ def __bool__(self):
+ return self.value
+ def __str__(self):
+ return self.label
+ __repr__ = __str__
+ __nonzero__ = __bool__
+
+class BoolBinOp(object):
+ def __init__(self,t):
self.args = t[0][0::2]
def __str__(self):
sep = " %s " % self.reprsymbol
return "(" + sep.join(map(str,self.args)) + ")"
-
-class BoolAnd(BoolOperand):
- reprsymbol = '&'
def __bool__(self):
- for a in self.args:
- if isinstance(a,str):
- v = eval(a)
- else:
- v = bool(a)
- if not v:
- return False
- return True
+ return self.evalop(bool(a) for a in self.args)
+ __nonzero__ = __bool__
+ __repr__ = __str__
-class BoolOr(BoolOperand):
- reprsymbol = '|'
- def __bool__(self):
- for a in self.args:
- if isinstance(a,str):
- v = eval(a)
- else:
- v = bool(a)
- if v:
- return True
- return False
+class BoolAnd(BoolBinOp):
+ reprsymbol = '&'
+ evalop = all
+
+class BoolOr(BoolBinOp):
+ reprsymbol = '|'
+ evalop = any
-class BoolNot(BoolOperand):
+class BoolNot(object):
def __init__(self,t):
self.arg = t[0][1]
- def __str__(self):
- return "~" + str(self.arg)
def __bool__(self):
- if isinstance(self.arg,str):
- v = eval(self.arg)
- else:
- v = bool(self.arg)
+ v = bool(self.arg)
return not v
+ def __str__(self):
+ return "~" + str(self.arg)
+ __repr__ = __str__
+ __nonzero__ = __bool__
+
+TRUE = Keyword("True")
+FALSE = Keyword("False")
+boolOperand = TRUE | FALSE | Word(alphas,max=1)
+boolOperand.setParseAction(BoolOperand)
-boolOperand = Word(alphas,max=1) | oneOf("True False")
-boolExpr = operatorPrecedence( boolOperand,
+# define expression, based on expression operand and
+# list of operations in precedence order
+boolExpr = infixNotation( boolOperand,
[
("not", 1, opAssoc.RIGHT, BoolNot),
("and", 2, opAssoc.LEFT, BoolAnd),
("or", 2, opAssoc.LEFT, BoolOr),
])
-test = ["p and not q",
- "not not p",
- "not(p and q)",
- "q or not p and r",
- "q or not p or not r",
- "q or not (p and r)",
- "p or q or r",
- "p or q or r and False",
- "(p or q or r) and False",
- ]
-p = True
-q = False
-r = True
-print("p =", p)
-print("q =", q)
-print("r =", r)
-print()
-for t in test:
- res = boolExpr.parseString(t)[0]
- print(t,'\n', res, '=', bool(res),'\n')
-
+
+if __name__ == "__main__":
+ p = True
+ q = False
+ r = True
+ tests = [("p", True),
+ ("q", False),
+ ("p and q", False),
+ ("p and not q", True),
+ ("not not p", True),
+ ("not(p and q)", True),
+ ("q or not p and r", False),
+ ("q or not p or not r", False),
+ ("q or not (p and r)", False),
+ ("p or q or r", True),
+ ("p or q or r and False", True),
+ ("(p or q or r) and False", False),
+ ]
+
+ print("p =", p)
+ print("q =", q)
+ print("r =", r)
+ print()
+ for t,expected in tests:
+ res = boolExpr.parseString(t)[0]
+ success = "PASS" if bool(res) == expected else "FAIL"
+ print (t,'\n', res, '=', bool(res),'\n', success, '\n')
+
+