]> git.saurik.com Git - cycript.git/blame - Output.cpp
Optimized the variable renamer to rename more variables to 'a'.
[cycript.git] / Output.cpp
CommitLineData
e91fbe93 1/* Cycript - Inlining/Optimizing JavaScript Compiler
4644480a
JF
2 * Copyright (C) 2009 Jay Freeman (saurik)
3*/
4
5/* Modified BSD License {{{ */
6/*
7 * Redistribution and use in source and binary
8 * forms, with or without modification, are permitted
9 * provided that the following conditions are met:
10 *
11 * 1. Redistributions of source code must retain the
12 * above copyright notice, this list of conditions
13 * and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the
15 * above copyright notice, this list of conditions
16 * and the following disclaimer in the documentation
17 * and/or other materials provided with the
18 * distribution.
19 * 3. The name of the author may not be used to endorse
20 * or promote products derived from this software
21 * without specific prior written permission.
22 *
23 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS''
24 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING,
25 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
26 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE
28 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
29 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
31 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
33 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
34 * TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
35 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
36 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37*/
38/* }}} */
39
520c130f 40#include "cycript.hpp"
5999c315
JF
41#include "Parser.hpp"
42
4afefdd9
JF
43#include <sstream>
44
b09da87b
JF
45_finline CYFlags operator ~(CYFlags rhs) {
46 return static_cast<CYFlags>(~static_cast<unsigned>(rhs));
47}
48
49_finline CYFlags operator &(CYFlags lhs, CYFlags rhs) {
50 return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
51}
52
53_finline CYFlags operator |(CYFlags lhs, CYFlags rhs) {
54 return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs));
55}
56
57_finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) {
58 return lhs = lhs | rhs;
59}
60
61_finline CYFlags CYLeft(CYFlags flags) {
9561f209 62 return flags & ~(CYNoDangle | CYNoInteger);
b09da87b
JF
63}
64
96a7e5c2
JF
65_finline CYFlags CYRight(CYFlags flags) {
66 return flags & ~CYNoBF;
b09da87b
JF
67}
68
96a7e5c2 69_finline CYFlags CYCenter(CYFlags flags) {
d29365ce 70 return CYLeft(CYRight(flags));
b09da87b
JF
71}
72
1fdca2fa
JF
73void CYOutput::Terminate() {
74 out_ << ';';
75 mode_ = NoMode;
76}
77
96a7e5c2 78CYOutput &CYOutput::operator <<(char rhs) {
1fdca2fa
JF
79 if (rhs == ' ' || rhs == '\n')
80 if (pretty_)
81 out_ << rhs;
82 else goto done;
83 else if (rhs == '\t')
84 if (pretty_)
85 for (unsigned i(0); i != indent_; ++i)
86 out_ << " ";
87 else goto done;
320ce753
JF
88 else if (rhs == '\r') {
89 if (right_) {
90 out_ << '\n';
91 right_ = false;
14ec9e00 92 } goto done;
320ce753 93 } else goto work;
1fdca2fa 94
320ce753 95 right_ = true;
1fdca2fa
JF
96 mode_ = NoMode;
97 goto done;
96a7e5c2 98
1fdca2fa 99 work:
320ce753
JF
100 if (mode_ == Terminated && rhs != '}') {
101 right_ = true;
96a7e5c2 102 out_ << ';';
320ce753 103 }
96a7e5c2
JF
104
105 if (rhs == ';') {
106 if (pretty_)
107 goto none;
108 else {
109 mode_ = Terminated;
110 goto done;
111 }
c0bc320e
JF
112 } else if (rhs == '+') {
113 if (mode_ == NoPlus)
114 out_ << ' ';
115 mode_ = NoPlus;
96a7e5c2
JF
116 } else if (rhs == '-') {
117 if (mode_ == NoHyphen)
118 out_ << ' ';
119 mode_ = NoHyphen;
120 } else if (WordEndRange_[rhs]) {
121 if (mode_ == NoLetter)
122 out_ << ' ';
123 mode_ = NoLetter;
124 } else none:
125 mode_ = NoMode;
126
320ce753 127 right_ = true;
96a7e5c2
JF
128 out_ << rhs;
129 done:
130 return *this;
131}
132
133CYOutput &CYOutput::operator <<(const char *rhs) {
134 size_t size(strlen(rhs));
135
136 if (size == 1)
137 return *this << *rhs;
138
139 if (mode_ == Terminated)
140 out_ << ';';
141 else if (
c0bc320e 142 mode_ == NoPlus && *rhs == '+' ||
96a7e5c2
JF
143 mode_ == NoHyphen && *rhs == '-' ||
144 mode_ == NoLetter && WordEndRange_[*rhs]
145 )
146 out_ << ' ';
147
148 if (WordEndRange_[rhs[size - 1]])
149 mode_ = NoLetter;
150 else
151 mode_ = NoMode;
152
320ce753 153 right_ = true;
96a7e5c2
JF
154 out_ << rhs;
155 return *this;
156}
157
652ec1ba 158void CYArgument::Output(CYOutput &out) const {
d35a3b07 159 if (name_ != NULL) {
5999c315 160 out << *name_;
96a7e5c2
JF
161 if (value_ != NULL)
162 out << ':' << ' ';
5999c315 163 }
d35a3b07 164 if (value_ != NULL)
b09da87b 165 value_->Output(out, CYPA, CYNoFlags);
5999c315 166 if (next_ != NULL) {
96a7e5c2 167 if (next_->name_ == NULL)
11c1cc16 168 out << ',';
96a7e5c2 169 out << ' ' << *next_;
5999c315
JF
170 }
171}
172
652ec1ba 173void CYArray::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 174 out << '[' << elements_ << ']';
5befe15e
JF
175}
176
652ec1ba 177void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
4644480a 178 out << '[' << *expression_ << ' ' << *comprehensions_ << ']';
75b0a457
JF
179}
180
652ec1ba 181void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 182 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
96a7e5c2 183 out << ' ' << Operator() << ' ';
b09da87b 184 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
185}
186
3b52fd1a
JF
187void CYBlock::Output(CYOutput &out) const {
188 out << '{' << '\n';
189 ++out.indent_;
190 if (statements_ != NULL)
191 statements_->Multiple(out);
192 --out.indent_;
193 out << '\t' << '}';
194}
195
fb98ac0c 196void CYBlock::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a
JF
197 if (statements_ == NULL)
198 out.Terminate();
199 else if (statements_->next_ == NULL)
200 statements_->Single(out, flags);
201 else
202 Output(out);
9e562cfc
JF
203}
204
652ec1ba 205void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
206 out << (Value() ? "true" : "false");
207}
208
fb98ac0c 209void CYBreak::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
210 out << "break";
211 if (label_ != NULL)
212 out << ' ' << *label_;
96a7e5c2 213 out << ';';
5999c315
JF
214}
215
652ec1ba 216void CYCall::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
217 bool protect((flags & CYNoCall) != 0);
218 if (protect)
219 out << '(';
220 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
96a7e5c2 221 out << '(' << arguments_ << ')';
fb98ac0c
JF
222 if (protect)
223 out << ')';
5999c315
JF
224}
225
37954781
JF
226namespace cy {
227namespace Syntax {
228
229void Catch::Output(CYOutput &out) const {
3b52fd1a 230 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
5999c315
JF
231}
232
37954781
JF
233} }
234
320ce753
JF
235void CYComment::Output(CYOutput &out, CYFlags flags) const {
236 out << '\r';
14ec9e00
JF
237 out.out_ << value_;
238 out.right_ = true;
320ce753
JF
239 out << '\r';
240}
241
652ec1ba 242void CYCompound::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
243 if (CYExpression *expression = expressions_)
244 if (CYExpression *next = expression->next_) {
245 expression->Output(out, CYLeft(flags));
246 CYFlags center(CYCenter(flags));
247 while (next != NULL) {
248 expression = next;
96a7e5c2 249 out << ',' << ' ';
e5bc40db
JF
250 next = expression->next_;
251 CYFlags right(next != NULL ? center : CYRight(flags));
252 expression->Output(out, right);
253 }
254 } else
255 expression->Output(out, flags);
256}
257
652ec1ba 258void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 259 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 260 out << ' ' << '?' << ' ';
5999c315 261 if (true_ != NULL)
b09da87b 262 true_->Output(out, CYPA, CYNoFlags);
96a7e5c2 263 out << ' ' << ':' << ' ';
b09da87b 264 false_->Output(out, CYPA, CYRight(flags));
5999c315
JF
265}
266
fb98ac0c 267void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
268 out << "continue";
269 if (label_ != NULL)
270 out << ' ' << *label_;
96a7e5c2 271 out << ';';
5999c315
JF
272}
273
652ec1ba 274void CYClause::Output(CYOutput &out) const {
96a7e5c2
JF
275 if (case_ != NULL)
276 out << "case" << ' ' << *case_;
277 else
5999c315 278 out << "default";
1fdca2fa 279 out << ':' << '\n';
3b52fd1a
JF
280 if (statements_ != NULL)
281 statements_->Multiple(out);
96a7e5c2 282 out << next_;
cac61857
JF
283}
284
285const char *CYDeclaration::ForEachIn() const {
029bc65b 286 return identifier_->Word();
5999c315
JF
287}
288
652ec1ba 289void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 290 out << "var";
96a7e5c2 291 Output(out, CYRight(flags));
75b0a457
JF
292}
293
652ec1ba 294void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 295 out << *identifier_;
d35a3b07 296 if (initialiser_ != NULL) {
96a7e5c2 297 out << ' ' << '=' << ' ';
75b0a457 298 initialiser_->Output(out, CYPA, CYRight(flags));
96a7e5c2 299 }
5999c315
JF
300}
301
652ec1ba 302void CYDeclarations::For(CYOutput &out) const {
fb98ac0c 303 out << "var";
96a7e5c2
JF
304 Output(out, CYNoIn);
305}
306
307void CYDeclarations::Output(CYOutput &out) const {
308 Output(out, CYNoFlags);
cac61857 309}
d35a3b07 310
652ec1ba 311void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 312 const CYDeclarations *declaration(this);
fb98ac0c 313 bool first(true);
d35a3b07 314 output:
75b0a457 315 CYDeclarations *next(declaration->next_);
fb98ac0c
JF
316 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
317 first = false;
318 declaration->declaration_->Output(out, jacks);
d35a3b07 319
75b0a457 320 if (next != NULL) {
96a7e5c2 321 out << ',' << ' ';
75b0a457 322 declaration = next;
d35a3b07
JF
323 goto output;
324 }
5999c315
JF
325}
326
652ec1ba 327void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0
JF
328 object_->Output(out, Precedence(), CYLeft(flags));
329 if (const char *word = property_->Word())
330 out << '.' << word;
96a7e5c2
JF
331 else
332 out << '[' << *property_ << ']';
9b5527f0
JF
333}
334
fb98ac0c 335void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 336 out << "do";
d29365ce 337 code_->Single(out, CYCenter(flags));
96a7e5c2 338 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
339}
340
652ec1ba 341void CYElement::Output(CYOutput &out) const {
5999c315 342 if (value_ != NULL)
b09da87b 343 value_->Output(out, CYPA, CYNoFlags);
11c1cc16 344 if (next_ != NULL || value_ == NULL) {
5999c315 345 out << ',';
96a7e5c2 346 if (next_ != NULL && next_->value_ != NULL)
11c1cc16
JF
347 out << ' ';
348 }
5befe15e
JF
349 if (next_ != NULL)
350 next_->Output(out);
5999c315
JF
351}
352
fb98ac0c 353void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 354 out.Terminate();
5999c315
JF
355}
356
fb98ac0c 357void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
358 expression_->Output(out, flags | CYNoBF);
359 out << ';';
5999c315
JF
360}
361
652ec1ba 362void CYExpression::ClassName(CYOutput &out, bool object) const {
e5bc40db
JF
363 Output(out, CYPA, CYNoFlags);
364}
365
cac61857
JF
366const char *CYExpression::ForEachIn() const {
367 return NULL;
368}
369
652ec1ba 370void CYExpression::For(CYOutput &out) const {
cac61857
JF
371 Output(out, CYNoIn);
372}
373
652ec1ba 374void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 375 Output(out, flags | CYNoRightHand);
d35a3b07
JF
376}
377
96a7e5c2
JF
378void CYExpression::Output(CYOutput &out) const {
379 Output(out, CYNoFlags);
380}
381
652ec1ba 382void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
96a7e5c2
JF
383 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
384 out << '(' << *this << ')';
385 else
b09da87b
JF
386 Output(out, flags);
387}
388
b10bd496 389void CYFinally::Output(CYOutput &out) const {
3b52fd1a 390 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
391}
392
fb98ac0c 393void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 394 out << "for" << ' ' << '(';
5999c315 395 if (initialiser_ != NULL)
cac61857 396 initialiser_->For(out);
1fdca2fa 397 out.Terminate();
96a7e5c2 398 out << test_;
1fdca2fa 399 out.Terminate();
96a7e5c2 400 out << increment_;
5999c315 401 out << ')';
d29365ce 402 code_->Single(out, CYRight(flags));
5999c315
JF
403}
404
fb98ac0c 405void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
406 out << "for" << ' ' << "each" << ' ' << '(';
407 initialiser_->ForIn(out, CYNoIn);
408 out << "in" << *set_ << ')';
409 code_->Single(out, CYRight(flags));
75b0a457
JF
410}
411
4644480a
JF
412void CYForEachInComprehension::Output(CYOutput &out) const {
413 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
414}
415
fb98ac0c 416void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 417 out << "for" << ' ' << '(';
029bc65b
JF
418 if (initialiser_ != NULL)
419 initialiser_->ForIn(out, CYNoIn);
96a7e5c2 420 out << "in" << *set_ << ')';
fb98ac0c 421 code_->Single(out, CYRight(flags));
5999c315
JF
422}
423
4644480a
JF
424void CYForInComprehension::Output(CYOutput &out) const {
425 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
426}
427
fb98ac0c 428void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 429 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
430 bool protect((flags & CYNoFunction) != 0);
431 if (protect)
432 out << '(';
fb98ac0c 433 out << "function";
029bc65b
JF
434 if (out.options_.verbose_)
435 out.out_ << ':' << static_cast<const CYScope *>(this);
fb98ac0c
JF
436 if (name_ != NULL)
437 out << ' ' << *name_;
1fdca2fa 438 out << '(' << parameters_ << ')';
3b52fd1a 439 out << ' ' << code_;
fb98ac0c
JF
440 if (protect)
441 out << ')';
442}
443
444void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
445 CYFunction::Output(out, flags);
446}
447
448void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
449 CYFunction::Output(out, flags);
b09da87b
JF
450}
451
652ec1ba 452void CYFunctionParameter::Output(CYOutput &out) const {
b09da87b 453 out << *name_;
96a7e5c2
JF
454 if (next_ != NULL)
455 out << ',' << ' ' << *next_;
5999c315
JF
456}
457
029bc65b
JF
458const char *CYIdentifier::Word() const {
459 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
460}
461
fb98ac0c
JF
462void CYIf::Output(CYOutput &out, CYFlags flags) const {
463 bool protect(false);
464 if (false_ == NULL && (flags & CYNoDangle) != 0) {
465 protect = true;
466 out << '{';
96a7e5c2 467 }
1fdca2fa
JF
468
469 out << "if" << ' ' << '(' << *test_ << ')';
470
fb98ac0c 471 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 472
fb98ac0c 473 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
474 if (false_ == NULL)
475 jacks |= right;
d29365ce
JF
476 else
477 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 478
3b52fd1a 479 true_->Single(out, jacks);
1fdca2fa 480
5999c315 481 if (false_ != NULL) {
fb98ac0c 482 out << "else";
96a7e5c2 483 false_->Single(out, right);
5999c315 484 }
1fdca2fa 485
fb98ac0c
JF
486 if (protect)
487 out << '}';
5999c315
JF
488}
489
4644480a
JF
490void CYIfComprehension::Output(CYOutput &out) const {
491 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
492}
493
652ec1ba 494void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 495 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 496 if (const char *word = property_->Word())
3b52fd1a 497 out << "->" << word;
96a7e5c2 498 else
3b52fd1a 499 out << "->" << '[' << *property_ << ']';
5999c315
JF
500}
501
652ec1ba 502void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 503 const char *name(Operator());
d09e527c 504 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
505 if (protect)
506 out << '(';
b09da87b 507 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 508 lhs_->Output(out, Precedence(), left);
96a7e5c2 509 out << ' ' << name << ' ';
b09da87b 510 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
511 rhs_->Output(out, Precedence() - 1, right);
512 if (protect)
513 out << ')';
5999c315
JF
514}
515
3b52fd1a
JF
516void CYLabel::Output(CYOutput &out, CYFlags flags) const {
517 out << *name_ << ':' << ' ';
518 statement_->Single(out, CYRight(flags));
519}
520
fb98ac0c 521void CYLet::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 522 out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << code_;
cac61857
JF
523}
524
652ec1ba 525void CYNew::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 526 out << "new" << ' ';
11c1cc16 527 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 528 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
529 if (arguments_ != NULL)
530 out << '(' << *arguments_ << ')';
5999c315
JF
531}
532
652ec1ba 533void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
534 CYWord::Output(out);
535}
536
652ec1ba 537void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
538 std::ostringstream str;
539 CYNumerify(str, Value());
9561f209
JF
540 std::string value(str.str());
541 out << value.c_str();
542 // XXX: this should probably also handle hex conversions and exponents
543 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
544 out << '.';
5999c315
JF
545}
546
652ec1ba 547void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 548 Output(out, CYNoFlags);
e5bc40db
JF
549}
550
652ec1ba 551void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
552 bool protect((flags & CYNoBrace) != 0);
553 if (protect)
554 out << '(';
c0bc320e
JF
555 out << '{' << '\n';
556 ++out.indent_;
3b52fd1a 557 out << properties_;
c0bc320e
JF
558 --out.indent_;
559 out << '\t' << '}';
b09da87b
JF
560 if (protect)
561 out << ')';
693d501b
JF
562}
563
652ec1ba 564void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 565 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 566 out << Operator();
5999c315
JF
567}
568
652ec1ba 569void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 570 const char *name(Operator());
1ef7d061 571 out << name;
96a7e5c2 572 if (Alphabetic())
11c1cc16 573 out << ' ';
96a7e5c2 574 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
575}
576
3b52fd1a
JF
577void CYProgram::Output(CYOutput &out) const {
578 if (statements_ != NULL)
579 statements_->Multiple(out);
580}
581
652ec1ba 582void CYProperty::Output(CYOutput &out) const {
c0bc320e 583 out << '\t';
e5bc40db 584 name_->PropertyName(out);
96a7e5c2 585 out << ':' << ' ';
b09da87b 586 value_->Output(out, CYPA, CYNoFlags);
96a7e5c2 587 if (next_ != NULL)
c0bc320e
JF
588 out << ',' << '\n' << *next_;
589 else
590 out << '\n';
5999c315
JF
591}
592
63cd45c9
JF
593void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
594 out << Value();
63cd45c9
JF
595}
596
fb98ac0c 597void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
598 out << "return";
599 if (value_ != NULL)
600 out << ' ' << *value_;
601 out << ';';
5999c315
JF
602}
603
fb98ac0c
JF
604void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
605 bool first(true);
606 for (const CYStatement *next(this); next != NULL; next = next->next_) {
607 bool last(next->next_ == NULL);
608 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
fb98ac0c 609 first = false;
1fdca2fa 610 out << '\t';
fb98ac0c 611 next->Output(out, jacks);
1fdca2fa 612 out << '\n';
fb98ac0c 613 }
5999c315
JF
614}
615
3b52fd1a
JF
616void CYStatement::Single(CYOutput &out, CYFlags flags) const {
617 _assert(next_ == NULL);
618 out << '\n';
619 ++out.indent_;
620 out << '\t';
621 Output(out, flags);
622 out << '\n';
623 --out.indent_;
5999c315
JF
624}
625
652ec1ba 626void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 627 std::ostringstream str;
520c130f 628 CYStringify(str, value_, size_);
96a7e5c2 629 out << str.str().c_str();
5999c315
JF
630}
631
652ec1ba 632void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
633 if (const char *word = Word())
634 out << word;
635 else
96a7e5c2 636 out << *this;
e5bc40db
JF
637}
638
c0bc320e
JF
639static const char *Reserved_[] = {
640 "false", "null", "true",
641
642 "break", "case", "catch", "continue", "default",
643 "delete", "do", "else", "finally", "for", "function",
644 "if", "in", "instanceof", "new", "return", "switch",
645 "this", "throw", "try", "typeof", "var", "void",
646 "while", "with",
647
648 "debugger", "const",
649
650 "class", "enum", "export", "extends", "import", "super",
651
652 "abstract", "boolean", "byte", "char", "double", "final",
653 "float", "goto", "int", "long", "native", "short",
654 "synchronized", "throws", "transient", "volatile",
655
656 "let", "yield",
657
c0bc320e
JF
658 NULL
659};
660
11c1cc16
JF
661const char *CYString::Word() const {
662 if (size_ == 0 || !WordStartRange_[value_[0]])
663 return NULL;
664 for (size_t i(1); i != size_; ++i)
665 if (!WordEndRange_[value_[i]])
666 return NULL;
667 const char *value(Value());
c0bc320e 668 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
669 if (strcmp(*reserved, value) == 0)
670 return NULL;
671 return value;
672}
673
fb98ac0c 674void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
675 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
676 out << clauses_;
5999c315
JF
677 out << '}';
678}
679
652ec1ba 680void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
681 CYWord::Output(out);
682}
683
37954781
JF
684namespace cy {
685namespace Syntax {
686
687void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
688 out << "throw";
689 if (value_ != NULL)
690 out << ' ' << *value_;
691 out << ';';
5999c315
JF
692}
693
37954781 694void Try::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 695 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
696}
697
37954781
JF
698} }
699
fb98ac0c 700void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 701 out << "var";
96a7e5c2
JF
702 declarations_->Output(out, flags);
703 out << ';';
cac61857
JF
704}
705
652ec1ba 706void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
707 out << *name_;
708}
709
fb98ac0c 710void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 711 out << "while" << '(' << *test_ << ')';
fb98ac0c 712 code_->Single(out, CYRight(flags));
5999c315
JF
713}
714
fb98ac0c 715void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 716 out << "with" << '(' << *scope_ << ')';
fb98ac0c 717 code_->Single(out, CYRight(flags));
5999c315
JF
718}
719
652ec1ba 720void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
721 if (object)
722 out << "objc_getClass(";
029bc65b 723 out << '"' << Word() << '"';
367eebb1
JF
724 if (object)
725 out << ')';
e5bc40db
JF
726}
727
652ec1ba 728void CYWord::Output(CYOutput &out) const {
029bc65b
JF
729 out << Word();
730 if (out.options_.verbose_)
731 out.out_ << '@' << this;
5999c315 732}
e5bc40db 733
652ec1ba 734void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
735 Output(out);
736}
029bc65b
JF
737
738const char *CYWord::Word() const {
739 return word_;
740}