Skip to content

Commit 42672f8

Browse files
various changes
1 parent 38cb014 commit 42672f8

17 files changed

+1232
-223
lines changed

hcl2/parser.py

Lines changed: 2 additions & 2 deletions
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-
"hcl2.lark",
15+
"rule_transformer/hcl2.lark.lark",
1616
parser="lalr",
1717
cache=str(PARSER_FILE), # Disable/Delete file to effect changes to the grammar
1818
rel_to=__file__,
@@ -29,7 +29,7 @@ def reconstruction_parser() -> Lark:
2929
if necessary.
3030
"""
3131
return Lark.open(
32-
"hcl2.lark",
32+
"rule_transformer/hcl2.lark",
3333
parser="lalr",
3434
# Caching must be disabled to allow for reconstruction until lark-parser/lark#1472 is fixed:
3535
#

hcl2/rule_transformer/editor.py

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
import dataclasses
2+
from copy import copy, deepcopy
3+
from typing import List, Optional, Set, Tuple
4+
5+
from hcl2.rule_transformer.rules.abstract import LarkRule
6+
from hcl2.rule_transformer.rules.base import BlockRule, StartRule
7+
8+
9+
@dataclasses.dataclass
10+
class TreePathElement:
11+
12+
name: str
13+
index: int = 0
14+
15+
16+
@dataclasses.dataclass
17+
class TreePath:
18+
19+
elements: List[TreePathElement] = dataclasses.field(default_factory=list)
20+
21+
@classmethod
22+
def build(cls, elements: List[Tuple[str, Optional[int]] | str]):
23+
results = []
24+
for element in elements:
25+
if isinstance(element, tuple):
26+
if len(element) == 1:
27+
result = TreePathElement(element[0], 0)
28+
else:
29+
result = TreePathElement(*element)
30+
else:
31+
result = TreePathElement(element, 0)
32+
33+
results.append(result)
34+
35+
return cls(results)
36+
37+
def __iter__(self):
38+
return self.elements.__iter__()
39+
40+
def __len__(self):
41+
return self.elements.__len__()
42+
43+
44+
class Editor:
45+
def __init__(self, rules_tree: LarkRule):
46+
self.rules_tree = rules_tree
47+
48+
@classmethod
49+
def _find_one(cls, rules_tree: LarkRule, path_element: TreePathElement) -> LarkRule:
50+
return cls._find_all(rules_tree, path_element.name)[path_element.index]
51+
52+
@classmethod
53+
def _find_all(cls, rules_tree: LarkRule, rule_name: str) -> List[LarkRule]:
54+
children = []
55+
print("rule", rules_tree)
56+
print("rule children", rules_tree.children)
57+
for child in rules_tree.children:
58+
if isinstance(child, LarkRule) and child.lark_name() == rule_name:
59+
children.append(child)
60+
61+
return children
62+
63+
def find_by_path(self, path: TreePath, rule_name: str) -> List[LarkRule]:
64+
path = deepcopy(path.elements)
65+
66+
current_rule = self.rules_tree
67+
while len(path) > 0:
68+
current_path, *path = path
69+
print(current_path, path)
70+
current_rule = self._find_one(current_rule, current_path)
71+
72+
return self._find_all(current_rule, rule_name)
73+
74+
# def visit(self, path: TreePath) -> "Editor":
75+
#
76+
# while len(path) > 1:
77+
# current =

hcl2/rule_transformer/hcl2.lark

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// ============================================================================
2+
// Terminals
3+
// ============================================================================
4+
5+
// Whitespace and Comments
6+
NL_OR_COMMENT: /\n[ \t]*/ | /#.*\n/ | /\/\/.*\n/ | /\/\*(.|\n)*?(\*\/)/
7+
8+
// Keywords
9+
IF : "if"
10+
IN : "in"
11+
FOR : "for"
12+
FOR_EACH : "for_each"
13+
14+
// Identifiers and Names
15+
NAME : /[a-zA-Z_][a-zA-Z0-9_-]*/
16+
IDENTIFIER: NAME | IN | FOR | IF | FOR_EACH
17+
18+
// Literals
19+
ESCAPED_INTERPOLATION.2: /\$\$\{[^}]*\}/
20+
STRING_CHARS.1: /(?:(?!\$\$\{)(?!\$\{)[^"\\]|\\.|(?:\$(?!\$?\{)))+/
21+
DECIMAL : "0".."9"
22+
NEGATIVE_DECIMAL : "-" DECIMAL
23+
EXP_MARK : ("e" | "E") ("+" | "-")? DECIMAL+
24+
INT_LITERAL: NEGATIVE_DECIMAL? DECIMAL+
25+
FLOAT_LITERAL: (NEGATIVE_DECIMAL? DECIMAL+ | NEGATIVE_DECIMAL+) "." DECIMAL+ (EXP_MARK)?
26+
| (NEGATIVE_DECIMAL? DECIMAL+ | NEGATIVE_DECIMAL+) (EXP_MARK)
27+
28+
// Operators
29+
BINARY_OP : DOUBLE_EQ | NEQ | LT | GT | LEQ | GEQ | MINUS | ASTERISK | SLASH | PERCENT | DOUBLE_AMP | DOUBLE_PIPE | PLUS
30+
DOUBLE_EQ : "=="
31+
NEQ : "!="
32+
LT : "<"
33+
GT : ">"
34+
LEQ : "<="
35+
GEQ : ">="
36+
MINUS : "-"
37+
ASTERISK : "*"
38+
SLASH : "/"
39+
PERCENT : "%"
40+
DOUBLE_AMP : "&&"
41+
DOUBLE_PIPE : "||"
42+
PLUS : "+"
43+
NOT : "!"
44+
QMARK : "?"
45+
46+
// Punctuation
47+
LPAR : "("
48+
RPAR : ")"
49+
LBRACE : "{"
50+
RBRACE : "}"
51+
LSQB : "["
52+
RSQB : "]"
53+
COMMA : ","
54+
DOT : "."
55+
EQ : /[ \t]*=(?!=|>)/
56+
COLON : ":"
57+
DBLQUOTE : "\""
58+
59+
// Interpolation
60+
INTERP_START : "${"
61+
62+
// Splat Operators
63+
ATTR_SPLAT : ".*"
64+
FULL_SPLAT_START : "[*]"
65+
66+
// Special Operators
67+
FOR_OBJECT_ARROW : "=>"
68+
ELLIPSIS : "..."
69+
COLONS: "::"
70+
71+
// Heredocs
72+
HEREDOC_TEMPLATE : /<<(?P<heredoc>[a-zA-Z][a-zA-Z0-9._-]+)\n?(?:.|\n)*?\n\s*(?P=heredoc)\n/
73+
HEREDOC_TEMPLATE_TRIM : /<<-(?P<heredoc_trim>[a-zA-Z][a-zA-Z0-9._-]+)\n?(?:.|\n)*?\n\s*(?P=heredoc_trim)\n/
74+
75+
// Ignore whitespace (but not newlines, as they're significant in HCL)
76+
%ignore /[ \t]+/
77+
78+
// ============================================================================
79+
// Rules
80+
// ============================================================================
81+
82+
// Top-level structure
83+
start : body
84+
85+
// Body and basic constructs
86+
body : (new_line_or_comment? (attribute | block))* new_line_or_comment?
87+
attribute : identifier EQ expression
88+
block : identifier (identifier | string)* new_line_or_comment? LBRACE body RBRACE
89+
90+
// Whitespace and comments
91+
new_line_or_comment: ( NL_OR_COMMENT )+
92+
93+
// Basic literals and identifiers
94+
identifier: IDENTIFIER
95+
int_lit: INT_LITERAL
96+
float_lit: FLOAT_LITERAL
97+
string: DBLQUOTE string_part* DBLQUOTE
98+
string_part: STRING_CHARS
99+
| ESCAPED_INTERPOLATION
100+
| interpolation
101+
102+
// Expressions
103+
?expression : expr_term | operation | conditional
104+
interpolation: INTERP_START expression RBRACE
105+
conditional : expression QMARK new_line_or_comment? expression new_line_or_comment? COLON new_line_or_comment? expression
106+
107+
// Operations
108+
?operation : unary_op | binary_op
109+
!unary_op : (MINUS | NOT) expr_term
110+
binary_op : expression binary_term new_line_or_comment?
111+
binary_term : binary_operator new_line_or_comment? expression
112+
!binary_operator : BINARY_OP
113+
114+
// Expression terms
115+
expr_term : LPAR new_line_or_comment? expression new_line_or_comment? RPAR
116+
| float_lit
117+
| int_lit
118+
| string
119+
| tuple
120+
| object
121+
| function_call
122+
| index_expr_term
123+
| get_attr_expr_term
124+
| identifier
125+
| provider_function_call
126+
| heredoc_template
127+
| heredoc_template_trim
128+
| attr_splat_expr_term
129+
| full_splat_expr_term
130+
| for_tuple_expr
131+
| for_object_expr
132+
133+
// 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
136+
object_elem : object_elem_key ( EQ | COLON ) expression
137+
object_elem_key : float_lit | int_lit | identifier | string | object_elem_key_dot_accessor | object_elem_key_expression
138+
object_elem_key_expression : LPAR expression RPAR
139+
object_elem_key_dot_accessor : identifier (DOT identifier)+
140+
141+
// Heredocs
142+
heredoc_template : HEREDOC_TEMPLATE
143+
heredoc_template_trim : HEREDOC_TEMPLATE_TRIM
144+
145+
// 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
149+
150+
// Indexing and attribute access
151+
index_expr_term : expr_term index
152+
get_attr_expr_term : expr_term get_attr
153+
attr_splat_expr_term : expr_term attr_splat
154+
full_splat_expr_term : expr_term full_splat
155+
?index : braces_index | short_index
156+
braces_index : LSQB new_line_or_comment? expression new_line_or_comment? RSQB
157+
short_index : DOT INT_LITERAL
158+
get_attr : DOT identifier
159+
attr_splat : ATTR_SPLAT get_attr*
160+
full_splat : FULL_SPLAT_START (get_attr | index)*
161+
162+
// For expressions
163+
!for_tuple_expr : LSQB new_line_or_comment? for_intro new_line_or_comment? expression new_line_or_comment? for_cond? new_line_or_comment? RSQB
164+
!for_object_expr : LBRACE new_line_or_comment? for_intro new_line_or_comment? expression FOR_OBJECT_ARROW new_line_or_comment? expression new_line_or_comment? ELLIPSIS? new_line_or_comment? for_cond? new_line_or_comment? RBRACE
165+
!for_intro : FOR new_line_or_comment? identifier (COMMA identifier new_line_or_comment?)? new_line_or_comment? IN new_line_or_comment? expression new_line_or_comment? COLON new_line_or_comment?
166+
!for_cond : IF new_line_or_comment? expression

0 commit comments

Comments
 (0)