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