Skip to content

Commit f72ab4d

Browse files
batch of changes
1 parent aba419f commit f72ab4d

17 files changed

+835
-312
lines changed

hcl2/parser.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
def parser() -> Lark:
1313
"""Build standard parser for transforming HCL2 text into python structures"""
1414
return Lark.open(
15-
"rule_transformer/hcl2.lark.lark",
15+
"rule_transformer/hcl2.lark",
1616
parser="lalr",
1717
cache=str(PARSER_FILE), # Disable/Delete file to effect changes to the grammar
1818
rel_to=__file__,

hcl2/reconstructor.py

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -166,12 +166,17 @@ def _should_add_space(self, rule, current_terminal, is_block_label: bool = False
166166
if self._is_equals_sign(current_terminal):
167167
return True
168168

169+
if is_block_label:
170+
pass
171+
# print(rule, self._last_rule, current_terminal, self._last_terminal)
172+
169173
if is_block_label and isinstance(rule, Token) and rule.value == "string":
170174
if (
171175
current_terminal == self._last_terminal == Terminal("DBLQUOTE")
172176
or current_terminal == Terminal("DBLQUOTE")
173-
and self._last_terminal == Terminal("NAME")
177+
and self._last_terminal == Terminal("IDENTIFIER")
174178
):
179+
# print("true")
175180
return True
176181

177182
# if we're in a ternary or binary operator, add space around the operator

hcl2/rule_transformer/deserializer.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import json
2+
from typing import Any, TextIO, List
3+
4+
from hcl2.rule_transformer.rules.abstract import LarkElement, LarkRule
5+
from hcl2.rule_transformer.utils import DeserializationOptions
6+
7+
8+
class Deserializer:
9+
def __init__(self, options=DeserializationOptions()):
10+
self.options = options
11+
12+
def load_python(self, value: Any) -> LarkElement:
13+
pass
14+
15+
def loads(self, value: str) -> LarkElement:
16+
return self.load_python(json.loads(value))
17+
18+
def load(self, file: TextIO) -> LarkElement:
19+
return self.loads(file.read())
20+
21+
def _deserialize(self, value: Any) -> LarkElement:
22+
pass
23+
24+
def _deserialize_dict(self, value: dict) -> LarkRule:
25+
pass
26+
27+
def _deserialize_list(self, value: List) -> LarkRule:
28+
pass
29+
30+
def _deserialize_expression(self, value: str) -> LarkRule:
31+
pass

hcl2/rule_transformer/hcl2.lark

Lines changed: 11 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,9 @@ IN : "in"
1111
FOR : "for"
1212
FOR_EACH : "for_each"
1313

14-
// Identifiers and Names
15-
NAME : /[a-zA-Z_][a-zA-Z0-9_-]*/
16-
IDENTIFIER: NAME | IN | FOR | IF | FOR_EACH
1714

1815
// Literals
16+
NAME : /[a-zA-Z_][a-zA-Z0-9_-]*/
1917
ESCAPED_INTERPOLATION.2: /\$\$\{[^}]*\}/
2018
STRING_CHARS.1: /(?:(?!\$\$\{)(?!\$\{)[^"\\]|\\.|(?:\$(?!\$?\{)))+/
2119
DECIMAL : "0".."9"
@@ -91,7 +89,8 @@ block : identifier (identifier | string)* new_line_or_comment? LBRACE body RBRAC
9189
new_line_or_comment: ( NL_OR_COMMENT )+
9290

9391
// Basic literals and identifiers
94-
identifier: IDENTIFIER
92+
identifier : NAME
93+
keyword: IN | FOR | IF | FOR_EACH
9594
int_lit: INT_LITERAL
9695
float_lit: FLOAT_LITERAL
9796
string: DBLQUOTE string_part* DBLQUOTE
@@ -118,21 +117,20 @@ expr_term : LPAR new_line_or_comment? expression new_line_or_comment? RPAR
118117
| string
119118
| tuple
120119
| object
121-
| function_call
122-
| index_expr_term
123-
| get_attr_expr_term
124120
| identifier
125-
| provider_function_call
121+
| function_call
126122
| heredoc_template
127123
| heredoc_template_trim
124+
| index_expr_term
125+
| get_attr_expr_term
128126
| attr_splat_expr_term
129127
| full_splat_expr_term
130128
| for_tuple_expr
131129
| for_object_expr
132130

133131
// Collections
134-
tuple : LSQB (new_line_or_comment* expression new_line_or_comment* COMMA)* (new_line_or_comment* expression)? new_line_or_comment* RSQB
135-
object : LBRACE new_line_or_comment? (new_line_or_comment* (object_elem | (object_elem COMMA)) new_line_or_comment*)* RBRACE
132+
tuple : LSQB new_line_or_comment? (expression new_line_or_comment? COMMA new_line_or_comment?)* (expression new_line_or_comment? COMMA? new_line_or_comment?)? RSQB
133+
object : LBRACE new_line_or_comment? ((object_elem | (object_elem new_line_or_comment? COMMA)) new_line_or_comment?)* RBRACE
136134
object_elem : object_elem_key ( EQ | COLON ) expression
137135
object_elem_key : float_lit | int_lit | identifier | string | object_elem_key_dot_accessor | object_elem_key_expression
138136
object_elem_key_expression : LPAR expression RPAR
@@ -143,9 +141,8 @@ heredoc_template : HEREDOC_TEMPLATE
143141
heredoc_template_trim : HEREDOC_TEMPLATE_TRIM
144142

145143
// Functions
146-
function_call : identifier LPAR new_line_or_comment? arguments? new_line_or_comment? RPAR
147-
arguments : (expression (new_line_or_comment* COMMA new_line_or_comment* expression)* (COMMA | ELLIPSIS)? new_line_or_comment*)
148-
provider_function_call: identifier COLONS identifier COLONS identifier LPAR new_line_or_comment? arguments? new_line_or_comment? RPAR
144+
function_call : identifier (COLONS identifier COLONS identifier)? LPAR new_line_or_comment? arguments? new_line_or_comment? RPAR
145+
arguments : (expression (new_line_or_comment? COMMA new_line_or_comment? expression)* (COMMA | ELLIPSIS)? new_line_or_comment?)
149146

150147
// Indexing and attribute access
151148
index_expr_term : expr_term index
@@ -156,7 +153,7 @@ full_splat_expr_term : expr_term full_splat
156153
braces_index : LSQB new_line_or_comment? expression new_line_or_comment? RSQB
157154
short_index : DOT INT_LITERAL
158155
get_attr : DOT identifier
159-
attr_splat : ATTR_SPLAT get_attr*
156+
attr_splat : ATTR_SPLAT (get_attr | index)*
160157
full_splat : FULL_SPLAT_START (get_attr | index)*
161158

162159
// For expressions

hcl2/rule_transformer/rules/abstract.py

Lines changed: 17 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,16 @@
22
from typing import Any, Union, List, Optional, Tuple, Callable
33

44
from lark import Token, Tree
5+
from lark.exceptions import VisitError
56
from lark.tree import Meta
67

7-
from hcl2.rule_transformer.utils import SerializationOptions
8+
from hcl2.rule_transformer.utils import SerializationOptions, SerializationContext
89

910

1011
class LarkElement(ABC):
11-
@property
12+
@staticmethod
1213
@abstractmethod
13-
def lark_name(self) -> str:
14+
def lark_name() -> str:
1415
raise NotImplementedError()
1516

1617
def __init__(self, index: int = -1, parent: "LarkElement" = None):
@@ -28,7 +29,9 @@ def to_lark(self) -> Any:
2829
raise NotImplementedError()
2930

3031
@abstractmethod
31-
def serialize(self, options: SerializationOptions = SerializationOptions()) -> Any:
32+
def serialize(
33+
self, options=SerializationOptions(), context=SerializationContext()
34+
) -> Any:
3235
raise NotImplementedError()
3336

3437

@@ -37,11 +40,6 @@ def __init__(self, value: Union[str, int]):
3740
self._value = value
3841
super().__init__()
3942

40-
@property
41-
@abstractmethod
42-
def lark_name(self) -> str:
43-
raise NotImplementedError()
44-
4543
@property
4644
@abstractmethod
4745
def serialize_conversion(self) -> Callable:
@@ -51,27 +49,26 @@ def serialize_conversion(self) -> Callable:
5149
def value(self):
5250
return self._value
5351

54-
def serialize(self, options: SerializationOptions = SerializationOptions()):
52+
def serialize(
53+
self, options=SerializationOptions(), context=SerializationContext()
54+
) -> Any:
5555
return self.serialize_conversion(self.value)
5656

5757
def to_lark(self) -> Token:
58-
return Token(self.lark_name, self.value)
58+
return Token(self.lark_name(), self.value)
5959

6060
def __str__(self) -> str:
6161
return str(self._value)
6262

6363
def __repr__(self) -> str:
64-
return f"<LarkToken instance: {self.lark_name} {self.value}>"
64+
return f"<LarkToken instance: {self.lark_name()} {self.value}>"
6565

6666

6767
class LarkRule(LarkElement, ABC):
68-
@property
69-
@abstractmethod
70-
def lark_name(self) -> str:
71-
raise NotImplementedError()
72-
7368
@abstractmethod
74-
def serialize(self, options: SerializationOptions = SerializationOptions()) -> Any:
69+
def serialize(
70+
self, options=SerializationOptions(), context=SerializationContext()
71+
) -> Any:
7572
raise NotImplementedError()
7673

7774
@property
@@ -94,7 +91,7 @@ def to_lark(self) -> Tree:
9491

9592
result_children.append(child.to_lark())
9693

97-
return Tree(self.lark_name, result_children, meta=self._meta)
94+
return Tree(self.lark_name(), result_children, meta=self._meta)
9895

9996
def __init__(self, children: List[LarkElement], meta: Optional[Meta] = None):
10097
super().__init__()
@@ -103,6 +100,7 @@ def __init__(self, children: List[LarkElement], meta: Optional[Meta] = None):
103100

104101
for index, child in enumerate(children):
105102
if child is not None:
103+
print(child)
106104
child.set_index(index)
107105
child.set_parent(self)
108106

hcl2/rule_transformer/rules/base.py

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -3,34 +3,37 @@
33

44
from lark.tree import Meta
55

6+
from hcl2.dict_transformer import START_LINE, END_LINE
67
from hcl2.rule_transformer.rules.abstract import LarkRule, LarkToken
7-
from hcl2.rule_transformer.rules.expression import Expression
8-
from hcl2.rule_transformer.rules.tokens import IdentifierToken, EQ_TOKEN
8+
from hcl2.rule_transformer.rules.expressions import ExpressionRule
9+
from hcl2.rule_transformer.rules.tokens import NAME, EQ
910

1011
from hcl2.rule_transformer.rules.whitespace import NewLineOrCommentRule
11-
from hcl2.rule_transformer.utils import SerializationOptions
12+
from hcl2.rule_transformer.utils import SerializationOptions, SerializationContext
1213

1314

1415
class AttributeRule(LarkRule):
1516
_children: Tuple[
16-
IdentifierToken,
17-
EQ_TOKEN,
18-
Expression,
17+
NAME,
18+
EQ,
19+
ExpressionRule,
1920
]
2021

21-
@property
22-
def lark_name(self) -> str:
22+
@staticmethod
23+
def lark_name() -> str:
2324
return "attribute"
2425

2526
@property
26-
def identifier(self) -> IdentifierToken:
27+
def identifier(self) -> NAME:
2728
return self._children[0]
2829

2930
@property
30-
def expression(self) -> Expression:
31+
def expression(self) -> ExpressionRule:
3132
return self._children[2]
3233

33-
def serialize(self, options: SerializationOptions = SerializationOptions()) -> Any:
34+
def serialize(
35+
self, options=SerializationOptions(), context=SerializationContext()
36+
) -> Any:
3437
return {self.identifier.serialize(options): self.expression.serialize(options)}
3538

3639

@@ -44,11 +47,13 @@ class BodyRule(LarkRule):
4447
]
4548
]
4649

47-
@property
48-
def lark_name(self) -> str:
50+
@staticmethod
51+
def lark_name() -> str:
4952
return "body"
5053

51-
def serialize(self, options: SerializationOptions = SerializationOptions()) -> Any:
54+
def serialize(
55+
self, options=SerializationOptions(), context=SerializationContext()
56+
) -> Any:
5257
blocks: List[BlockRule] = []
5358
attributes: List[AttributeRule] = []
5459
comments = []
@@ -99,11 +104,13 @@ class StartRule(LarkRule):
99104
def body(self) -> BodyRule:
100105
return self._children[0]
101106

102-
@property
103-
def lark_name(self) -> str:
107+
@staticmethod
108+
def lark_name() -> str:
104109
return "start"
105110

106-
def serialize(self, options: SerializationOptions = SerializationOptions()) -> Any:
111+
def serialize(
112+
self, options=SerializationOptions(), context=SerializationContext()
113+
) -> Any:
107114
return self.body.serialize(options)
108115

109116

@@ -118,23 +125,31 @@ def __init__(self, children, meta: Optional[Meta] = None):
118125
child for child in children if not isinstance(child, LarkToken)
119126
]
120127

121-
@property
122-
def lark_name(self) -> str:
128+
@staticmethod
129+
def lark_name() -> str:
123130
return "block"
124131

125132
@property
126-
def labels(self) -> List[IdentifierToken]:
133+
def labels(self) -> List[NAME]:
127134
return list(filter(lambda label: label is not None, self._labels))
128135

129136
@property
130137
def body(self) -> BodyRule:
131138
return self._body
132139

133140
def serialize(
134-
self, options: SerializationOptions = SerializationOptions()
135-
) -> BodyRule:
141+
self, options=SerializationOptions(), context=SerializationContext()
142+
) -> Any:
136143
result = self._body.serialize(options)
137144
labels = self._labels
138-
for label in reversed(labels):
145+
for label in reversed(labels[1:]):
139146
result = {label.serialize(options): result}
147+
148+
result.update(
149+
{
150+
START_LINE: self._meta.line,
151+
END_LINE: self._meta.end_line,
152+
}
153+
)
154+
140155
return result

0 commit comments

Comments
 (0)