Оценщик вложенных выражений - PullRequest
0 голосов
/ 28 февраля 2019

Я хотел бы сделать вычислитель выражений с pyparsing следующим образом:

Анализируемые строки должны быть обычными выражениями, использующими комбинации ~ & |символы (для not и or с, скажем, таким порядком приоритета) со строками определенного формата (пока что для каждой буквы используются только отдельные буквы, от a до z), где каждая буква оценивается как список логических значений с помощью пользовательской функции (предположим, f), и~ & |операции с каждым логическим списком должны применяться поточечно.

т.е.

a=[True, False] -> a=[True, False]
a=[True, False] -> ~a=[False, True]
a=[True, False] -> ~~a=[True, False]
a=[True, False] -> (((a)))=[True, False]
a=[True, False], b=[False,False], c=[True, True] -> ((a|b)&(~c))=[False, False]

к любому вложенному уровню.

Любые предложения приветствуются.

РЕДАКТИРОВАТЬ: После прочтения комментария, а также опубликованной электронной книги автора комментария "Начало работы с Pyparsing" (O'Reilly), я попал сюда:

class UnaryOperation(object):
    def __init__(self, tokens):
        self.operator, self.operand = tokens[0]
class BinaryOperation(object):
    def __init__(self, tokens):
        self.operator = tokens[0][1]
        self.operands = tokens[0][0::2]
class SearchNot(UnaryOperation):
    def generateExpression(self):
        return u'~{}'.format(self.operand.generateExpression())
class SearchAnd(BinaryOperation):
    def generateExpression(self):
        return u'({})'.format('&'.join(op.generateExpression() for op in self.operands))
class SearchOr(BinaryOperation):
    def generateExpression(self):
        return u'({})'.format('|'.join(op.generateExpression() for op in self.operands))
class ConditionString(object):
    def __init__(self, tokens):
        self.term = tokens[0]
    def generateExpression(self):
        return str(mapper(self.term))

def mapper(input_string):
    p = True
    q = False
    r = True
    d = {u'b_1':[p,q,r],
     u'a_1':[r,q,q],
     u'c2':[p,p,r],
     u'a1':[q,q,r],
     u'a':[r,r,p],
     u'd1':[q,p,p]}
    return d[input_string] if input_string in d.keys() else 3*[True]



qname = Word(alphas+u'_', alphanums+u'_')
expression = operatorPrecedence(qname.setParseAction(ConditionString),
                                [(u'~', 1, opAssoc.RIGHT, SearchNot),
                                 (u'&', 2, opAssoc.LEFT, SearchAnd),
                                 (u'|', 2, opAssoc.LEFT, SearchOr)])
tests = [
         u'b_1',
         u'~a_1',
         u'b_1&~c2',
         u'~a1|(a&(((c2|d_1))))',
         u'a&a1&b_1|c2'
            ]

for t in tests:
    try:
        evalStack = (expression + stringEnd).parseString(t)[0]
    except ParseException, pe:
        print "Invalid search string"
        continue
    evalExpr = evalStack.generateExpression()
    print "Eval expr: ", evalExpr

, которая распечатает

Eval expr:  [True, False, True]
Eval expr:  ~[True, False, False]
Eval expr:  ([True, False, True]&~[True, True, True])
Eval expr:  (~[False, False, True]|([True, True, True]&([True, True, True]|[True, True, True])))
Eval expr:  (([True, True, True]&[False, False, True]&[True, False, True])|[True, True, True])

, что-то похожее на пример, представленный на страницах 59-60, но как мы могли бы продолжить таким же образом с eval (), используемым там (но для множеств)?

1 Ответ

0 голосов
/ 03 марта 2019

Чтобы добавить оценку, добавьте eval() методы к каждому из ваших классов.Каждый метод eval () будет выполнять соответствующую операцию в ваших списках bools:

list_wise_op(op, operands):
    return [op(a_b) for a_b in zip(operands)]

# ConditionString
    def eval(self):
        return mapper(self.term)

#SearchNot
    def eval(self):
        return [not x for x in self.operand.eval()]

# SearchAnd
    def eval(self):
        return list_wise_op(all, [op.eval() for op in self.operands])

# SearchOr
    def eval(self):
        return list_wise_op(any, [op.eval() for op in self.operands])

Теперь вы сможете вызывать evalstack.eval().

...