1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
|
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
|