0

For example, there is a given string

( a > b or a > c) and a < d

in python. I want to at first extract expression and logical operator from this statement, then check it one by one, such as

if a > b then check a < d, else check a > c then check a < d

I don‘t know how to extract it in the logical order. Thanks a lot for help.

3
  • You need to write a parser to break it down into individual expressions. You can use a library like pyparsing for this. Commented Feb 5, 2024 at 16:31
  • BTW, your proposed way to check one by one corresponds to (a > b and a < d) or (a > c or a < d). They're equivalent due to the distributive property, but it's not what a straightforward parse would produce. Commented Feb 5, 2024 at 16:33
  • 1
    Are you looking for just a true/false evaluation, or something more complex? If it's a simple evaluation, have you tried the solutions proposed in stackoverflow.com/questions/2467590/… ? Commented Feb 5, 2024 at 16:42

1 Answer 1

0

You can use Abstract Syntax Trees module to do this. It allows you to parse Python codes and work with its abstract syntax tree.

import ast

def evaluateComparison(node):
    left_operand = ast.literal_eval(node.left)
    right_operand = ast.literal_eval(node.comparators[0])
    comparison_operator = type(node.ops[0]).__name__

    if comparison_operator == 'Lt':
        return left_operand < right_operand
    elif comparison_operator == 'Gt':
        return left_operand > right_operand
    elif comparison_operator == 'LtE':
        return left_operand <= right_operand
    elif comparison_operator == 'GtE':
        return left_operand >= right_operand
    elif comparison_operator == 'Eq':
        return left_operand == right_operand
    elif comparison_operator == 'NotEq':
        return left_operand != right_operand
    else:
        raise ValueError(f"Unsupported comparison operator: {comparison_operator}")

def getOperatorSymbol(operator_name):
    operator_mapping = {
        'Lt': '<',
        'Gt': '>',
        'LtE': '<=',
        'GtE': '>=',
        'Eq': '==',
        'NotEq': '!='
    }
    return operator_mapping.get(operator_name, operator_name)

def processNode(node, indent=''):
    if isinstance(node, ast.BoolOp):
        # Logical operator (and/or)
        operator = type(node.op).__name__
        left_result = processNode(node.values[0], indent)
        right_result = processNode(node.values[1], '')
        return f"{left_result} {operator} {right_result}"

    elif isinstance(node, ast.Compare):
        # Comparison operator (<, >, <=, >=, ==, !=)
        result = evaluateComparison(node)
        left_operand = ast.unparse(node.left).strip()
        comparison_operator = getOperatorSymbol(type(node.ops[0]).__name__)
        right_operand = ast.unparse(node.comparators[0]).strip()
        return f"{indent}{left_operand} {comparison_operator} {right_operand} (Result: {result})"

Output for this code is:

# Example
logical_statement = "(3 > 2 or 3 > 4) and 3 < 5"
result = processNode(ast.parse(logical_statement, mode='eval').body)
print(f"The result is:\n{result}")

#Output
The result is:
3 > 2 (Result: True) Or 3 > 4 (Result: False) And 3 < 5 (Result: True)

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.