]> git.saurik.com Git - cycript.git/blame - Output.cpp
Fixed a bug with trailing backslashes in trampoline comments.
[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_;
e013809d 296 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
d35a3b07 297 if (initialiser_ != NULL) {
96a7e5c2 298 out << ' ' << '=' << ' ';
75b0a457 299 initialiser_->Output(out, CYPA, CYRight(flags));
96a7e5c2 300 }
5999c315
JF
301}
302
652ec1ba 303void CYDeclarations::For(CYOutput &out) const {
fb98ac0c 304 out << "var";
96a7e5c2
JF
305 Output(out, CYNoIn);
306}
307
308void CYDeclarations::Output(CYOutput &out) const {
309 Output(out, CYNoFlags);
cac61857 310}
d35a3b07 311
652ec1ba 312void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 313 const CYDeclarations *declaration(this);
fb98ac0c 314 bool first(true);
d35a3b07 315 output:
75b0a457 316 CYDeclarations *next(declaration->next_);
fb98ac0c
JF
317 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
318 first = false;
319 declaration->declaration_->Output(out, jacks);
d35a3b07 320
75b0a457 321 if (next != NULL) {
96a7e5c2 322 out << ',' << ' ';
75b0a457 323 declaration = next;
d35a3b07
JF
324 goto output;
325 }
5999c315
JF
326}
327
652ec1ba 328void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
b38adb44 329 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
9b5527f0
JF
330 if (const char *word = property_->Word())
331 out << '.' << word;
96a7e5c2
JF
332 else
333 out << '[' << *property_ << ']';
9b5527f0
JF
334}
335
fb98ac0c 336void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 337 out << "do";
d29365ce 338 code_->Single(out, CYCenter(flags));
96a7e5c2 339 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
340}
341
652ec1ba 342void CYElement::Output(CYOutput &out) const {
5999c315 343 if (value_ != NULL)
b09da87b 344 value_->Output(out, CYPA, CYNoFlags);
11c1cc16 345 if (next_ != NULL || value_ == NULL) {
5999c315 346 out << ',';
96a7e5c2 347 if (next_ != NULL && next_->value_ != NULL)
11c1cc16
JF
348 out << ' ';
349 }
5befe15e
JF
350 if (next_ != NULL)
351 next_->Output(out);
5999c315
JF
352}
353
fb98ac0c 354void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 355 out.Terminate();
5999c315
JF
356}
357
fb98ac0c 358void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
359 expression_->Output(out, flags | CYNoBF);
360 out << ';';
5999c315
JF
361}
362
652ec1ba 363void CYExpression::ClassName(CYOutput &out, bool object) const {
e5bc40db
JF
364 Output(out, CYPA, CYNoFlags);
365}
366
cac61857
JF
367const char *CYExpression::ForEachIn() const {
368 return NULL;
369}
370
652ec1ba 371void CYExpression::For(CYOutput &out) const {
cac61857
JF
372 Output(out, CYNoIn);
373}
374
652ec1ba 375void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 376 Output(out, flags | CYNoRightHand);
d35a3b07
JF
377}
378
96a7e5c2
JF
379void CYExpression::Output(CYOutput &out) const {
380 Output(out, CYNoFlags);
381}
382
652ec1ba 383void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
96a7e5c2
JF
384 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
385 out << '(' << *this << ')';
386 else
b09da87b
JF
387 Output(out, flags);
388}
389
b10bd496 390void CYFinally::Output(CYOutput &out) const {
3b52fd1a 391 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
392}
393
fb98ac0c 394void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 395 out << "for" << ' ' << '(';
5999c315 396 if (initialiser_ != NULL)
cac61857 397 initialiser_->For(out);
1fdca2fa 398 out.Terminate();
96a7e5c2 399 out << test_;
1fdca2fa 400 out.Terminate();
96a7e5c2 401 out << increment_;
5999c315 402 out << ')';
d29365ce 403 code_->Single(out, CYRight(flags));
5999c315
JF
404}
405
fb98ac0c 406void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
407 out << "for" << ' ' << "each" << ' ' << '(';
408 initialiser_->ForIn(out, CYNoIn);
409 out << "in" << *set_ << ')';
410 code_->Single(out, CYRight(flags));
75b0a457
JF
411}
412
4644480a
JF
413void CYForEachInComprehension::Output(CYOutput &out) const {
414 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
415}
416
fb98ac0c 417void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 418 out << "for" << ' ' << '(';
029bc65b
JF
419 if (initialiser_ != NULL)
420 initialiser_->ForIn(out, CYNoIn);
96a7e5c2 421 out << "in" << *set_ << ')';
fb98ac0c 422 code_->Single(out, CYRight(flags));
5999c315
JF
423}
424
4644480a
JF
425void CYForInComprehension::Output(CYOutput &out) const {
426 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
427}
428
fb98ac0c 429void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 430 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
431 bool protect((flags & CYNoFunction) != 0);
432 if (protect)
433 out << '(';
fb98ac0c
JF
434 out << "function";
435 if (name_ != NULL)
436 out << ' ' << *name_;
1fdca2fa 437 out << '(' << parameters_ << ')';
3b52fd1a 438 out << ' ' << code_;
fb98ac0c
JF
439 if (protect)
440 out << ')';
441}
442
443void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
444 CYFunction::Output(out, flags);
445}
446
447void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
448 CYFunction::Output(out, flags);
b09da87b
JF
449}
450
652ec1ba 451void CYFunctionParameter::Output(CYOutput &out) const {
b09da87b 452 out << *name_;
96a7e5c2
JF
453 if (next_ != NULL)
454 out << ',' << ' ' << *next_;
5999c315
JF
455}
456
029bc65b
JF
457const char *CYIdentifier::Word() const {
458 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
459}
460
fb98ac0c
JF
461void CYIf::Output(CYOutput &out, CYFlags flags) const {
462 bool protect(false);
463 if (false_ == NULL && (flags & CYNoDangle) != 0) {
464 protect = true;
465 out << '{';
96a7e5c2 466 }
1fdca2fa
JF
467
468 out << "if" << ' ' << '(' << *test_ << ')';
469
fb98ac0c 470 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 471
fb98ac0c 472 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
473 if (false_ == NULL)
474 jacks |= right;
d29365ce
JF
475 else
476 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 477
3b52fd1a 478 true_->Single(out, jacks);
1fdca2fa 479
5999c315 480 if (false_ != NULL) {
fb98ac0c 481 out << "else";
96a7e5c2 482 false_->Single(out, right);
5999c315 483 }
1fdca2fa 484
fb98ac0c
JF
485 if (protect)
486 out << '}';
5999c315
JF
487}
488
4644480a
JF
489void CYIfComprehension::Output(CYOutput &out) const {
490 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
491}
492
652ec1ba 493void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 494 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 495 if (const char *word = property_->Word())
3b52fd1a 496 out << "->" << word;
96a7e5c2 497 else
3b52fd1a 498 out << "->" << '[' << *property_ << ']';
5999c315
JF
499}
500
652ec1ba 501void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 502 const char *name(Operator());
d09e527c 503 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
504 if (protect)
505 out << '(';
b09da87b 506 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 507 lhs_->Output(out, Precedence(), left);
96a7e5c2 508 out << ' ' << name << ' ';
b09da87b 509 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
510 rhs_->Output(out, Precedence() - 1, right);
511 if (protect)
512 out << ')';
5999c315
JF
513}
514
3b52fd1a
JF
515void CYLabel::Output(CYOutput &out, CYFlags flags) const {
516 out << *name_ << ':' << ' ';
517 statement_->Single(out, CYRight(flags));
518}
519
fb98ac0c 520void CYLet::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 521 out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << code_;
cac61857
JF
522}
523
652ec1ba 524void CYNew::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 525 out << "new" << ' ';
11c1cc16 526 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 527 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
528 if (arguments_ != NULL)
529 out << '(' << *arguments_ << ')';
5999c315
JF
530}
531
652ec1ba 532void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
533 CYWord::Output(out);
534}
535
652ec1ba 536void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
537 std::ostringstream str;
538 CYNumerify(str, Value());
9561f209
JF
539 std::string value(str.str());
540 out << value.c_str();
541 // XXX: this should probably also handle hex conversions and exponents
542 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
543 out << '.';
5999c315
JF
544}
545
652ec1ba 546void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 547 Output(out, CYNoFlags);
e5bc40db
JF
548}
549
652ec1ba 550void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
551 bool protect((flags & CYNoBrace) != 0);
552 if (protect)
553 out << '(';
c0bc320e
JF
554 out << '{' << '\n';
555 ++out.indent_;
3b52fd1a 556 out << properties_;
c0bc320e
JF
557 --out.indent_;
558 out << '\t' << '}';
b09da87b
JF
559 if (protect)
560 out << ')';
693d501b
JF
561}
562
652ec1ba 563void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 564 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 565 out << Operator();
5999c315
JF
566}
567
652ec1ba 568void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 569 const char *name(Operator());
1ef7d061 570 out << name;
96a7e5c2 571 if (Alphabetic())
11c1cc16 572 out << ' ';
96a7e5c2 573 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
574}
575
3b52fd1a
JF
576void CYProgram::Output(CYOutput &out) const {
577 if (statements_ != NULL)
578 statements_->Multiple(out);
579}
580
652ec1ba 581void CYProperty::Output(CYOutput &out) const {
c0bc320e 582 out << '\t';
e5bc40db 583 name_->PropertyName(out);
96a7e5c2 584 out << ':' << ' ';
b09da87b 585 value_->Output(out, CYPA, CYNoFlags);
96a7e5c2 586 if (next_ != NULL)
c0bc320e
JF
587 out << ',' << '\n' << *next_;
588 else
589 out << '\n';
5999c315
JF
590}
591
63cd45c9
JF
592void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
593 out << Value();
63cd45c9
JF
594}
595
fb98ac0c 596void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
597 out << "return";
598 if (value_ != NULL)
599 out << ' ' << *value_;
600 out << ';';
5999c315
JF
601}
602
fb98ac0c
JF
603void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
604 bool first(true);
605 for (const CYStatement *next(this); next != NULL; next = next->next_) {
606 bool last(next->next_ == NULL);
607 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
fb98ac0c 608 first = false;
1fdca2fa 609 out << '\t';
fb98ac0c 610 next->Output(out, jacks);
1fdca2fa 611 out << '\n';
fb98ac0c 612 }
5999c315
JF
613}
614
3b52fd1a
JF
615void CYStatement::Single(CYOutput &out, CYFlags flags) const {
616 _assert(next_ == NULL);
617 out << '\n';
618 ++out.indent_;
619 out << '\t';
620 Output(out, flags);
621 out << '\n';
622 --out.indent_;
5999c315
JF
623}
624
652ec1ba 625void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 626 std::ostringstream str;
520c130f 627 CYStringify(str, value_, size_);
96a7e5c2 628 out << str.str().c_str();
5999c315
JF
629}
630
652ec1ba 631void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
632 if (const char *word = Word())
633 out << word;
634 else
96a7e5c2 635 out << *this;
e5bc40db
JF
636}
637
c0bc320e
JF
638static const char *Reserved_[] = {
639 "false", "null", "true",
640
641 "break", "case", "catch", "continue", "default",
642 "delete", "do", "else", "finally", "for", "function",
643 "if", "in", "instanceof", "new", "return", "switch",
644 "this", "throw", "try", "typeof", "var", "void",
645 "while", "with",
646
647 "debugger", "const",
648
649 "class", "enum", "export", "extends", "import", "super",
650
651 "abstract", "boolean", "byte", "char", "double", "final",
652 "float", "goto", "int", "long", "native", "short",
653 "synchronized", "throws", "transient", "volatile",
654
655 "let", "yield",
656
c0bc320e
JF
657 NULL
658};
659
11c1cc16
JF
660const char *CYString::Word() const {
661 if (size_ == 0 || !WordStartRange_[value_[0]])
662 return NULL;
663 for (size_t i(1); i != size_; ++i)
664 if (!WordEndRange_[value_[i]])
665 return NULL;
666 const char *value(Value());
c0bc320e 667 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
668 if (strcmp(*reserved, value) == 0)
669 return NULL;
670 return value;
671}
672
fb98ac0c 673void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
674 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
675 out << clauses_;
5999c315
JF
676 out << '}';
677}
678
652ec1ba 679void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
680 CYWord::Output(out);
681}
682
37954781
JF
683namespace cy {
684namespace Syntax {
685
686void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
687 out << "throw";
688 if (value_ != NULL)
689 out << ' ' << *value_;
690 out << ';';
5999c315
JF
691}
692
37954781 693void Try::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 694 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
695}
696
37954781
JF
697} }
698
fb98ac0c 699void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 700 out << "var";
96a7e5c2
JF
701 declarations_->Output(out, flags);
702 out << ';';
cac61857
JF
703}
704
652ec1ba 705void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
706 out << *name_;
707}
708
fb98ac0c 709void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 710 out << "while" << '(' << *test_ << ')';
fb98ac0c 711 code_->Single(out, CYRight(flags));
5999c315
JF
712}
713
fb98ac0c 714void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 715 out << "with" << '(' << *scope_ << ')';
fb98ac0c 716 code_->Single(out, CYRight(flags));
5999c315
JF
717}
718
652ec1ba 719void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
720 if (object)
721 out << "objc_getClass(";
029bc65b 722 out << '"' << Word() << '"';
367eebb1
JF
723 if (object)
724 out << ')';
e5bc40db
JF
725}
726
652ec1ba 727void CYWord::Output(CYOutput &out) const {
029bc65b
JF
728 out << Word();
729 if (out.options_.verbose_)
730 out.out_ << '@' << this;
5999c315 731}
e5bc40db 732
652ec1ba 733void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
734 Output(out);
735}
029bc65b
JF
736
737const char *CYWord::Word() const {
738 return word_;
739}