2 from . import OP_PRECEDENCE
, UNARY_PRECEDENCE
, is_identifier
, RESERVED_WORDS
3 from math
import inf
, ceil
, log10
6 dump_block(parse(reader
))
8 def dump_block(block
, level
=0):
10 if stmt
[0] or not isinstance(stmt
[1], tuple) \
11 or stmt
[1][0] != 'block' or stmt
[1][1]:
12 dump_stmt(stmt
, level
)
14 def dump_stmt(stmt
, level
):
17 print(f
'{(level - 1) * " "}{label}:')
18 print(end
=level
* ' ')
19 if isinstance(stmt
, tuple):
22 elif stmt
[0] in {'return', 'throw'}:
25 if expr
!= ('undefined',):
27 dump_expr(expr
, level
=level
)
28 elif stmt
[0] == 'for':
29 [init
, test
, final
, stmt
] = stmt
[1:]
30 if init
== final
== ('undefined',) and test
is not True:
32 dump_expr(test
, level
=level
)
37 dump_expr(test
, level
=level
)
39 if final
!= ('undefined',):
40 dump_expr(final
, level
=level
)
41 dump_substmt(')', stmt
, level
)
43 elif stmt
[0] == 'block':
46 dump_block(stmt
, level
+ 1)
47 print(f
'{level * " "}}}')
51 [cond
, true
, false
] = stmt
[1:]
52 dump_expr(cond
, level
=level
)
53 dump_substmt(')', true
, level
)
54 if false
[0] or false
[1][0] != 'block' or false
[1][1]:
55 dump_substmt(f
'{level * " "}else', false
, level
)
57 elif stmt
[0] in {'break', 'continue'}:
61 print(end
=f
' {label}')
62 elif stmt
[0] == 'for in':
63 [var
, iter, stmt
] = stmt
[1:]
66 dump_expr(iter, level
=level
)
67 dump_substmt(')', stmt
, level
)
69 elif stmt
[0] == 'try':
71 [block
, exc
, catch
, finally_block
] = stmt
[1:]
72 dump_block(block
, level
+ 1)
74 print(f
'{level * " "}}} catch ({exc}) {{')
75 dump_block(catch
, level
+ 1)
76 if finally_block
or exc
is None:
77 print(f
'{level * " "}}} finally {{')
78 dump_block(finally_block
, level
+ 1)
79 print(f
'{level * " "}}}')
81 elif stmt
[0] == 'function':
82 dump_function(stmt
, level
)
86 [stmt
, expr
] = stmt
[1:]
87 dump_substmt('do', stmt
, level
)
88 print(end
=f
'{level * " "}while (')
89 dump_expr(expr
, level
=level
)
91 elif stmt
[0] == 'switch':
92 [expr
, cases
] = stmt
[1:]
94 dump_expr(expr
, level
=level
)
96 for [case
, stmts
] in cases
:
97 if case
== ('undefined',):
98 print(end
=f
'{level * " "}default')
100 print(end
=f
'{level * " "}case ')
101 dump_expr(case
, level
=level
)
103 dump_block(stmts
, level
+ 1)
104 print(f
'{level * " "}}}')
107 dump_expr(stmt
, disallow
={'function', 'object'}, level
=level
)
109 dump_expr(stmt
, disallow
={'function', 'object'}, level
=level
)
112 def dump_substmt(code
, stmt
, level
):
114 [labels
, instruct
] = stmt
115 if instruct
[0] != 'block':
117 dump_stmt(stmt
, level
+ 1)
120 dump_stmt(stmt
, level
)
123 [stmt
] = instruct
[1:]
124 dump_block(stmt
, level
+ 1)
125 print(f
'{level * " "}}}')
127 def dump_for(init
, level
):
129 if isinstance(init
, tuple) and init
[:1] == ('var',):
130 dump_var(init
, level
, disallow
={'in'})
131 elif init
!= ('undefined',):
132 dump_expr(init
, level
=level
, disallow
={'in'})
134 def dump_var(stmt
, level
, *, disallow
=frozenset()):
137 for [i
, [name
, expr
]] in enumerate(vars):
141 if expr
!= ('undefined',):
143 dump_expr(expr
, OP_PRECEDENCE
[','], level
=level
)
145 def dump_expr(expr
, precedence
=-inf
, *,
146 disallow
=frozenset(), level
, disallow_nullary_new
=False):
147 if isinstance(expr
, float):
148 print(end
=format(expr
, f
'.{ceil(log10(2) * 52) + 1}g'))
149 elif isinstance(expr
, str):
150 print(end
=repr(expr
))
151 elif isinstance(expr
, list):
153 for [i
, elem
] in enumerate(expr
):
154 if elem
== ('undefined',):
158 dump_expr(elem
, OP_PRECEDENCE
[','], level
=level
)
159 if i
< len(expr
) - 1 or elem
== ('undefined',):
161 if i
< len(expr
) - 1:
164 elif isinstance(expr
, tuple):
165 if expr
[0].startswith('prefix '):
168 p
= OP_PRECEDENCE
.get(expr
[0], +inf
)
169 if p
<= precedence
or expr
[0] in disallow \
170 or disallow_nullary_new
and expr
[0] == 'new' and not expr
[2]:
173 disallow
= frozenset()
177 if expr
[0] == 'call':
178 [expr
, args
] = expr
[1:]
179 dump_expr(expr
, UNARY_PRECEDENCE
, disallow
=disallow
, level
=level
,
180 disallow_nullary_new
=True)
181 dump_args(args
, level
)
182 elif expr
[0] == 'function':
183 dump_function(expr
, level
)
184 elif expr
[0] == 'object':
187 for [i
, [name
, expr
]] in enumerate(items
):
190 if is_unreserved_ident(name
):
193 dump_expr(name
, level
=level
)
195 dump_expr(expr
, OP_PRECEDENCE
[','], level
=level
)
197 elif expr
[0] == 'this':
199 elif expr
[0] in OP_PRECEDENCE
:
200 rhs
= OP_PRECEDENCE
[expr
[0]]
201 if rhs
== OP_PRECEDENCE
['=']:
206 dump_expr(expr
[1], precedence
=lhs
, disallow
=disallow
, level
=level
)
209 print(end
=f
'{expr[0]} ')
210 disallow
= disallow
- {'function', 'object'}
211 dump_expr(expr
[2], precedence
=rhs
, disallow
=disallow
, level
=level
)
212 elif expr
[0] == 'identifier':
215 elif expr
[0] == 'property':
216 dump_expr(expr
[1], UNARY_PRECEDENCE
, level
=level
,
217 disallow_nullary_new
=True)
218 if is_unreserved_ident(expr
[2]):
219 print(end
=f
'.{expr[2]}')
222 dump_expr(expr
[2], level
=level
)
225 dump_expr(expr
[1], OP_PRECEDENCE
['='],
226 disallow
=disallow
, level
=level
)
228 dump_expr(expr
[2], OP_PRECEDENCE
[','], level
=level
)
230 dump_expr(expr
[3], OP_PRECEDENCE
[','],
231 disallow
=disallow
- {'function', 'object'}, level
=level
)
232 elif expr
[0].startswith('prefix '):
234 if op
== 'prefix !' and isinstance(expr
, (float, str, bool)):
235 print(end
=repr(not expr
).lower())
237 print(end
=op
[len('prefix '):])
238 if op
[len('prefix '):].isalnum():
240 dump_expr(expr
, UNARY_PRECEDENCE
, level
=level
)
241 elif expr
[0].startswith('postfix '):
242 dump_expr(expr
[1], UNARY_PRECEDENCE
, level
=level
)
243 print(end
=expr
[0][len('postfix '):])
244 elif expr
[0] == 'new':
246 [expr
, args
] = expr
[1:]
247 if isinstance(expr
, tuple) and expr
[0].startswith('postfix '):
249 dump_expr(expr
, UNARY_PRECEDENCE
, disallow
={'call'}, level
=level
,
250 disallow_nullary_new
=args
)
251 if isinstance(expr
, tuple) and expr
[0].startswith('postfix '):
254 dump_args(args
, level
)
255 elif expr
[0] == 'regex':
256 [pattern
, flags
] = expr
[1:]
257 print(end
=f
'/{pattern}/{flags}')
259 raise NotImplementedError(expr
)
262 LITERALS
= {None: 'null', True: 'true', False: 'false'}
263 print(end
=LITERALS
[expr
])
265 def dump_args(args
, level
):
267 for [i
, expr
] in enumerate(args
):
270 dump_expr(expr
, OP_PRECEDENCE
[','], level
=level
)
273 def dump_function(f
, level
):
274 [name
, params
, body
] = f
[1:]
277 print(end
=f
'function {name}(')
278 for [i
, name
] in enumerate(params
):
283 dump_block(body
, level
=level
+ 1)
284 print(end
=f
'{level * " "}}}')
286 def is_unreserved_ident(name
):
287 return isinstance(name
, str) and is_identifier(name
) \
288 and name
not in RESERVED_WORDS
290 if __name__
== '__main__':
291 from sys
import stdin