Skip to content

Commit feb6628

Browse files
reorganize code
1 parent e05f845 commit feb6628

File tree

11 files changed

+544
-513
lines changed

11 files changed

+544
-513
lines changed

hcl2/rule_transformer/__init__.py

Whitespace-only changes.

hcl2/rule_transformer/json.py

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
from json import JSONEncoder
2+
from typing import Any
3+
4+
from hcl2.rule_transformer.rules.abstract import LarkRule
5+
6+
7+
class LarkEncoder(JSONEncoder):
8+
def default(self, obj: Any):
9+
if isinstance(obj, LarkRule):
10+
return obj.serialize()
11+
else:
12+
return super().default(obj)

hcl2/rule_transformer/rules/__init__.py

Whitespace-only changes.
Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
from abc import ABC, abstractmethod
2+
from typing import Any, Union, List
3+
4+
from lark import Token, Tree
5+
from lark.tree import Meta
6+
7+
8+
class LarkElement(ABC):
9+
@abstractmethod
10+
def tree(self) -> Token:
11+
raise NotImplementedError()
12+
13+
@abstractmethod
14+
def serialize(self) -> Any:
15+
raise NotImplementedError()
16+
17+
18+
class LarkToken(LarkElement):
19+
def __init__(self, name: str, value: Union[str, int]):
20+
self._name = name
21+
self._value = value
22+
23+
@property
24+
def name(self) -> str:
25+
return self._name
26+
27+
@property
28+
def value(self):
29+
return self._value
30+
31+
def serialize(self) -> Any:
32+
return self._value
33+
34+
def tree(self) -> Token:
35+
return Token(self.name, self.value)
36+
37+
def __str__(self) -> str:
38+
return str(self._value)
39+
40+
def __repr__(self) -> str:
41+
return f"<LarkToken instance: {self._name} {self._value}>"
42+
43+
44+
class TokenSequence:
45+
def __init__(self, tokens: List[LarkToken]):
46+
self.tokens = tokens
47+
48+
def tree(self) -> List[Token]:
49+
return [token.tree() for token in self.tokens]
50+
51+
def joined(self):
52+
return "".join(str(token) for token in self.tokens)
53+
54+
55+
class LarkRule(ABC):
56+
@staticmethod
57+
@abstractmethod
58+
def rule_name() -> str:
59+
raise NotImplementedError()
60+
61+
@abstractmethod
62+
def serialize(self) -> Any:
63+
raise NotImplementedError()
64+
65+
@property
66+
def children(self) -> List[LarkElement]:
67+
return self._children
68+
69+
def tree(self) -> Tree:
70+
result_children = []
71+
for child in self._children:
72+
if child is None:
73+
continue
74+
75+
if isinstance(child, TokenSequence):
76+
result_children.extend(child.tree())
77+
else:
78+
result_children.append(child.tree())
79+
80+
return Tree(self.rule_name(), result_children)
81+
82+
def __init__(self, children, meta: Meta):
83+
self._children: List[LarkElement] = children
84+
self._meta = meta
85+
86+
def __repr__(self):
87+
return f"<LarkRule: {self.__class__.__name__} ({';'.join(str(child) for child in self._children)})>"

hcl2/rule_transformer/rules/base.py

Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
from typing import Tuple, Any, List, Union
2+
3+
from hcl2.rule_transformer.rules.abstract import LarkRule
4+
from hcl2.rule_transformer.rules.expression import EQ_Token, Expression
5+
from hcl2.rule_transformer.rules.token_sequence import IdentifierRule
6+
from hcl2.rule_transformer.rules.whitespace import NewLineOrCommentRule
7+
8+
9+
class AttributeRule(LarkRule):
10+
_children: Tuple[
11+
IdentifierRule,
12+
EQ_Token,
13+
Expression,
14+
]
15+
16+
@staticmethod
17+
def rule_name() -> str:
18+
return "attribute"
19+
20+
@property
21+
def identifier(self) -> IdentifierRule:
22+
return self._children[0]
23+
24+
@property
25+
def expression(self) -> Expression:
26+
return self._children[2]
27+
28+
def serialize(self) -> Any:
29+
return {self.identifier.serialize(): self.expression.serialize()}
30+
31+
32+
class BodyRule(LarkRule):
33+
34+
_children: List[
35+
Union[
36+
NewLineOrCommentRule,
37+
AttributeRule,
38+
"BlockRule",
39+
]
40+
]
41+
42+
@staticmethod
43+
def rule_name() -> str:
44+
return "body"
45+
46+
def serialize(self) -> Any:
47+
blocks: List[BlockRule] = []
48+
attributes: List[AttributeRule] = []
49+
comments = []
50+
51+
for child in self._children:
52+
if isinstance(child, BlockRule):
53+
blocks.append(child)
54+
if isinstance(child, AttributeRule):
55+
attributes.append(child)
56+
if isinstance(child, NewLineOrCommentRule):
57+
child_comments = child.actual_comments()
58+
if child_comments:
59+
comments.extend(child_comments)
60+
61+
result = {}
62+
63+
for attribute in attributes:
64+
result.update(
65+
{attribute.identifier.serialize(): attribute.expression.serialize()}
66+
)
67+
68+
result.update(
69+
{block.labels[0].serialize(): block.serialize() for block in blocks}
70+
)
71+
72+
if comments:
73+
result["__comments__"] = comments
74+
75+
return result
76+
77+
78+
class StartRule(LarkRule):
79+
80+
_children: Tuple[BodyRule]
81+
82+
@staticmethod
83+
def rule_name() -> str:
84+
return "start"
85+
86+
@property
87+
def body(self) -> BodyRule:
88+
return self._children[0]
89+
90+
def serialize(self) -> Any:
91+
return self.body.serialize()
92+
93+
94+
class BlockRule(LarkRule):
95+
@staticmethod
96+
def rule_name() -> str:
97+
return "block"
98+
99+
def __init__(self, children):
100+
super().__init__(children)
101+
*self._labels, self._body = children
102+
103+
@property
104+
def labels(self) -> List["IdentifierRule"]:
105+
return list(filter(lambda label: label is not None, self._labels))
106+
107+
@property
108+
def body(self) -> BodyRule:
109+
return self._body
110+
111+
def serialize(self) -> BodyRule:
112+
result = self._body.serialize()
113+
labels = self._labels
114+
for label in reversed(labels[1:]):
115+
result = {label.serialize(): result}
116+
return result
Lines changed: 174 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,174 @@
1+
from abc import ABC
2+
from typing import Any, Tuple, Optional
3+
4+
from lark import Tree, Token
5+
6+
from hcl2.rule_transformer.rules.abstract import LarkRule, LarkToken
7+
from hcl2.rule_transformer.rules.whitespace import NewLineOrCommentRule
8+
from hcl2.rule_transformer.rules.token_sequence import BinaryOperatorRule
9+
from hcl2.rule_transformer.utils import (
10+
wrap_into_parentheses,
11+
to_dollar_string,
12+
unwrap_dollar_string,
13+
)
14+
15+
EQ_Token = LarkToken
16+
17+
18+
class Expression(LarkRule, ABC):
19+
@staticmethod
20+
def rule_name() -> str:
21+
return "expression"
22+
23+
24+
class ExprTermRule(Expression):
25+
@staticmethod
26+
def rule_name() -> str:
27+
return "expr_term"
28+
29+
def __init__(self, children):
30+
self._parentheses = False
31+
if (
32+
isinstance(children[0], LarkToken)
33+
and children[0].name == "LPAR"
34+
and isinstance(children[-1], LarkToken)
35+
and children[-1].name == "RPAR"
36+
):
37+
self._parentheses = True
38+
children = children[1:-1]
39+
super().__init__(children)
40+
41+
@property
42+
def parentheses(self) -> bool:
43+
return self._parentheses
44+
45+
def serialize(self) -> Any:
46+
result = self._children[0].serialize()
47+
if self.parentheses:
48+
result = wrap_into_parentheses(result)
49+
result = to_dollar_string(result)
50+
return result
51+
52+
def tree(self) -> Tree:
53+
tree = super().tree()
54+
if self.parentheses:
55+
return Tree(
56+
tree.data, [Token("LPAR", "("), *tree.children, Token("RPAR", ")")]
57+
)
58+
return tree
59+
60+
61+
class ConditionalRule(ExprTermRule):
62+
63+
_children: Tuple[
64+
Expression,
65+
Expression,
66+
Expression,
67+
]
68+
69+
@staticmethod
70+
def rule_name():
71+
return "conditional"
72+
73+
@property
74+
def condition(self) -> Expression:
75+
return self._children[0]
76+
77+
@property
78+
def if_true(self) -> Expression:
79+
return self._children[1]
80+
81+
@property
82+
def if_false(self) -> Expression:
83+
return self._children[2]
84+
85+
def __init__(self, children):
86+
super().__init__(children)
87+
88+
def serialize(self) -> Any:
89+
result = f"{self.condition.serialize()} ? {self.if_true.serialize()} : {self.if_false.serialize()}"
90+
return to_dollar_string(result)
91+
92+
93+
class BinaryTermRule(LarkRule):
94+
95+
_children: Tuple[
96+
BinaryOperatorRule,
97+
Optional["NewLineOrCommentRule"],
98+
ExprTermRule,
99+
]
100+
101+
@staticmethod
102+
def rule_name() -> str:
103+
return "binary_term"
104+
105+
def __init__(self, children):
106+
if len(children) == 2:
107+
children.insert(1, None)
108+
super().__init__(children)
109+
110+
@property
111+
def binary_operator(self) -> BinaryOperatorRule:
112+
return self._children[0]
113+
114+
@property
115+
def comment(self) -> Optional[NewLineOrCommentRule]:
116+
return self._children[1]
117+
118+
@property
119+
def has_comment(self) -> bool:
120+
return self.comment is not None
121+
122+
@property
123+
def expr_term(self) -> ExprTermRule:
124+
return self._children[2]
125+
126+
def serialize(self) -> Any:
127+
return f"{self.binary_operator.serialize()} {self.expr_term.serialize()}"
128+
129+
130+
class UnaryOpRule(Expression):
131+
132+
_children: Tuple[LarkToken, ExprTermRule]
133+
134+
@staticmethod
135+
def rule_name() -> str:
136+
return "unary_op"
137+
138+
@property
139+
def operator(self) -> str:
140+
return str(self._children[0])
141+
142+
@property
143+
def expr_term(self):
144+
return self._children[1]
145+
146+
def serialize(self) -> Any:
147+
return to_dollar_string(f"{self.operator}{self.expr_term.serialize()}")
148+
149+
150+
class BinaryOpRule(Expression):
151+
_children: Tuple[
152+
ExprTermRule,
153+
BinaryTermRule,
154+
"NewLineOrCommentRule",
155+
]
156+
157+
@staticmethod
158+
def rule_name() -> str:
159+
return "binary_op"
160+
161+
@property
162+
def expr_term(self) -> ExprTermRule:
163+
return self._children[0]
164+
165+
@property
166+
def binary_term(self) -> BinaryTermRule:
167+
return self._children[1]
168+
169+
def serialize(self) -> Any:
170+
lhs = self.expr_term.serialize()
171+
operator = self.binary_term.binary_operator.serialize()
172+
rhs = self.binary_term.expr_term.serialize()
173+
rhs = unwrap_dollar_string(rhs)
174+
return to_dollar_string(f"{lhs} {operator} {rhs}")

0 commit comments

Comments
 (0)