Parses a complex boolean expression involving state keys. Args: expression (str): The boolean expression to parse. state (dict): Dictionary of state keys used to evaluate the expression. Raises: ValueError: If the expression is empty, has adjacent state keys wi
(expression, state: dict)
| 6 | |
| 7 | |
| 8 | def parse_expression(expression, state: dict) -> list: |
| 9 | """ |
| 10 | Parses a complex boolean expression involving state keys. |
| 11 | |
| 12 | Args: |
| 13 | expression (str): The boolean expression to parse. |
| 14 | state (dict): Dictionary of state keys used to evaluate the expression. |
| 15 | |
| 16 | Raises: |
| 17 | ValueError: If the expression is empty, has adjacent state keys without operators, |
| 18 | invalid operator usage, unbalanced parentheses, or if no state keys match the expression. |
| 19 | |
| 20 | Returns: |
| 21 | list: A list of state keys that match the boolean expression, |
| 22 | ensuring each key appears only once. |
| 23 | |
| 24 | Example: |
| 25 | >>> parse_expression("user_input & (relevant_chunks | parsed_document | document)", |
| 26 | {"user_input": None, "document": None, |
| 27 | "parsed_document": None, "relevant_chunks": None}) |
| 28 | ['user_input', 'relevant_chunks', 'parsed_document', 'document'] |
| 29 | |
| 30 | This function evaluates the expression to determine the |
| 31 | logical inclusion of state keys based on provided boolean logic. |
| 32 | It checks for syntax errors such as unbalanced parentheses, |
| 33 | incorrect adjacency of operators, and empty expressions. |
| 34 | """ |
| 35 | |
| 36 | if not expression: |
| 37 | raise ValueError("Empty expression.") |
| 38 | |
| 39 | pattern = ( |
| 40 | r"\b(" |
| 41 | + "|".join(re.escape(key) for key in state.keys()) |
| 42 | + r")(\b\s*\b)(" |
| 43 | + "|".join(re.escape(key) for key in state.keys()) |
| 44 | + r")\b" |
| 45 | ) |
| 46 | if re.search(pattern, expression): |
| 47 | raise ValueError("Adjacent state keys found without an operator between them.") |
| 48 | |
| 49 | expression = expression.replace(" ", "") |
| 50 | |
| 51 | if ( |
| 52 | expression[0] in "&|" |
| 53 | or expression[-1] in "&|" |
| 54 | or "&&" in expression |
| 55 | or "||" in expression |
| 56 | or "&|" in expression |
| 57 | or "|&" in expression |
| 58 | ): |
| 59 | raise ValueError("Invalid operator usage.") |
| 60 | |
| 61 | open_parentheses = close_parentheses = 0 |
| 62 | for i, char in enumerate(expression): |
| 63 | if char == "(": |
| 64 | open_parentheses += 1 |
| 65 | elif char == ")": |