]> git.saurik.com Git - cycript.git/blame - Output.cpp
Fixed non-local return insanity.
[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
4e11a430 563void CYOptionalFunctionParameter::Output(CYOutput &out) const {
6c093cce 564 out << *name_ << '=';
830fda7a 565 initializer_->Output(out, CYPA, CYNoFlags);
4e11a430
JF
566 if (next_ != NULL)
567 out << ',' << ' ' << *next_;
568}
569
652ec1ba 570void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 571 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 572 out << Operator();
5999c315
JF
573}
574
652ec1ba 575void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 576 const char *name(Operator());
1ef7d061 577 out << name;
96a7e5c2 578 if (Alphabetic())
11c1cc16 579 out << ' ';
96a7e5c2 580 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
581}
582
3b52fd1a
JF
583void CYProgram::Output(CYOutput &out) const {
584 if (statements_ != NULL)
585 statements_->Multiple(out);
586}
587
652ec1ba 588void CYProperty::Output(CYOutput &out) const {
c0bc320e 589 out << '\t';
e5bc40db 590 name_->PropertyName(out);
96a7e5c2 591 out << ':' << ' ';
b09da87b 592 value_->Output(out, CYPA, CYNoFlags);
96a7e5c2 593 if (next_ != NULL)
c0bc320e
JF
594 out << ',' << '\n' << *next_;
595 else
596 out << '\n';
5999c315
JF
597}
598
63cd45c9
JF
599void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
600 out << Value();
63cd45c9
JF
601}
602
fb98ac0c 603void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
604 out << "return";
605 if (value_ != NULL)
606 out << ' ' << *value_;
607 out << ';';
5999c315
JF
608}
609
6c093cce
JF
610void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
611 call_->Output(out, CYLeft(flags));
612 out << ' ';
613 proc_->Output(out, CYRight(flags));
614}
615
616void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
617 // XXX: this is not outputting the parameters
618 out << code_;
619}
620
fb98ac0c
JF
621void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
622 bool first(true);
623 for (const CYStatement *next(this); next != NULL; next = next->next_) {
624 bool last(next->next_ == NULL);
625 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
fb98ac0c 626 first = false;
1fdca2fa 627 out << '\t';
fb98ac0c 628 next->Output(out, jacks);
1fdca2fa 629 out << '\n';
fb98ac0c 630 }
5999c315
JF
631}
632
3b52fd1a
JF
633void CYStatement::Single(CYOutput &out, CYFlags flags) const {
634 _assert(next_ == NULL);
635 out << '\n';
636 ++out.indent_;
637 out << '\t';
638 Output(out, flags);
639 out << '\n';
640 --out.indent_;
5999c315
JF
641}
642
652ec1ba 643void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 644 std::ostringstream str;
520c130f 645 CYStringify(str, value_, size_);
96a7e5c2 646 out << str.str().c_str();
5999c315
JF
647}
648
652ec1ba 649void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
650 if (const char *word = Word())
651 out << word;
652 else
96a7e5c2 653 out << *this;
e5bc40db
JF
654}
655
c0bc320e
JF
656static const char *Reserved_[] = {
657 "false", "null", "true",
658
659 "break", "case", "catch", "continue", "default",
660 "delete", "do", "else", "finally", "for", "function",
661 "if", "in", "instanceof", "new", "return", "switch",
662 "this", "throw", "try", "typeof", "var", "void",
663 "while", "with",
664
665 "debugger", "const",
666
667 "class", "enum", "export", "extends", "import", "super",
668
669 "abstract", "boolean", "byte", "char", "double", "final",
670 "float", "goto", "int", "long", "native", "short",
671 "synchronized", "throws", "transient", "volatile",
672
673 "let", "yield",
674
c0bc320e
JF
675 NULL
676};
677
11c1cc16
JF
678const char *CYString::Word() const {
679 if (size_ == 0 || !WordStartRange_[value_[0]])
680 return NULL;
681 for (size_t i(1); i != size_; ++i)
682 if (!WordEndRange_[value_[i]])
683 return NULL;
684 const char *value(Value());
c0bc320e 685 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
686 if (strcmp(*reserved, value) == 0)
687 return NULL;
688 return value;
689}
690
fb98ac0c 691void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
692 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
693 out << clauses_;
5999c315
JF
694 out << '}';
695}
696
652ec1ba 697void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
698 CYWord::Output(out);
699}
700
37954781
JF
701namespace cy {
702namespace Syntax {
703
704void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
705 out << "throw";
706 if (value_ != NULL)
707 out << ' ' << *value_;
708 out << ';';
5999c315
JF
709}
710
37954781 711void Try::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 712 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
713}
714
37954781
JF
715} }
716
fb98ac0c 717void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 718 out << "var";
96a7e5c2
JF
719 declarations_->Output(out, flags);
720 out << ';';
cac61857
JF
721}
722
652ec1ba 723void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
724 out << *name_;
725}
726
fb98ac0c 727void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 728 out << "while" << '(' << *test_ << ')';
fb98ac0c 729 code_->Single(out, CYRight(flags));
5999c315
JF
730}
731
fb98ac0c 732void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 733 out << "with" << '(' << *scope_ << ')';
fb98ac0c 734 code_->Single(out, CYRight(flags));
5999c315
JF
735}
736
652ec1ba 737void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
738 if (object)
739 out << "objc_getClass(";
029bc65b 740 out << '"' << Word() << '"';
367eebb1
JF
741 if (object)
742 out << ')';
e5bc40db
JF
743}
744
652ec1ba 745void CYWord::Output(CYOutput &out) const {
029bc65b
JF
746 out << Word();
747 if (out.options_.verbose_)
748 out.out_ << '@' << this;
5999c315 749}
e5bc40db 750
652ec1ba 751void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
752 Output(out);
753}
029bc65b
JF
754
755const char *CYWord::Word() const {
756 return word_;
757}