Bartłomiej Bartnicki
Bartłomiej Bartnicki

Reputation: 1175

evaluating bool in pyparsing

I have based my code on http://pyparsing.wikispaces.com/file/view/simpleBool.py/451074414/simpleBool.py I want to parse language generating words like this:

ABC:"a" and BCA:"b" or ABC:"d"

After parsing I want to evaluate bool value of this expresion. In code I have dict with key ABC and BCA, and ABC:"a" mean "a" in dict[ABC].

Somewhere I make mistake but I can not find where, conversion to bool always return True.

output:

DEBUG self.value=True

[ABC:"a"[True]] True

DEBUG self.value=False

[ABC:"h"[False]] True

code:

from pyparsing import infixNotation, opAssoc, Keyword, Word, alphas, dblQuotedString, removeQuotes

d = {
    "ABC": "TEST abc TEST",
    "BCA": "TEST abc TEST",
}


class BoolOperand:
    def __init__(self, t):
        self.value = t[2] in d[t[0]]
        print(F"DEBUG self.value={self.value}")
        self.label = f"{t[0]}:\"{t[2]}\"[{str(self.value)}]"

    def __bool__(self):
        print("GET V")
        return self.value

    def __str__(self):
        return self.label

    __nonzero__ = __bool__
    __repr__ = __str__


class BoolBinOp:
    def __init__(self, t):
        self.args = t[0][0::2]

    def __str__(self):
        sep = " %s " % self.reprsymbol
        return "(" + sep.join(map(str, self.args)) + ")"

    def __bool__(self):
        print("DEBUG BoolBinOp")
        return self.evalop(bool(a) for a in self.args)

    __nonzero__ = __bool__
    __repr__ = __str__


class BoolAnd(BoolBinOp):
    reprsymbol = '&'
    evalop = all


class BoolOr(BoolBinOp):
    reprsymbol = '|'
    evalop = any


class BoolNot:
    def __init__(self, t):
        self.arg = t[0][1]

    def __bool__(self):
        print("DEBUG BoolNot")
        v = bool(self.arg)
        return not v

    def __str__(self):
        return "~" + str(self.arg)

    __repr__ = __str__
    __nonzero__ = __bool__


EXPRESSION = Word(alphas) + ":" + dblQuotedString().setParseAction(removeQuotes)
TRUE = Keyword("True")
FALSE = Keyword("False")
boolOperand = TRUE | FALSE  | EXPRESSION
boolOperand.setParseAction(BoolOperand)

boolExpr = infixNotation(boolOperand,
                         [
                             ("not", 1, opAssoc.RIGHT, BoolNot),
                             ("and", 2, opAssoc.LEFT, BoolAnd),
                             ("or", 2, opAssoc.LEFT, BoolOr),
                         ])

if __name__ == "__main__":
    res = boolExpr.parseString('ABC:"a"')
    print(res, "\t", bool(res))
    print("\n\n")
    res = boolExpr.parseString('ABC:"h"')
    print(res, "\t", bool(res))

Upvotes: 1

Views: 378

Answers (1)

PaulMcG
PaulMcG

Reputation: 63747

If at the end of your program you add:

print(type(res), bool(res))
print(type(res[0]), bool(res[0]))

You'll see

<class 'pyparsing.ParseResults'> True
GET V
<class '__main__.BoolOperand'> False

res is not your parsed operand, it is a ParseResults container of your parsed operand. If you evaluate res[0] you'll see how your operand is evaluating.

ParseResults will have similar behavior as lists with respect to bool. If non-empty, they will be True, if empty they will be False. Add these lines to your program:

res.pop(0)
print(bool(res))

And you'll see the ParseResults is False, indicating that it has no contents.

Upvotes: 1

Related Questions