@@ -47,51 +47,57 @@ def parse_file(filename):
47
47
return idented_tree
48
48
49
49
50
- html_chars = pp .alphanums + '-_'
51
- tag_def = pp .Word (html_chars )
52
- tag_class = pp .Combine (pp .Literal ('.' ) + pp .Word (html_chars ))
53
- tag_id = pp .Combine (pp .Literal ('#' ) + pp .Word (html_chars ))
54
- attribute_name = pp .Word (html_chars )
55
-
56
- def parse_attribute_value (s , l , t ):
57
- return ast .parse (s [t ._original_start :t ._original_end ]).body [0 ].value
58
- attribute_value = pp .originalTextFor (
59
- pp .sglQuotedString ()
60
- ^ pp .dblQuotedString ()
61
- ^ pp .nestedExpr ()
62
- ^ pp .nestedExpr ('[' , ']' )
63
- ).setParseAction (parse_attribute_value )
64
-
65
- def parse_tag_attribute (s , l , t ):
66
- return ast .Dict (
67
- keys = [ast .Str (s = str (k )) for k , v in t ],
68
- values = [v for k , v in t ]
50
+ def create_parser ():
51
+ html_chars = pp .alphanums + '-_'
52
+ tag_def = pp .Word (html_chars )
53
+ tag_class = pp .Combine (pp .Literal ('.' ) + pp .Word (html_chars ))
54
+ tag_id = pp .Combine (pp .Literal ('#' ) + pp .Word (html_chars ))
55
+ attribute_name = pp .Word (html_chars )
56
+
57
+ def parse_attribute_value (s , l , t ):
58
+ return ast .parse (s [t ._original_start :t ._original_end ]).body [0 ].value
59
+ attribute_value = pp .originalTextFor (
60
+ pp .sglQuotedString ()
61
+ ^ pp .dblQuotedString ()
62
+ ^ pp .nestedExpr ()
63
+ ^ pp .nestedExpr ('[' , ']' )
64
+ ).setParseAction (parse_attribute_value )
65
+
66
+ def parse_tag_attribute (s , l , t ):
67
+ return ast .Dict (
68
+ keys = [ast .Str (s = str (k )) for k , v in t ],
69
+ values = [v for k , v in t ]
70
+ )
71
+ tag_attribute = pp .Group (attribute_name + pp .Suppress ('=' ) + attribute_value ).setParseAction (parse_tag_attribute )
72
+ tag_dict = pp .nestedExpr ('{' , '}' ).setParseAction (
73
+ lambda s , l , t : ast .parse (s [l :]).body [0 ].value
74
+ )
75
+ tag_grammar = (
76
+ tag_def
77
+ + pp .Group (pp .ZeroOrMore (tag_class ^ tag_id ))
78
+ + (tag_dict ^ pp .Group (pp .ZeroOrMore (tag_attribute )))
69
79
)
70
- tag_attribute = pp .Group (attribute_name + pp .Suppress ('=' ) + attribute_value ).setParseAction (parse_tag_attribute )
71
- tag_dict = pp .nestedExpr ('{' , '}' ).setParseAction (
72
- lambda s , l , t : ast .parse (s [l :]).body [0 ].value
73
- )
74
- tag_grammar = (
75
- tag_def
76
- + pp .Group (pp .ZeroOrMore (tag_class ^ tag_id ))
77
- + (tag_dict ^ pp .Group (pp .ZeroOrMore (tag_attribute )))
78
- )
79
- def parse_tag (node_string ):
80
- node , attrs_keys , node_attrs = tag_grammar .parseString (node_string )
81
- node_attrs = None if not node_attrs else node_attrs
82
- node_attrs = node_attrs [0 ] if isinstance (node_attrs , pp .ParseResults ) else node_attrs
83
- return node , node_attrs
80
+ def parse_tag (node_string ):
81
+ node , attrs_keys , node_attrs = tag_grammar .parseString (node_string )
82
+ node_attrs = None if not node_attrs else node_attrs
83
+ node_attrs = node_attrs [0 ] if isinstance (node_attrs , pp .ParseResults ) else node_attrs
84
+ return node , node_attrs
85
+ return parse_tag
86
+
87
+ parse_tag = create_parser ()
84
88
85
89
86
90
def dump_ast (node , tabs = 0 ):
87
- space = ' ' * tabs
91
+ space = ' ' * tabs
88
92
print (space , '--' , node , getattr (node , 'lineno' , None ), getattr (node , 'col_offset' , None ))
89
93
if hasattr (node , '_fields' ):
90
94
for field in node ._fields :
91
- print (space , field , dump_ast (getattr (node , field ), tabs + 1 ))
95
+ if getattr (node , field ):
96
+ print (space , '=' , field )
97
+ dump_ast (getattr (node , field ), tabs + 1 )
92
98
elif isinstance (node , list ):
93
99
for node_ in node :
94
- print ( space , dump_ast (node_ , tabs + 1 ) )
100
+ dump_ast (node_ , tabs + 1 )
95
101
96
102
97
103
NoValue = object ()
@@ -117,18 +123,36 @@ def stop(self):
117
123
118
124
119
125
def _convert_to_ast (idented_tree , order = 0 ):
120
- elements = []
126
+ node_with_else = None # track if and for
121
127
for lineno , node_string , childs in idented_tree :
122
128
ast_childs = _convert_to_ast (childs , order = order )
129
+ elif_ = False
123
130
if node_string .startswith ('-' ):
124
- if node_string .endswith (':' ):
125
- node_string = node_string + ' pass'
126
- res = ast .parse (node_string [1 :].strip (), filename = 'text.pyml' ).body [0 ]
127
- res .lineno = lineno
128
- res .col_offset = 0
129
- if childs and isinstance (res .body [0 ], ast .Pass ):
130
- res .body = list (ast_childs ) or []
131
- yield res
131
+ node_string = node_string [1 :].strip ()
132
+ if node_string == 'else' :
133
+ node_with_else .orelse = list (ast_childs ) or []
134
+ else :
135
+ if node_string .startswith ('elif ' ):
136
+ node_string = node_string [2 :]
137
+ elif_ = True
138
+ else :
139
+ # swap out (if|for)node
140
+ node_with_else = None
141
+ if node_string .endswith (':' ):
142
+ node_string = node_string + ' pass'
143
+ res = ast .parse (node_string , filename = 'text.pyml' ).body [0 ]
144
+ res .lineno = lineno + 1
145
+ res .col_offset = 0
146
+ if not elif_ and isinstance (res , (ast .If , ast .For )):
147
+ node_with_else = res
148
+ if childs and isinstance (res .body [0 ], ast .Pass ):
149
+ res .body = list (ast_childs ) or []
150
+ ast .fix_missing_locations (res )
151
+ if elif_ :
152
+ node_with_else .orelse = [res ]
153
+ node_with_else = res
154
+ else :
155
+ yield res
132
156
continue
133
157
if node_string .startswith ('"' ):
134
158
yield ast .Expr (
@@ -148,7 +172,6 @@ def _convert_to_ast(idented_tree, order=0):
148
172
keywords = [],
149
173
starargs = None ,
150
174
kwargs = node_attrs ,
151
- ** line_n_offset
152
175
),
153
176
** line_n_offset
154
177
)
@@ -179,16 +202,16 @@ def convert_to_ast(idented_tree, order=0):
179
202
180
203
181
204
182
- def convert_internal_ast_to_python_code (idented_tree ):
205
+ def convert_internal_ast_to_python_code (idented_tree , filename = '<unknown>' ):
183
206
result_ast = ast .Module (
184
207
body = [ast .FunctionDef (
185
208
name = 'render' ,
186
209
args = ast .arguments (
187
210
args = [],
188
- vararg = ast .arg (arg = 'arguments' ),
211
+ vararg = ast .arg (arg = 'arguments' , annotation = None ),
189
212
kwonlyargs = [],
190
213
kw_defaults = [],
191
- kwarg = ast .arg (arg = 'options' ),
214
+ kwarg = ast .arg (arg = 'options' , annotation = None ),
192
215
defaults = [],
193
216
),
194
217
body = convert_to_ast (idented_tree ),
@@ -199,7 +222,7 @@ def convert_internal_ast_to_python_code(idented_tree):
199
222
)
200
223
result_ast = ast .fix_missing_locations (result_ast )
201
224
# dump_ast(result_ast)
202
- return compile (result_ast , 'test.pyml' , 'exec' )
225
+ return compile (result_ast , filename , 'exec' )
203
226
204
227
205
228
def convert_to_function (code ):
@@ -262,7 +285,7 @@ def load_module(self, fullname):
262
285
mod .__loader__ = self
263
286
mod .__package__ = '.' .join (fullname .split ('.' )[:- 1 ])
264
287
mod .__dict__ ['Tag' ] = self .tag_class
265
- code = convert_internal_ast_to_python_code (parse_file (self .filename ))
288
+ code = convert_internal_ast_to_python_code (parse_file (self .filename ), filename = self . filename )
266
289
exec (code , mod .__dict__ )
267
290
return mod
268
291
0 commit comments