]> git.saurik.com Git - cycript.git/blame - Output.cpp
Rename CYForEachIn to CYForOf to better match ECMA6.
[cycript.git] / Output.cpp
CommitLineData
b3378a02
JF
1/* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2010 Jay Freeman (saurik)
4644480a
JF
3*/
4
b3378a02 5/* GNU Lesser General Public License, Version 3 {{{ */
4644480a 6/*
b3378a02
JF
7 * Cycript is free software: you can redistribute it and/or modify it under
8 * the terms of the GNU Lesser General Public License as published by the
9 * Free Software Foundation, either version 3 of the License, or (at your
10 * option) any later version.
4644480a 11 *
b3378a02
JF
12 * Cycript is distributed in the hope that it will be useful, but WITHOUT
13 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
14 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public
15 * License for more details.
4644480a 16 *
b3378a02
JF
17 * You should have received a copy of the GNU Lesser General Public License
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) {
96a7e5c2 121 if (next_->name_ == NULL)
11c1cc16 122 out << ',';
96a7e5c2 123 out << ' ' << *next_;
5999c315
JF
124 }
125}
126
652ec1ba 127void CYArray::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 128 out << '[' << elements_ << ']';
5befe15e
JF
129}
130
652ec1ba 131void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
4644480a 132 out << '[' << *expression_ << ' ' << *comprehensions_ << ']';
75b0a457
JF
133}
134
652ec1ba 135void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 136 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
96a7e5c2 137 out << ' ' << Operator() << ' ';
b09da87b 138 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
139}
140
3b52fd1a
JF
141void CYBlock::Output(CYOutput &out) const {
142 out << '{' << '\n';
143 ++out.indent_;
144 if (statements_ != NULL)
145 statements_->Multiple(out);
146 --out.indent_;
147 out << '\t' << '}';
148}
149
fb98ac0c 150void CYBlock::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a
JF
151 if (statements_ == NULL)
152 out.Terminate();
153 else if (statements_->next_ == NULL)
154 statements_->Single(out, flags);
155 else
156 Output(out);
9e562cfc
JF
157}
158
652ec1ba 159void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
160 out << (Value() ? "true" : "false");
161}
162
fb98ac0c 163void CYBreak::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
164 out << "break";
165 if (label_ != NULL)
166 out << ' ' << *label_;
96a7e5c2 167 out << ';';
5999c315
JF
168}
169
652ec1ba 170void CYCall::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
171 bool protect((flags & CYNoCall) != 0);
172 if (protect)
173 out << '(';
174 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
96a7e5c2 175 out << '(' << arguments_ << ')';
fb98ac0c
JF
176 if (protect)
177 out << ')';
5999c315
JF
178}
179
37954781
JF
180namespace cy {
181namespace Syntax {
182
183void Catch::Output(CYOutput &out) const {
3b52fd1a 184 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ' << code_;
5999c315
JF
185}
186
37954781
JF
187} }
188
320ce753
JF
189void CYComment::Output(CYOutput &out, CYFlags flags) const {
190 out << '\r';
14ec9e00
JF
191 out.out_ << value_;
192 out.right_ = true;
320ce753
JF
193 out << '\r';
194}
195
652ec1ba 196void CYCompound::Output(CYOutput &out, CYFlags flags) const {
e5bc40db
JF
197 if (CYExpression *expression = expressions_)
198 if (CYExpression *next = expression->next_) {
199 expression->Output(out, CYLeft(flags));
200 CYFlags center(CYCenter(flags));
201 while (next != NULL) {
202 expression = next;
96a7e5c2 203 out << ',' << ' ';
e5bc40db
JF
204 next = expression->next_;
205 CYFlags right(next != NULL ? center : CYRight(flags));
206 expression->Output(out, right);
207 }
208 } else
209 expression->Output(out, flags);
210}
211
652ec1ba 212void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 213 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 214 out << ' ' << '?' << ' ';
5999c315 215 if (true_ != NULL)
8351aa30 216 true_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 217 out << ' ' << ':' << ' ';
8351aa30 218 false_->Output(out, CYAssign::Precedence_, CYRight(flags));
5999c315
JF
219}
220
fb98ac0c 221void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
222 out << "continue";
223 if (label_ != NULL)
224 out << ' ' << *label_;
96a7e5c2 225 out << ';';
5999c315
JF
226}
227
652ec1ba 228void CYClause::Output(CYOutput &out) const {
96a7e5c2
JF
229 if (case_ != NULL)
230 out << "case" << ' ' << *case_;
231 else
5999c315 232 out << "default";
1fdca2fa 233 out << ':' << '\n';
3b52fd1a
JF
234 if (statements_ != NULL)
235 statements_->Multiple(out);
96a7e5c2 236 out << next_;
cac61857
JF
237}
238
c8a0500b
JF
239void CYDebugger::Output(CYOutput &out, CYFlags flags) const {
240 out << "debugger" << ';';
241}
242
652ec1ba 243void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 244 out << "var";
96a7e5c2 245 Output(out, CYRight(flags));
75b0a457
JF
246}
247
652ec1ba 248void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 249 out << *identifier_;
e013809d 250 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
d35a3b07 251 if (initialiser_ != NULL) {
96a7e5c2 252 out << ' ' << '=' << ' ';
8351aa30 253 initialiser_->Output(out, CYAssign::Precedence_, CYRight(flags));
96a7e5c2 254 }
5999c315
JF
255}
256
15b88a33 257void CYForDeclarations::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 258 out << "var";
15b88a33 259 Output(out, CYRight(flags));
96a7e5c2
JF
260}
261
262void CYDeclarations::Output(CYOutput &out) const {
263 Output(out, CYNoFlags);
cac61857 264}
d35a3b07 265
652ec1ba 266void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 267 const CYDeclarations *declaration(this);
fb98ac0c 268 bool first(true);
d35a3b07 269
c8a0500b
JF
270 for (;;) {
271 CYDeclarations *next(declaration->next_);
272
273 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
274 first = false;
275 declaration->declaration_->Output(out, jacks);
276
277 if (next == NULL)
278 break;
279
96a7e5c2 280 out << ',' << ' ';
75b0a457 281 declaration = next;
d35a3b07 282 }
5999c315
JF
283}
284
652ec1ba 285void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
b38adb44 286 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
9b5527f0
JF
287 if (const char *word = property_->Word())
288 out << '.' << word;
96a7e5c2
JF
289 else
290 out << '[' << *property_ << ']';
9b5527f0
JF
291}
292
fb98ac0c 293void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 294 out << "do";
d29365ce 295 code_->Single(out, CYCenter(flags));
96a7e5c2 296 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
297}
298
652ec1ba 299void CYElement::Output(CYOutput &out) const {
5999c315 300 if (value_ != NULL)
8351aa30 301 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
11c1cc16 302 if (next_ != NULL || value_ == NULL) {
5999c315 303 out << ',';
96a7e5c2 304 if (next_ != NULL && next_->value_ != NULL)
11c1cc16
JF
305 out << ' ';
306 }
5befe15e
JF
307 if (next_ != NULL)
308 next_->Output(out);
5999c315
JF
309}
310
fb98ac0c 311void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 312 out.Terminate();
5999c315
JF
313}
314
fb98ac0c 315void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
316 expression_->Output(out, flags | CYNoBF);
317 out << ';';
5999c315
JF
318}
319
652ec1ba 320void CYExpression::ClassName(CYOutput &out, bool object) const {
8351aa30 321 Output(out, CYAssign::Precedence_, CYNoFlags);
e5bc40db
JF
322}
323
652ec1ba 324void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 325 Output(out, flags | CYNoRightHand);
d35a3b07
JF
326}
327
96a7e5c2
JF
328void CYExpression::Output(CYOutput &out) const {
329 Output(out, CYNoFlags);
330}
331
652ec1ba 332void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
96a7e5c2
JF
333 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
334 out << '(' << *this << ')';
335 else
b09da87b
JF
336 Output(out, flags);
337}
338
b10bd496 339void CYFinally::Output(CYOutput &out) const {
3b52fd1a 340 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
341}
342
fb98ac0c 343void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 344 out << "for" << ' ' << '(';
5999c315 345 if (initialiser_ != NULL)
15b88a33 346 initialiser_->Output(out, CYNoIn);
1fdca2fa 347 out.Terminate();
e661185c
JF
348 if (test_ != NULL)
349 out << ' ';
96a7e5c2 350 out << test_;
1fdca2fa 351 out.Terminate();
e661185c
JF
352 if (increment_ != NULL)
353 out << ' ';
96a7e5c2 354 out << increment_;
5999c315 355 out << ')';
d29365ce 356 code_->Single(out, CYRight(flags));
5999c315
JF
357}
358
d5618df7 359void CYForOf::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
360 out << "for" << ' ' << "each" << ' ' << '(';
361 initialiser_->ForIn(out, CYNoIn);
362 out << "in" << *set_ << ')';
363 code_->Single(out, CYRight(flags));
75b0a457
JF
364}
365
d5618df7 366void CYForOfComprehension::Output(CYOutput &out) const {
4644480a 367 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
368}
369
fb98ac0c 370void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 371 out << "for" << ' ' << '(';
029bc65b
JF
372 if (initialiser_ != NULL)
373 initialiser_->ForIn(out, CYNoIn);
96a7e5c2 374 out << "in" << *set_ << ')';
fb98ac0c 375 code_->Single(out, CYRight(flags));
5999c315
JF
376}
377
4644480a
JF
378void CYForInComprehension::Output(CYOutput &out) const {
379 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
380}
381
fb98ac0c 382void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 383 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
384 bool protect((flags & CYNoFunction) != 0);
385 if (protect)
386 out << '(';
fb98ac0c
JF
387 out << "function";
388 if (name_ != NULL)
389 out << ' ' << *name_;
1fdca2fa 390 out << '(' << parameters_ << ')';
3b52fd1a 391 out << ' ' << code_;
fb98ac0c
JF
392 if (protect)
393 out << ')';
394}
395
396void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
397 CYFunction::Output(out, flags);
398}
399
400void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
401 CYFunction::Output(out, flags);
b09da87b
JF
402}
403
652ec1ba 404void CYFunctionParameter::Output(CYOutput &out) const {
c8a0500b 405 initialiser_->Output(out, CYNoFlags);
96a7e5c2
JF
406 if (next_ != NULL)
407 out << ',' << ' ' << *next_;
5999c315
JF
408}
409
029bc65b
JF
410const char *CYIdentifier::Word() const {
411 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
412}
413
fb98ac0c
JF
414void CYIf::Output(CYOutput &out, CYFlags flags) const {
415 bool protect(false);
416 if (false_ == NULL && (flags & CYNoDangle) != 0) {
417 protect = true;
418 out << '{';
96a7e5c2 419 }
1fdca2fa
JF
420
421 out << "if" << ' ' << '(' << *test_ << ')';
422
fb98ac0c 423 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 424
fb98ac0c 425 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
426 if (false_ == NULL)
427 jacks |= right;
d29365ce
JF
428 else
429 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 430
3b52fd1a 431 true_->Single(out, jacks);
1fdca2fa 432
5999c315 433 if (false_ != NULL) {
e661185c 434 out << '\t' << "else";
96a7e5c2 435 false_->Single(out, right);
5999c315 436 }
1fdca2fa 437
fb98ac0c
JF
438 if (protect)
439 out << '}';
5999c315
JF
440}
441
4644480a
JF
442void CYIfComprehension::Output(CYOutput &out) const {
443 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
444}
445
652ec1ba 446void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 447 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 448 if (const char *word = property_->Word())
3b52fd1a 449 out << "->" << word;
96a7e5c2 450 else
3b52fd1a 451 out << "->" << '[' << *property_ << ']';
5999c315
JF
452}
453
652ec1ba 454void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 455 const char *name(Operator());
d09e527c 456 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
457 if (protect)
458 out << '(';
b09da87b 459 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 460 lhs_->Output(out, Precedence(), left);
96a7e5c2 461 out << ' ' << name << ' ';
b09da87b 462 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
463 rhs_->Output(out, Precedence() - 1, right);
464 if (protect)
465 out << ')';
5999c315
JF
466}
467
3b52fd1a
JF
468void CYLabel::Output(CYOutput &out, CYFlags flags) const {
469 out << *name_ << ':' << ' ';
470 statement_->Single(out, CYRight(flags));
471}
472
c8a0500b 473void CYLetStatement::Output(CYOutput &out, CYFlags flags) const {
15b88a33
JF
474 out << "let" << ' ' << '(' << *declarations_ << ')';
475 code_->Single(out, CYRight(flags));
cac61857
JF
476}
477
2eb8215d
JF
478namespace cy {
479namespace Syntax {
480
481void New::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 482 out << "new" << ' ';
11c1cc16 483 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 484 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
485 if (arguments_ != NULL)
486 out << '(' << *arguments_ << ')';
5999c315
JF
487}
488
2eb8215d
JF
489} }
490
652ec1ba 491void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
492 CYWord::Output(out);
493}
494
652ec1ba 495void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
496 std::ostringstream str;
497 CYNumerify(str, Value());
9561f209
JF
498 std::string value(str.str());
499 out << value.c_str();
500 // XXX: this should probably also handle hex conversions and exponents
501 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
502 out << '.';
5999c315
JF
503}
504
652ec1ba 505void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 506 Output(out, CYNoFlags);
e5bc40db
JF
507}
508
652ec1ba 509void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
510 bool protect((flags & CYNoBrace) != 0);
511 if (protect)
512 out << '(';
c0bc320e
JF
513 out << '{' << '\n';
514 ++out.indent_;
3b52fd1a 515 out << properties_;
c0bc320e
JF
516 --out.indent_;
517 out << '\t' << '}';
b09da87b
JF
518 if (protect)
519 out << ')';
693d501b
JF
520}
521
652ec1ba 522void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 523 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 524 out << Operator();
5999c315
JF
525}
526
652ec1ba 527void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 528 const char *name(Operator());
1ef7d061 529 out << name;
96a7e5c2 530 if (Alphabetic())
11c1cc16 531 out << ' ';
96a7e5c2 532 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
533}
534
3b52fd1a
JF
535void CYProgram::Output(CYOutput &out) const {
536 if (statements_ != NULL)
537 statements_->Multiple(out);
538}
539
652ec1ba 540void CYProperty::Output(CYOutput &out) const {
c0bc320e 541 out << '\t';
e5bc40db 542 name_->PropertyName(out);
96a7e5c2 543 out << ':' << ' ';
8351aa30 544 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 545 if (next_ != NULL)
c0bc320e
JF
546 out << ',' << '\n' << *next_;
547 else
548 out << '\n';
5999c315
JF
549}
550
63cd45c9
JF
551void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
552 out << Value();
63cd45c9
JF
553}
554
fb98ac0c 555void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
556 out << "return";
557 if (value_ != NULL)
558 out << ' ' << *value_;
559 out << ';';
5999c315
JF
560}
561
6c093cce
JF
562void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
563 call_->Output(out, CYLeft(flags));
564 out << ' ';
565 proc_->Output(out, CYRight(flags));
566}
567
568void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
569 // XXX: this is not outputting the parameters
570 out << code_;
571}
572
fb98ac0c
JF
573void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
574 bool first(true);
c2c9f509 575 CYForEach (next, this) {
fb98ac0c 576 bool last(next->next_ == NULL);
7bf4a0cd 577 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
fb98ac0c 578 first = false;
1fdca2fa 579 out << '\t';
fb98ac0c 580 next->Output(out, jacks);
1fdca2fa 581 out << '\n';
fb98ac0c 582 }
5999c315
JF
583}
584
3b52fd1a 585void CYStatement::Single(CYOutput &out, CYFlags flags) const {
0f37eca9
JF
586 if (this == NULL)
587 return out.Terminate();
588
3b52fd1a
JF
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
c0bc320e
JF
630 NULL
631};
632
11c1cc16
JF
633const char *CYString::Word() const {
634 if (size_ == 0 || !WordStartRange_[value_[0]])
635 return NULL;
636 for (size_t i(1); i != size_; ++i)
637 if (!WordEndRange_[value_[i]])
638 return NULL;
639 const char *value(Value());
c0bc320e 640 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
641 if (strcmp(*reserved, value) == 0)
642 return NULL;
643 return value;
644}
645
fb98ac0c 646void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
647 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
648 out << clauses_;
5999c315
JF
649 out << '}';
650}
651
652ec1ba 652void CYThis::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
653 CYWord::Output(out);
654}
655
37954781
JF
656namespace cy {
657namespace Syntax {
658
659void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
660 out << "throw";
661 if (value_ != NULL)
662 out << ' ' << *value_;
663 out << ';';
5999c315
JF
664}
665
37954781 666void Try::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a 667 out << "try" << ' ' << code_ << catch_ << finally_;
5999c315
JF
668}
669
37954781
JF
670} }
671
fb98ac0c 672void CYVar::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 673 out << "var";
96a7e5c2
JF
674 declarations_->Output(out, flags);
675 out << ';';
cac61857
JF
676}
677
652ec1ba 678void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
679 out << *name_;
680}
681
fb98ac0c 682void CYWhile::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 683 out << "while" << '(' << *test_ << ')';
fb98ac0c 684 code_->Single(out, CYRight(flags));
5999c315
JF
685}
686
fb98ac0c 687void CYWith::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 688 out << "with" << '(' << *scope_ << ')';
fb98ac0c 689 code_->Single(out, CYRight(flags));
5999c315
JF
690}
691
652ec1ba 692void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
693 if (object)
694 out << "objc_getClass(";
029bc65b 695 out << '"' << Word() << '"';
367eebb1
JF
696 if (object)
697 out << ')';
e5bc40db
JF
698}
699
652ec1ba 700void CYWord::Output(CYOutput &out) const {
029bc65b
JF
701 out << Word();
702 if (out.options_.verbose_)
703 out.out_ << '@' << this;
5999c315 704}
e5bc40db 705
652ec1ba 706void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
707 Output(out);
708}
029bc65b
JF
709
710const char *CYWord::Word() const {
711 return word_;
712}