from typing import Any from .modifier import Modifier class ExpressionParser: __data: dict[str, Any] __expression_modifiers: list[type[Modifier]] def __init__(self, data: dict[str, Any], expression_modifiers: list[type[Modifier]]) -> None: self.__data = data self.__expression_modifiers = expression_modifiers def parse(self, expression: str) -> Any: # no curly brackets means that the whole thing is an interpolation if expression.count("{") != expression.count("}"): parsed_interpolation = self.__parse_interpolation(expression) return parsed_interpolation # otherwise only parts of it are parsed_expression = "" interp_start = None interp_end = None for idx, char in enumerate(expression): parsed_expression += char if char == "{": interp_start = idx if char == "}": interp_end = idx + 1 if interp_start is not None and interp_end is not None: interp = expression[interp_start:interp_end] parsed_expression = parsed_expression.replace(interp, self.__parse_interpolation(interp[1:-1])) interp_start = None interp_end = None return parsed_expression def __parse_interpolation(self, interpolation: str) -> Any: parts = interpolation.split("|") value = self.__var_to_val(parts[0].strip()) modifiers = [x.strip() for x in parts[1:]] if len(parts) > 1 else [] for modifier in modifiers: modifier_parts = modifier.split(":") modifier_name = modifier_parts[0].strip() modifier_opts = [x.strip() for x in modifier_parts[1:]] if len(modifier_parts) > 1 else [] value = self.__use_modifier(value, modifier_name, modifier_opts) return value def __use_modifier(self, value: Any, modifier_name: str, modifier_opts: list[Any]) -> Any: for modifier in self.__expression_modifiers: modifier_instance = modifier() if modifier_instance.name == modifier_name: return modifier_instance.modify(value, modifier_opts) return value def __var_to_val(self, var: str) -> Any: parts = var.split(".") value = self.__data for part in parts: if part in value: value = value[part] else: return None return value