]> git.saurik.com Git - cycript.git/blame - Output.cpp
Desktop Mac seems to use ^{_objc_class=...} instead of #.
[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
37954781
JF
216namespace cy {
217namespace Syntax {
218
219void Catch::Output(CYOutput &out) const {
3b52fd1a 220 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
5999c315
JF
221}
222
37954781
JF
223} }
224
652ec1ba 225void CYCompound::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
226 if (CYExpression *expression = expressions_)
227 if (CYExpression *next = expression->next_) {
228 expression->Output(out, CYLeft(flags));
229 CYFlags center(CYCenter(flags));
230 while (next != NULL) {
231 expression = next;
96a7e5c2 232 out << ',' << ' ';
e5bc40db
JF
233 next = expression->next_;
234 CYFlags right(next != NULL ? center : CYRight(flags));
235 expression->Output(out, right);
236 }
237 } else
238 expression->Output(out, flags);
239}
240
652ec1ba 241void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 242 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 243 out << ' ' << '?' << ' ';
5999c315 244 if (true_ != NULL)
b09da87b 245 true_->Output(out, CYPA, CYNoFlags);
96a7e5c2 246 out << ' ' << ':' << ' ';
b09da87b 247 false_->Output(out, CYPA, CYRight(flags));
5999c315
JF
248}
249
fb98ac0c 250void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
251 out << "continue";
252 if (label_ != NULL)
253 out << ' ' << *label_;
96a7e5c2 254 out << ';';
5999c315
JF
255}
256
652ec1ba 257void CYClause::Output(CYOutput &out) const {
96a7e5c2
JF
258 if (case_ != NULL)
259 out << "case" << ' ' << *case_;
260 else
5999c315 261 out << "default";
1fdca2fa 262 out << ':' << '\n';
3b52fd1a
JF
263 if (statements_ != NULL)
264 statements_->Multiple(out);
96a7e5c2 265 out << next_;
cac61857
JF
266}
267
268const char *CYDeclaration::ForEachIn() const {
269 return identifier_->Value();
5999c315
JF
270}
271
652ec1ba 272void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 273 out << "var";
96a7e5c2 274 Output(out, CYRight(flags));
75b0a457
JF
275}
276
652ec1ba 277void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 278 out << *identifier_;
d35a3b07 279 if (initialiser_ != NULL) {
96a7e5c2 280 out << ' ' << '=' << ' ';
75b0a457 281 initialiser_->Output(out, CYPA, 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 {
9b5527f0
JF
311 object_->Output(out, Precedence(), CYLeft(flags));
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)
b09da87b 326 value_->Output(out, CYPA, 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 {
e5bc40db
JF
346 Output(out, CYPA, CYNoFlags);
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();
96a7e5c2 381 out << test_;
1fdca2fa 382 out.Terminate();
96a7e5c2 383 out << increment_;
5999c315 384 out << ')';
d29365ce 385 code_->Single(out, CYRight(flags));
5999c315
JF
386}
387
fb98ac0c 388void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
389 out << "for" << ' ' << "each" << ' ' << '(';
390 initialiser_->ForIn(out, CYNoIn);
391 out << "in" << *set_ << ')';
392 code_->Single(out, CYRight(flags));
75b0a457
JF
393}
394
4644480a
JF
395void CYForEachInComprehension::Output(CYOutput &out) const {
396 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
397}
398
fb98ac0c 399void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
400 out << "for" << ' ' << '(';
401 initialiser_->ForIn(out, CYNoIn);
402 out << "in" << *set_ << ')';
fb98ac0c 403 code_->Single(out, CYRight(flags));
5999c315
JF
404}
405
4644480a
JF
406void CYForInComprehension::Output(CYOutput &out) const {
407 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
408}
409
fb98ac0c 410void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 411 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
412 bool protect((flags & CYNoFunction) != 0);
413 if (protect)
414 out << '(';
fb98ac0c
JF
415 out << "function";
416 if (name_ != NULL)
417 out << ' ' << *name_;
1fdca2fa 418 out << '(' << parameters_ << ')';
3b52fd1a 419 out << ' ' << code_;
fb98ac0c
JF
420 if (protect)
421 out << ')';
422}
423
424void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
425 CYFunction::Output(out, flags);
426}
427
428void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
429 CYFunction::Output(out, flags);
b09da87b
JF
430}
431
652ec1ba 432void CYFunctionParameter::Output(CYOutput &out) const {
b09da87b 433 out << *name_;
96a7e5c2
JF
434 if (next_ != NULL)
435 out << ',' << ' ' << *next_;
5999c315
JF
436}
437
fb98ac0c
JF
438void CYIf::Output(CYOutput &out, CYFlags flags) const {
439 bool protect(false);
440 if (false_ == NULL && (flags & CYNoDangle) != 0) {
441 protect = true;
442 out << '{';
96a7e5c2 443 }
1fdca2fa
JF
444
445 out << "if" << ' ' << '(' << *test_ << ')';
446
fb98ac0c 447 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 448
fb98ac0c 449 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
450 if (false_ == NULL)
451 jacks |= right;
d29365ce
JF
452 else
453 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 454
3b52fd1a 455 true_->Single(out, jacks);
1fdca2fa 456
5999c315 457 if (false_ != NULL) {
fb98ac0c 458 out << "else";
96a7e5c2 459 false_->Single(out, right);
5999c315 460 }
1fdca2fa 461
fb98ac0c
JF
462 if (protect)
463 out << '}';
5999c315
JF
464}
465
4644480a
JF
466void CYIfComprehension::Output(CYOutput &out) const {
467 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
468}
469
652ec1ba 470void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 471 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 472 if (const char *word = property_->Word())
3b52fd1a 473 out << "->" << word;
96a7e5c2 474 else
3b52fd1a 475 out << "->" << '[' << *property_ << ']';
5999c315
JF
476}
477
652ec1ba 478void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 479 const char *name(Operator());
d09e527c 480 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
481 if (protect)
482 out << '(';
b09da87b 483 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 484 lhs_->Output(out, Precedence(), left);
96a7e5c2 485 out << ' ' << name << ' ';
b09da87b 486 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
487 rhs_->Output(out, Precedence() - 1, right);
488 if (protect)
489 out << ')';
5999c315
JF
490}
491
3b52fd1a
JF
492void CYLabel::Output(CYOutput &out, CYFlags flags) const {
493 out << *name_ << ':' << ' ';
494 statement_->Single(out, CYRight(flags));
495}
496
fb98ac0c 497void CYLet::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 498 out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << code_;
cac61857
JF
499}
500
652ec1ba 501void CYNew::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 502 out << "new" << ' ';
11c1cc16 503 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 504 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
505 if (arguments_ != NULL)
506 out << '(' << *arguments_ << ')';
5999c315
JF
507}
508
652ec1ba 509void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
510 CYWord::Output(out);
511}
512
652ec1ba 513void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
514 std::ostringstream str;
515 CYNumerify(str, Value());
516 out << str.str().c_str();
5999c315
JF
517}
518
652ec1ba 519void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 520 Output(out, CYNoFlags);
e5bc40db
JF
521}
522
652ec1ba 523void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
524 bool protect((flags & CYNoBrace) != 0);
525 if (protect)
526 out << '(';
c0bc320e
JF
527 out << '{' << '\n';
528 ++out.indent_;
3b52fd1a 529 out << properties_;
c0bc320e
JF
530 --out.indent_;
531 out << '\t' << '}';
b09da87b
JF
532 if (protect)
533 out << ')';
693d501b
JF
534}
535
652ec1ba 536void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 537 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 538 out << Operator();
5999c315
JF
539}
540
652ec1ba 541void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 542 const char *name(Operator());
1ef7d061 543 out << name;
96a7e5c2 544 if (Alphabetic())
11c1cc16 545 out << ' ';
96a7e5c2 546 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
547}
548
3b52fd1a
JF
549void CYProgram::Output(CYOutput &out) const {
550 if (statements_ != NULL)
551 statements_->Multiple(out);
552}
553
652ec1ba 554void CYProperty::Output(CYOutput &out) const {
c0bc320e 555 out << '\t';
e5bc40db 556 name_->PropertyName(out);
96a7e5c2 557 out << ':' << ' ';
b09da87b 558 value_->Output(out, CYPA, CYNoFlags);
96a7e5c2 559 if (next_ != NULL)
c0bc320e
JF
560 out << ',' << '\n' << *next_;
561 else
562 out << '\n';
5999c315
JF
563}
564
63cd45c9
JF
565void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
566 out << Value();
63cd45c9
JF
567}
568
fb98ac0c 569void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
570 out << "return";
571 if (value_ != NULL)
572 out << ' ' << *value_;
573 out << ';';
5999c315
JF
574}
575
fb98ac0c
JF
576void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
577 bool first(true);
578 for (const CYStatement *next(this); next != NULL; next = next->next_) {
579 bool last(next->next_ == NULL);
580 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
fb98ac0c 581 first = false;
1fdca2fa 582 out << '\t';
fb98ac0c 583 next->Output(out, jacks);
1fdca2fa 584 out << '\n';
fb98ac0c 585 }
5999c315
JF
586}
587
3b52fd1a
JF
588void CYStatement::Single(CYOutput &out, CYFlags flags) const {
589 _assert(next_ == NULL);
590 out << '\n';
591 ++out.indent_;
592 out << '\t';
593 Output(out, flags);
594 out << '\n';
595 --out.indent_;
5999c315
JF
596}
597
652ec1ba 598void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 599 std::ostringstream str;
520c130f 600 CYStringify(str, value_, size_);
96a7e5c2 601 out << str.str().c_str();
5999c315
JF
602}
603
652ec1ba 604void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
605 if (const char *word = Word())
606 out << word;
607 else
96a7e5c2 608 out << *this;
e5bc40db
JF
609}
610
c0bc320e
JF
611static const char *Reserved_[] = {
612 "false", "null", "true",
613
614 "break", "case", "catch", "continue", "default",
615 "delete", "do", "else", "finally", "for", "function",
616 "if", "in", "instanceof", "new", "return", "switch",
617 "this", "throw", "try", "typeof", "var", "void",
618 "while", "with",
619
620 "debugger", "const",
621
622 "class", "enum", "export", "extends", "import", "super",
623
624 "abstract", "boolean", "byte", "char", "double", "final",
625 "float", "goto", "int", "long", "native", "short",
626 "synchronized", "throws", "transient", "volatile",
627
628 "let", "yield",
629
630 "each",
631
632 NULL
633};
634
11c1cc16
JF
635const char *CYString::Word() const {
636 if (size_ == 0 || !WordStartRange_[value_[0]])
637 return NULL;
638 for (size_t i(1); i != size_; ++i)
639 if (!WordEndRange_[value_[i]])
640 return NULL;
641 const char *value(Value());
c0bc320e 642 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
643 if (strcmp(*reserved, value) == 0)
644 return NULL;
645 return value;
646}
647
fb98ac0c 648void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
649 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
650 out << clauses_;
5999c315
JF
651 out << '}';
652}
653
652ec1ba 654void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
655 CYWord::Output(out);
656}
657
37954781
JF
658namespace cy {
659namespace Syntax {
660
661void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
662 out << "throw";
663 if (value_ != NULL)
664 out << ' ' << *value_;
665 out << ';';
5999c315
JF
666}
667
37954781 668void Try::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 669 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
670}
671
37954781
JF
672} }
673
fb98ac0c 674void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 675 out << "var";
96a7e5c2
JF
676 declarations_->Output(out, flags);
677 out << ';';
cac61857
JF
678}
679
652ec1ba 680void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
681 out << *name_;
682}
683
fb98ac0c 684void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 685 out << "while" << '(' << *test_ << ')';
fb98ac0c 686 code_->Single(out, CYRight(flags));
5999c315
JF
687}
688
fb98ac0c 689void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 690 out << "with" << '(' << *scope_ << ')';
fb98ac0c 691 code_->Single(out, CYRight(flags));
5999c315
JF
692}
693
652ec1ba 694void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
695 if (object)
696 out << "objc_getClass(";
697 out << '"' << Value() << '"';
698 if (object)
699 out << ')';
e5bc40db
JF
700}
701
652ec1ba 702void CYWord::Output(CYOutput &out) const {
5999c315
JF
703 out << Value();
704}
e5bc40db 705
652ec1ba 706void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
707 Output(out);
708}