]> git.saurik.com Git - cycript.git/blame - Output.cpp
Factored out the execution engine from the 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 {
287 return identifier_->Value();
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 {
1fdca2fa 355 out.Terminate();
5999c315
JF
356}
357
fb98ac0c 358void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
359 expression_->Output(out, flags | CYNoBF);
360 out << ';';
5999c315
JF
361}
362
652ec1ba 363void CYExpression::ClassName(CYOutput &out, bool object) const {
e5bc40db
JF
364 Output(out, CYPA, CYNoFlags);
365}
366
cac61857
JF
367const char *CYExpression::ForEachIn() const {
368 return NULL;
369}
370
652ec1ba 371void CYExpression::For(CYOutput &out) const {
cac61857
JF
372 Output(out, CYNoIn);
373}
374
652ec1ba 375void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 376 Output(out, flags | CYNoRightHand);
d35a3b07
JF
377}
378
96a7e5c2
JF
379void CYExpression::Output(CYOutput &out) const {
380 Output(out, CYNoFlags);
381}
382
652ec1ba 383void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
96a7e5c2
JF
384 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
385 out << '(' << *this << ')';
386 else
b09da87b
JF
387 Output(out, flags);
388}
389
b10bd496 390void CYFinally::Output(CYOutput &out) const {
3b52fd1a 391 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
392}
393
fb98ac0c 394void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 395 out << "for" << ' ' << '(';
5999c315 396 if (initialiser_ != NULL)
cac61857 397 initialiser_->For(out);
1fdca2fa 398 out.Terminate();
96a7e5c2 399 out << test_;
1fdca2fa 400 out.Terminate();
96a7e5c2 401 out << increment_;
5999c315 402 out << ')';
d29365ce 403 code_->Single(out, CYRight(flags));
5999c315
JF
404}
405
fb98ac0c 406void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
407 out << "for" << ' ' << "each" << ' ' << '(';
408 initialiser_->ForIn(out, CYNoIn);
409 out << "in" << *set_ << ')';
410 code_->Single(out, CYRight(flags));
75b0a457
JF
411}
412
4644480a
JF
413void CYForEachInComprehension::Output(CYOutput &out) const {
414 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
415}
416
fb98ac0c 417void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
418 out << "for" << ' ' << '(';
419 initialiser_->ForIn(out, CYNoIn);
420 out << "in" << *set_ << ')';
fb98ac0c 421 code_->Single(out, CYRight(flags));
5999c315
JF
422}
423
4644480a
JF
424void CYForInComprehension::Output(CYOutput &out) const {
425 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
426}
427
fb98ac0c 428void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 429 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
430 bool protect((flags & CYNoFunction) != 0);
431 if (protect)
432 out << '(';
fb98ac0c
JF
433 out << "function";
434 if (name_ != NULL)
435 out << ' ' << *name_;
1fdca2fa 436 out << '(' << parameters_ << ')';
3b52fd1a 437 out << ' ' << code_;
fb98ac0c
JF
438 if (protect)
439 out << ')';
440}
441
442void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
443 CYFunction::Output(out, flags);
444}
445
446void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
447 CYFunction::Output(out, flags);
b09da87b
JF
448}
449
652ec1ba 450void CYFunctionParameter::Output(CYOutput &out) const {
b09da87b 451 out << *name_;
96a7e5c2
JF
452 if (next_ != NULL)
453 out << ',' << ' ' << *next_;
5999c315
JF
454}
455
fb98ac0c
JF
456void CYIf::Output(CYOutput &out, CYFlags flags) const {
457 bool protect(false);
458 if (false_ == NULL && (flags & CYNoDangle) != 0) {
459 protect = true;
460 out << '{';
96a7e5c2 461 }
1fdca2fa
JF
462
463 out << "if" << ' ' << '(' << *test_ << ')';
464
fb98ac0c 465 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 466
fb98ac0c 467 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
468 if (false_ == NULL)
469 jacks |= right;
d29365ce
JF
470 else
471 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 472
3b52fd1a 473 true_->Single(out, jacks);
1fdca2fa 474
5999c315 475 if (false_ != NULL) {
fb98ac0c 476 out << "else";
96a7e5c2 477 false_->Single(out, right);
5999c315 478 }
1fdca2fa 479
fb98ac0c
JF
480 if (protect)
481 out << '}';
5999c315
JF
482}
483
4644480a
JF
484void CYIfComprehension::Output(CYOutput &out) const {
485 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
486}
487
652ec1ba 488void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 489 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 490 if (const char *word = property_->Word())
3b52fd1a 491 out << "->" << word;
96a7e5c2 492 else
3b52fd1a 493 out << "->" << '[' << *property_ << ']';
5999c315
JF
494}
495
652ec1ba 496void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 497 const char *name(Operator());
d09e527c 498 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
499 if (protect)
500 out << '(';
b09da87b 501 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 502 lhs_->Output(out, Precedence(), left);
96a7e5c2 503 out << ' ' << name << ' ';
b09da87b 504 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
505 rhs_->Output(out, Precedence() - 1, right);
506 if (protect)
507 out << ')';
5999c315
JF
508}
509
3b52fd1a
JF
510void CYLabel::Output(CYOutput &out, CYFlags flags) const {
511 out << *name_ << ':' << ' ';
512 statement_->Single(out, CYRight(flags));
513}
514
fb98ac0c 515void CYLet::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 516 out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << code_;
cac61857
JF
517}
518
652ec1ba 519void CYNew::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 520 out << "new" << ' ';
11c1cc16 521 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 522 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
523 if (arguments_ != NULL)
524 out << '(' << *arguments_ << ')';
5999c315
JF
525}
526
652ec1ba 527void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
528 CYWord::Output(out);
529}
530
652ec1ba 531void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
532 std::ostringstream str;
533 CYNumerify(str, Value());
9561f209
JF
534 std::string value(str.str());
535 out << value.c_str();
536 // XXX: this should probably also handle hex conversions and exponents
537 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
538 out << '.';
5999c315
JF
539}
540
652ec1ba 541void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 542 Output(out, CYNoFlags);
e5bc40db
JF
543}
544
652ec1ba 545void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
546 bool protect((flags & CYNoBrace) != 0);
547 if (protect)
548 out << '(';
c0bc320e
JF
549 out << '{' << '\n';
550 ++out.indent_;
3b52fd1a 551 out << properties_;
c0bc320e
JF
552 --out.indent_;
553 out << '\t' << '}';
b09da87b
JF
554 if (protect)
555 out << ')';
693d501b
JF
556}
557
652ec1ba 558void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 559 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 560 out << Operator();
5999c315
JF
561}
562
652ec1ba 563void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 564 const char *name(Operator());
1ef7d061 565 out << name;
96a7e5c2 566 if (Alphabetic())
11c1cc16 567 out << ' ';
96a7e5c2 568 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
569}
570
3b52fd1a
JF
571void CYProgram::Output(CYOutput &out) const {
572 if (statements_ != NULL)
573 statements_->Multiple(out);
574}
575
652ec1ba 576void CYProperty::Output(CYOutput &out) const {
c0bc320e 577 out << '\t';
e5bc40db 578 name_->PropertyName(out);
96a7e5c2 579 out << ':' << ' ';
b09da87b 580 value_->Output(out, CYPA, CYNoFlags);
96a7e5c2 581 if (next_ != NULL)
c0bc320e
JF
582 out << ',' << '\n' << *next_;
583 else
584 out << '\n';
5999c315
JF
585}
586
63cd45c9
JF
587void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
588 out << Value();
63cd45c9
JF
589}
590
fb98ac0c 591void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
592 out << "return";
593 if (value_ != NULL)
594 out << ' ' << *value_;
595 out << ';';
5999c315
JF
596}
597
fb98ac0c
JF
598void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
599 bool first(true);
600 for (const CYStatement *next(this); next != NULL; next = next->next_) {
601 bool last(next->next_ == NULL);
602 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
fb98ac0c 603 first = false;
1fdca2fa 604 out << '\t';
fb98ac0c 605 next->Output(out, jacks);
1fdca2fa 606 out << '\n';
fb98ac0c 607 }
5999c315
JF
608}
609
3b52fd1a
JF
610void CYStatement::Single(CYOutput &out, CYFlags flags) const {
611 _assert(next_ == NULL);
612 out << '\n';
613 ++out.indent_;
614 out << '\t';
615 Output(out, flags);
616 out << '\n';
617 --out.indent_;
5999c315
JF
618}
619
652ec1ba 620void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 621 std::ostringstream str;
520c130f 622 CYStringify(str, value_, size_);
96a7e5c2 623 out << str.str().c_str();
5999c315
JF
624}
625
652ec1ba 626void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
627 if (const char *word = Word())
628 out << word;
629 else
96a7e5c2 630 out << *this;
e5bc40db
JF
631}
632
c0bc320e
JF
633static const char *Reserved_[] = {
634 "false", "null", "true",
635
636 "break", "case", "catch", "continue", "default",
637 "delete", "do", "else", "finally", "for", "function",
638 "if", "in", "instanceof", "new", "return", "switch",
639 "this", "throw", "try", "typeof", "var", "void",
640 "while", "with",
641
642 "debugger", "const",
643
644 "class", "enum", "export", "extends", "import", "super",
645
646 "abstract", "boolean", "byte", "char", "double", "final",
647 "float", "goto", "int", "long", "native", "short",
648 "synchronized", "throws", "transient", "volatile",
649
650 "let", "yield",
651
652 "each",
653
654 NULL
655};
656
11c1cc16
JF
657const char *CYString::Word() const {
658 if (size_ == 0 || !WordStartRange_[value_[0]])
659 return NULL;
660 for (size_t i(1); i != size_; ++i)
661 if (!WordEndRange_[value_[i]])
662 return NULL;
663 const char *value(Value());
c0bc320e 664 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
665 if (strcmp(*reserved, value) == 0)
666 return NULL;
667 return value;
668}
669
fb98ac0c 670void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
671 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
672 out << clauses_;
5999c315
JF
673 out << '}';
674}
675
652ec1ba 676void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
677 CYWord::Output(out);
678}
679
37954781
JF
680namespace cy {
681namespace Syntax {
682
683void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
684 out << "throw";
685 if (value_ != NULL)
686 out << ' ' << *value_;
687 out << ';';
5999c315
JF
688}
689
37954781 690void Try::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 691 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
692}
693
37954781
JF
694} }
695
fb98ac0c 696void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 697 out << "var";
96a7e5c2
JF
698 declarations_->Output(out, flags);
699 out << ';';
cac61857
JF
700}
701
652ec1ba 702void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
703 out << *name_;
704}
705
fb98ac0c 706void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 707 out << "while" << '(' << *test_ << ')';
fb98ac0c 708 code_->Single(out, CYRight(flags));
5999c315
JF
709}
710
fb98ac0c 711void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 712 out << "with" << '(' << *scope_ << ')';
fb98ac0c 713 code_->Single(out, CYRight(flags));
5999c315
JF
714}
715
652ec1ba 716void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
717 if (object)
718 out << "objc_getClass(";
719 out << '"' << Value() << '"';
720 if (object)
721 out << ')';
e5bc40db
JF
722}
723
652ec1ba 724void CYWord::Output(CYOutput &out) const {
5999c315
JF
725 out << Value();
726}
e5bc40db 727
652ec1ba 728void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
729 Output(out);
730}