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