summaryrefslogtreecommitdiff
path: root/htmtl/expression_parser.py
blob: c27b8f4bc6c0eba0656037a5396f5c695ae5da80 (plain)
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 Dict, Any
from .expression_modifier import ExpressionModifier


class ExpressionParser:
    __data: Dict[str, Any]
    __expression_modifiers: list[type[ExpressionModifier]]

    def __init__(self, data: Dict[str, Any], expression_modifiers: list[type[ExpressionModifier]]) -> 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