]> git.saurik.com Git - cycript.git/blame - Output.cpp
Began work on implementing E4X.
[cycript.git] / Output.cpp
CommitLineData
4644480a
JF
1/* Cycript - Remove Execution Server and Disassembler
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) {
d29365ce 62 return flags & ~CYNoDangle;
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;
88 else goto work;
89
90 mode_ = NoMode;
91 goto done;
96a7e5c2 92
1fdca2fa 93 work:
96a7e5c2
JF
94 if (mode_ == Terminated && rhs != '}')
95 out_ << ';';
96
97 if (rhs == ';') {
98 if (pretty_)
99 goto none;
100 else {
101 mode_ = Terminated;
102 goto done;
103 }
c0bc320e
JF
104 } else if (rhs == '+') {
105 if (mode_ == NoPlus)
106 out_ << ' ';
107 mode_ = NoPlus;
96a7e5c2
JF
108 } else if (rhs == '-') {
109 if (mode_ == NoHyphen)
110 out_ << ' ';
111 mode_ = NoHyphen;
112 } else if (WordEndRange_[rhs]) {
113 if (mode_ == NoLetter)
114 out_ << ' ';
115 mode_ = NoLetter;
116 } else none:
117 mode_ = NoMode;
118
119 out_ << rhs;
120 done:
121 return *this;
122}
123
124CYOutput &CYOutput::operator <<(const char *rhs) {
125 size_t size(strlen(rhs));
126
127 if (size == 1)
128 return *this << *rhs;
129
130 if (mode_ == Terminated)
131 out_ << ';';
132 else if (
c0bc320e 133 mode_ == NoPlus && *rhs == '+' ||
96a7e5c2
JF
134 mode_ == NoHyphen && *rhs == '-' ||
135 mode_ == NoLetter && WordEndRange_[*rhs]
136 )
137 out_ << ' ';
138
139 if (WordEndRange_[rhs[size - 1]])
140 mode_ = NoLetter;
141 else
142 mode_ = NoMode;
143
144 out_ << rhs;
145 return *this;
146}
147
652ec1ba 148void CYArgument::Output(CYOutput &out) const {
d35a3b07 149 if (name_ != NULL) {
5999c315 150 out << *name_;
96a7e5c2
JF
151 if (value_ != NULL)
152 out << ':' << ' ';
5999c315 153 }
d35a3b07 154 if (value_ != NULL)
b09da87b 155 value_->Output(out, CYPA, CYNoFlags);
5999c315 156 if (next_ != NULL) {
96a7e5c2 157 if (next_->name_ == NULL)
11c1cc16 158 out << ',';
96a7e5c2 159 out << ' ' << *next_;
5999c315
JF
160 }
161}
162
652ec1ba 163void CYArray::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 164 out << '[' << elements_ << ']';
5befe15e
JF
165}
166
652ec1ba 167void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
4644480a 168 out << '[' << *expression_ << ' ' << *comprehensions_ << ']';
75b0a457
JF
169}
170
652ec1ba 171void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 172 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
96a7e5c2 173 out << ' ' << Operator() << ' ';
b09da87b 174 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
175}
176
3b52fd1a
JF
177void CYBlock::Output(CYOutput &out) const {
178 out << '{' << '\n';
179 ++out.indent_;
180 if (statements_ != NULL)
181 statements_->Multiple(out);
182 --out.indent_;
183 out << '\t' << '}';
184}
185
fb98ac0c 186void CYBlock::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a
JF
187 if (statements_ == NULL)
188 out.Terminate();
189 else if (statements_->next_ == NULL)
190 statements_->Single(out, flags);
191 else
192 Output(out);
9e562cfc
JF
193}
194
652ec1ba 195void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
196 out << (Value() ? "true" : "false");
197}
198
fb98ac0c 199void CYBreak::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
200 out << "break";
201 if (label_ != NULL)
202 out << ' ' << *label_;
96a7e5c2 203 out << ';';
5999c315
JF
204}
205
652ec1ba 206void CYCall::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
207 bool protect((flags & CYNoCall) != 0);
208 if (protect)
209 out << '(';
210 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
96a7e5c2 211 out << '(' << arguments_ << ')';
fb98ac0c
JF
212 if (protect)
213 out << ')';
5999c315
JF
214}
215
652ec1ba 216void CYCatch::Output(CYOutput &out) const {
3b52fd1a 217 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
5999c315
JF
218}
219
652ec1ba 220void CYCompound::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
221 if (CYExpression *expression = expressions_)
222 if (CYExpression *next = expression->next_) {
223 expression->Output(out, CYLeft(flags));
224 CYFlags center(CYCenter(flags));
225 while (next != NULL) {
226 expression = next;
96a7e5c2 227 out << ',' << ' ';
e5bc40db
JF
228 next = expression->next_;
229 CYFlags right(next != NULL ? center : CYRight(flags));
230 expression->Output(out, right);
231 }
232 } else
233 expression->Output(out, flags);
234}
235
652ec1ba 236void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 237 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 238 out << ' ' << '?' << ' ';
5999c315 239 if (true_ != NULL)
b09da87b 240 true_->Output(out, CYPA, CYNoFlags);
96a7e5c2 241 out << ' ' << ':' << ' ';
b09da87b 242 false_->Output(out, CYPA, CYRight(flags));
5999c315
JF
243}
244
fb98ac0c 245void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
246 out << "continue";
247 if (label_ != NULL)
248 out << ' ' << *label_;
96a7e5c2 249 out << ';';
5999c315
JF
250}
251
652ec1ba 252void CYClause::Output(CYOutput &out) const {
96a7e5c2
JF
253 if (case_ != NULL)
254 out << "case" << ' ' << *case_;
255 else
5999c315 256 out << "default";
1fdca2fa 257 out << ':' << '\n';
3b52fd1a
JF
258 if (statements_ != NULL)
259 statements_->Multiple(out);
96a7e5c2 260 out << next_;
cac61857
JF
261}
262
263const char *CYDeclaration::ForEachIn() const {
264 return identifier_->Value();
5999c315
JF
265}
266
652ec1ba 267void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 268 out << "var";
96a7e5c2 269 Output(out, CYRight(flags));
75b0a457
JF
270}
271
652ec1ba 272void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 273 out << *identifier_;
d35a3b07 274 if (initialiser_ != NULL) {
96a7e5c2 275 out << ' ' << '=' << ' ';
75b0a457 276 initialiser_->Output(out, CYPA, CYRight(flags));
96a7e5c2 277 }
5999c315
JF
278}
279
652ec1ba 280void CYDeclarations::For(CYOutput &out) const {
fb98ac0c 281 out << "var";
96a7e5c2
JF
282 Output(out, CYNoIn);
283}
284
285void CYDeclarations::Output(CYOutput &out) const {
286 Output(out, CYNoFlags);
cac61857 287}
d35a3b07 288
652ec1ba 289void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 290 const CYDeclarations *declaration(this);
fb98ac0c 291 bool first(true);
d35a3b07 292 output:
75b0a457 293 CYDeclarations *next(declaration->next_);
fb98ac0c
JF
294 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
295 first = false;
296 declaration->declaration_->Output(out, jacks);
d35a3b07 297
75b0a457 298 if (next != NULL) {
96a7e5c2 299 out << ',' << ' ';
75b0a457 300 declaration = next;
d35a3b07
JF
301 goto output;
302 }
5999c315
JF
303}
304
652ec1ba 305void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0
JF
306 object_->Output(out, Precedence(), CYLeft(flags));
307 if (const char *word = property_->Word())
308 out << '.' << word;
96a7e5c2
JF
309 else
310 out << '[' << *property_ << ']';
9b5527f0
JF
311}
312
fb98ac0c 313void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 314 out << "do";
d29365ce 315 code_->Single(out, CYCenter(flags));
96a7e5c2 316 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
317}
318
652ec1ba 319void CYElement::Output(CYOutput &out) const {
5999c315 320 if (value_ != NULL)
b09da87b 321 value_->Output(out, CYPA, CYNoFlags);
11c1cc16 322 if (next_ != NULL || value_ == NULL) {
5999c315 323 out << ',';
96a7e5c2 324 if (next_ != NULL && next_->value_ != NULL)
11c1cc16
JF
325 out << ' ';
326 }
5befe15e
JF
327 if (next_ != NULL)
328 next_->Output(out);
5999c315
JF
329}
330
fb98ac0c 331void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 332 out.Terminate();
5999c315
JF
333}
334
fb98ac0c 335void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
336 expression_->Output(out, flags | CYNoBF);
337 out << ';';
5999c315
JF
338}
339
652ec1ba 340void CYExpression::ClassName(CYOutput &out, bool object) const {
e5bc40db
JF
341 Output(out, CYPA, CYNoFlags);
342}
343
cac61857
JF
344const char *CYExpression::ForEachIn() const {
345 return NULL;
346}
347
652ec1ba 348void CYExpression::For(CYOutput &out) const {
cac61857
JF
349 Output(out, CYNoIn);
350}
351
652ec1ba 352void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 353 Output(out, flags | CYNoRightHand);
d35a3b07
JF
354}
355
96a7e5c2
JF
356void CYExpression::Output(CYOutput &out) const {
357 Output(out, CYNoFlags);
358}
359
652ec1ba 360void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
96a7e5c2
JF
361 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
362 out << '(' << *this << ')';
363 else
b09da87b
JF
364 Output(out, flags);
365}
366
b10bd496 367void CYFinally::Output(CYOutput &out) const {
3b52fd1a 368 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
369}
370
fb98ac0c 371void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 372 out << "for" << ' ' << '(';
5999c315 373 if (initialiser_ != NULL)
cac61857 374 initialiser_->For(out);
1fdca2fa 375 out.Terminate();
96a7e5c2 376 out << test_;
1fdca2fa 377 out.Terminate();
96a7e5c2 378 out << increment_;
5999c315 379 out << ')';
d29365ce 380 code_->Single(out, CYRight(flags));
5999c315
JF
381}
382
fb98ac0c 383void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
384 out << "for" << ' ' << "each" << ' ' << '(';
385 initialiser_->ForIn(out, CYNoIn);
386 out << "in" << *set_ << ')';
387 code_->Single(out, CYRight(flags));
75b0a457
JF
388}
389
4644480a
JF
390void CYForEachInComprehension::Output(CYOutput &out) const {
391 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
392}
393
fb98ac0c 394void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
395 out << "for" << ' ' << '(';
396 initialiser_->ForIn(out, CYNoIn);
397 out << "in" << *set_ << ')';
fb98ac0c 398 code_->Single(out, CYRight(flags));
5999c315
JF
399}
400
4644480a
JF
401void CYForInComprehension::Output(CYOutput &out) const {
402 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
403}
404
fb98ac0c 405void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 406 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
407 bool protect((flags & CYNoFunction) != 0);
408 if (protect)
409 out << '(';
fb98ac0c
JF
410 out << "function";
411 if (name_ != NULL)
412 out << ' ' << *name_;
1fdca2fa 413 out << '(' << parameters_ << ')';
3b52fd1a 414 out << ' ' << code_;
fb98ac0c
JF
415 if (protect)
416 out << ')';
417}
418
419void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
420 CYFunction::Output(out, flags);
421}
422
423void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
424 CYFunction::Output(out, flags);
b09da87b
JF
425}
426
652ec1ba 427void CYFunctionParameter::Output(CYOutput &out) const {
b09da87b 428 out << *name_;
96a7e5c2
JF
429 if (next_ != NULL)
430 out << ',' << ' ' << *next_;
5999c315
JF
431}
432
fb98ac0c
JF
433void CYIf::Output(CYOutput &out, CYFlags flags) const {
434 bool protect(false);
435 if (false_ == NULL && (flags & CYNoDangle) != 0) {
436 protect = true;
437 out << '{';
96a7e5c2 438 }
1fdca2fa
JF
439
440 out << "if" << ' ' << '(' << *test_ << ')';
441
fb98ac0c 442 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 443
fb98ac0c 444 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
445 if (false_ == NULL)
446 jacks |= right;
d29365ce
JF
447 else
448 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 449
3b52fd1a 450 true_->Single(out, jacks);
1fdca2fa 451
5999c315 452 if (false_ != NULL) {
fb98ac0c 453 out << "else";
96a7e5c2 454 false_->Single(out, right);
5999c315 455 }
1fdca2fa 456
fb98ac0c
JF
457 if (protect)
458 out << '}';
5999c315
JF
459}
460
4644480a
JF
461void CYIfComprehension::Output(CYOutput &out) const {
462 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
463}
464
652ec1ba 465void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 466 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 467 if (const char *word = property_->Word())
3b52fd1a 468 out << "->" << word;
96a7e5c2 469 else
3b52fd1a 470 out << "->" << '[' << *property_ << ']';
5999c315
JF
471}
472
652ec1ba 473void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 474 const char *name(Operator());
d09e527c 475 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
476 if (protect)
477 out << '(';
b09da87b 478 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 479 lhs_->Output(out, Precedence(), left);
96a7e5c2 480 out << ' ' << name << ' ';
b09da87b 481 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
482 rhs_->Output(out, Precedence() - 1, right);
483 if (protect)
484 out << ')';
5999c315
JF
485}
486
3b52fd1a
JF
487void CYLabel::Output(CYOutput &out, CYFlags flags) const {
488 out << *name_ << ':' << ' ';
489 statement_->Single(out, CYRight(flags));
490}
491
fb98ac0c 492void CYLet::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 493 out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << code_;
cac61857
JF
494}
495
652ec1ba 496void CYNew::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 497 out << "new" << ' ';
11c1cc16 498 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 499 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
500 if (arguments_ != NULL)
501 out << '(' << *arguments_ << ')';
5999c315
JF
502}
503
652ec1ba 504void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
505 CYWord::Output(out);
506}
507
652ec1ba 508void CYNumber::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 509 char value[32];
4644480a 510 // XXX: I want this to print 1e3 rather than 1000
96a7e5c2
JF
511 sprintf(value, "%.17g", Value());
512 out << value;
5999c315
JF
513}
514
652ec1ba 515void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 516 Output(out, CYNoFlags);
e5bc40db
JF
517}
518
652ec1ba 519void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
520 bool protect((flags & CYNoBrace) != 0);
521 if (protect)
522 out << '(';
c0bc320e
JF
523 out << '{' << '\n';
524 ++out.indent_;
3b52fd1a 525 out << properties_;
c0bc320e
JF
526 --out.indent_;
527 out << '\t' << '}';
b09da87b
JF
528 if (protect)
529 out << ')';
693d501b
JF
530}
531
652ec1ba 532void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 533 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 534 out << Operator();
5999c315
JF
535}
536
652ec1ba 537void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 538 const char *name(Operator());
1ef7d061 539 out << name;
96a7e5c2 540 if (Alphabetic())
11c1cc16 541 out << ' ';
96a7e5c2 542 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
543}
544
3b52fd1a
JF
545void CYProgram::Output(CYOutput &out) const {
546 if (statements_ != NULL)
547 statements_->Multiple(out);
548}
549
652ec1ba 550void CYProperty::Output(CYOutput &out) const {
c0bc320e 551 out << '\t';
e5bc40db 552 name_->PropertyName(out);
96a7e5c2 553 out << ':' << ' ';
b09da87b 554 value_->Output(out, CYPA, CYNoFlags);
96a7e5c2 555 if (next_ != NULL)
c0bc320e
JF
556 out << ',' << '\n' << *next_;
557 else
558 out << '\n';
5999c315
JF
559}
560
63cd45c9
JF
561void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
562 out << Value();
63cd45c9
JF
563}
564
fb98ac0c 565void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
566 out << "return";
567 if (value_ != NULL)
568 out << ' ' << *value_;
569 out << ';';
5999c315
JF
570}
571
fb98ac0c
JF
572void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
573 bool first(true);
574 for (const CYStatement *next(this); next != NULL; next = next->next_) {
575 bool last(next->next_ == NULL);
576 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
fb98ac0c 577 first = false;
1fdca2fa 578 out << '\t';
fb98ac0c 579 next->Output(out, jacks);
1fdca2fa 580 out << '\n';
fb98ac0c 581 }
5999c315
JF
582}
583
3b52fd1a
JF
584void CYStatement::Single(CYOutput &out, CYFlags flags) const {
585 _assert(next_ == NULL);
586 out << '\n';
587 ++out.indent_;
588 out << '\t';
589 Output(out, flags);
590 out << '\n';
591 --out.indent_;
5999c315
JF
592}
593
652ec1ba 594void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 595 std::ostringstream str;
520c130f 596 CYStringify(str, value_, size_);
96a7e5c2 597 out << str.str().c_str();
5999c315
JF
598}
599
652ec1ba 600void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
601 if (const char *word = Word())
602 out << word;
603 else
96a7e5c2 604 out << *this;
e5bc40db
JF
605}
606
c0bc320e
JF
607static const char *Reserved_[] = {
608 "false", "null", "true",
609
610 "break", "case", "catch", "continue", "default",
611 "delete", "do", "else", "finally", "for", "function",
612 "if", "in", "instanceof", "new", "return", "switch",
613 "this", "throw", "try", "typeof", "var", "void",
614 "while", "with",
615
616 "debugger", "const",
617
618 "class", "enum", "export", "extends", "import", "super",
619
620 "abstract", "boolean", "byte", "char", "double", "final",
621 "float", "goto", "int", "long", "native", "short",
622 "synchronized", "throws", "transient", "volatile",
623
624 "let", "yield",
625
626 "each",
627
628 NULL
629};
630
11c1cc16
JF
631const char *CYString::Word() const {
632 if (size_ == 0 || !WordStartRange_[value_[0]])
633 return NULL;
634 for (size_t i(1); i != size_; ++i)
635 if (!WordEndRange_[value_[i]])
636 return NULL;
637 const char *value(Value());
c0bc320e 638 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
639 if (strcmp(*reserved, value) == 0)
640 return NULL;
641 return value;
642}
643
fb98ac0c 644void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
645 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
646 out << clauses_;
5999c315
JF
647 out << '}';
648}
649
652ec1ba 650void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
651 CYWord::Output(out);
652}
653
fb98ac0c 654void CYThrow::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
655 out << "throw";
656 if (value_ != NULL)
657 out << ' ' << *value_;
658 out << ';';
5999c315
JF
659}
660
fb98ac0c 661void CYTry::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 662 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
663}
664
fb98ac0c 665void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 666 out << "var";
96a7e5c2
JF
667 declarations_->Output(out, flags);
668 out << ';';
cac61857
JF
669}
670
652ec1ba 671void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
672 out << *name_;
673}
674
fb98ac0c 675void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 676 out << "while" << '(' << *test_ << ')';
fb98ac0c 677 code_->Single(out, CYRight(flags));
5999c315
JF
678}
679
fb98ac0c 680void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 681 out << "with" << '(' << *scope_ << ')';
fb98ac0c 682 code_->Single(out, CYRight(flags));
5999c315
JF
683}
684
652ec1ba 685void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
686 if (object)
687 out << "objc_getClass(";
688 out << '"' << Value() << '"';
689 if (object)
690 out << ')';
e5bc40db
JF
691}
692
652ec1ba 693void CYWord::Output(CYOutput &out) const {
5999c315
JF
694 out << Value();
695}
e5bc40db 696
652ec1ba 697void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
698 Output(out);
699}