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