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