]> git.saurik.com Git - cycript.git/blame - Output.cpp
Preserve declaration initialisers replacing for-each.
[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
652ec1ba 239void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 240 out << "var";
96a7e5c2 241 Output(out, CYRight(flags));
75b0a457
JF
242}
243
652ec1ba 244void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 245 out << *identifier_;
e013809d 246 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
d35a3b07 247 if (initialiser_ != NULL) {
96a7e5c2 248 out << ' ' << '=' << ' ';
8351aa30 249 initialiser_->Output(out, CYAssign::Precedence_, CYRight(flags));
96a7e5c2 250 }
5999c315
JF
251}
252
15b88a33 253void CYForDeclarations::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 254 out << "var";
15b88a33 255 Output(out, CYRight(flags));
96a7e5c2
JF
256}
257
258void CYDeclarations::Output(CYOutput &out) const {
259 Output(out, CYNoFlags);
cac61857 260}
d35a3b07 261
652ec1ba 262void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 263 const CYDeclarations *declaration(this);
fb98ac0c 264 bool first(true);
d35a3b07 265 output:
75b0a457 266 CYDeclarations *next(declaration->next_);
fb98ac0c
JF
267 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
268 first = false;
269 declaration->declaration_->Output(out, jacks);
d35a3b07 270
75b0a457 271 if (next != NULL) {
96a7e5c2 272 out << ',' << ' ';
75b0a457 273 declaration = next;
d35a3b07
JF
274 goto output;
275 }
5999c315
JF
276}
277
652ec1ba 278void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
b38adb44 279 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
9b5527f0
JF
280 if (const char *word = property_->Word())
281 out << '.' << word;
96a7e5c2
JF
282 else
283 out << '[' << *property_ << ']';
9b5527f0
JF
284}
285
fb98ac0c 286void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 287 out << "do";
d29365ce 288 code_->Single(out, CYCenter(flags));
96a7e5c2 289 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
290}
291
652ec1ba 292void CYElement::Output(CYOutput &out) const {
5999c315 293 if (value_ != NULL)
8351aa30 294 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
11c1cc16 295 if (next_ != NULL || value_ == NULL) {
5999c315 296 out << ',';
96a7e5c2 297 if (next_ != NULL && next_->value_ != NULL)
11c1cc16
JF
298 out << ' ';
299 }
5befe15e
JF
300 if (next_ != NULL)
301 next_->Output(out);
5999c315
JF
302}
303
fb98ac0c 304void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 305 out.Terminate();
5999c315
JF
306}
307
fb98ac0c 308void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
309 expression_->Output(out, flags | CYNoBF);
310 out << ';';
5999c315
JF
311}
312
652ec1ba 313void CYExpression::ClassName(CYOutput &out, bool object) const {
8351aa30 314 Output(out, CYAssign::Precedence_, CYNoFlags);
e5bc40db
JF
315}
316
652ec1ba 317void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 318 Output(out, flags | CYNoRightHand);
d35a3b07
JF
319}
320
96a7e5c2
JF
321void CYExpression::Output(CYOutput &out) const {
322 Output(out, CYNoFlags);
323}
324
652ec1ba 325void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
96a7e5c2
JF
326 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
327 out << '(' << *this << ')';
328 else
b09da87b
JF
329 Output(out, flags);
330}
331
b10bd496 332void CYFinally::Output(CYOutput &out) const {
3b52fd1a 333 out << ' ' << "finally" << ' ' << code_;
b10bd496
JF
334}
335
fb98ac0c 336void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 337 out << "for" << ' ' << '(';
5999c315 338 if (initialiser_ != NULL)
15b88a33 339 initialiser_->Output(out, CYNoIn);
1fdca2fa 340 out.Terminate();
e661185c
JF
341 if (test_ != NULL)
342 out << ' ';
96a7e5c2 343 out << test_;
1fdca2fa 344 out.Terminate();
e661185c
JF
345 if (increment_ != NULL)
346 out << ' ';
96a7e5c2 347 out << increment_;
5999c315 348 out << ')';
d29365ce 349 code_->Single(out, CYRight(flags));
5999c315
JF
350}
351
fb98ac0c 352void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
353 out << "for" << ' ' << "each" << ' ' << '(';
354 initialiser_->ForIn(out, CYNoIn);
355 out << "in" << *set_ << ')';
356 code_->Single(out, CYRight(flags));
75b0a457
JF
357}
358
4644480a
JF
359void CYForEachInComprehension::Output(CYOutput &out) const {
360 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
361}
362
fb98ac0c 363void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 364 out << "for" << ' ' << '(';
029bc65b
JF
365 if (initialiser_ != NULL)
366 initialiser_->ForIn(out, CYNoIn);
96a7e5c2 367 out << "in" << *set_ << ')';
fb98ac0c 368 code_->Single(out, CYRight(flags));
5999c315
JF
369}
370
4644480a
JF
371void CYForInComprehension::Output(CYOutput &out) const {
372 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
373}
374
fb98ac0c 375void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 376 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
377 bool protect((flags & CYNoFunction) != 0);
378 if (protect)
379 out << '(';
fb98ac0c
JF
380 out << "function";
381 if (name_ != NULL)
382 out << ' ' << *name_;
1fdca2fa 383 out << '(' << parameters_ << ')';
3b52fd1a 384 out << ' ' << code_;
fb98ac0c
JF
385 if (protect)
386 out << ')';
387}
388
389void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
390 CYFunction::Output(out, flags);
391}
392
393void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
394 CYFunction::Output(out, flags);
b09da87b
JF
395}
396
652ec1ba 397void CYFunctionParameter::Output(CYOutput &out) const {
b09da87b 398 out << *name_;
96a7e5c2
JF
399 if (next_ != NULL)
400 out << ',' << ' ' << *next_;
5999c315
JF
401}
402
029bc65b
JF
403const char *CYIdentifier::Word() const {
404 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
405}
406
fb98ac0c
JF
407void CYIf::Output(CYOutput &out, CYFlags flags) const {
408 bool protect(false);
409 if (false_ == NULL && (flags & CYNoDangle) != 0) {
410 protect = true;
411 out << '{';
96a7e5c2 412 }
1fdca2fa
JF
413
414 out << "if" << ' ' << '(' << *test_ << ')';
415
fb98ac0c 416 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 417
fb98ac0c 418 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
419 if (false_ == NULL)
420 jacks |= right;
d29365ce
JF
421 else
422 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 423
3b52fd1a 424 true_->Single(out, jacks);
1fdca2fa 425
5999c315 426 if (false_ != NULL) {
e661185c 427 out << '\t' << "else";
96a7e5c2 428 false_->Single(out, right);
5999c315 429 }
1fdca2fa 430
fb98ac0c
JF
431 if (protect)
432 out << '}';
5999c315
JF
433}
434
4644480a
JF
435void CYIfComprehension::Output(CYOutput &out) const {
436 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
437}
438
652ec1ba 439void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 440 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 441 if (const char *word = property_->Word())
3b52fd1a 442 out << "->" << word;
96a7e5c2 443 else
3b52fd1a 444 out << "->" << '[' << *property_ << ']';
5999c315
JF
445}
446
652ec1ba 447void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 448 const char *name(Operator());
d09e527c 449 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
450 if (protect)
451 out << '(';
b09da87b 452 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 453 lhs_->Output(out, Precedence(), left);
96a7e5c2 454 out << ' ' << name << ' ';
b09da87b 455 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
456 rhs_->Output(out, Precedence() - 1, right);
457 if (protect)
458 out << ')';
5999c315
JF
459}
460
3b52fd1a
JF
461void CYLabel::Output(CYOutput &out, CYFlags flags) const {
462 out << *name_ << ':' << ' ';
463 statement_->Single(out, CYRight(flags));
464}
465
fb98ac0c 466void CYLet::Output(CYOutput &out, CYFlags flags) const {
15b88a33
JF
467 out << "let" << ' ' << '(' << *declarations_ << ')';
468 code_->Single(out, CYRight(flags));
cac61857
JF
469}
470
2eb8215d
JF
471namespace cy {
472namespace Syntax {
473
474void New::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 475 out << "new" << ' ';
11c1cc16 476 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 477 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
478 if (arguments_ != NULL)
479 out << '(' << *arguments_ << ')';
5999c315
JF
480}
481
2eb8215d
JF
482} }
483
652ec1ba 484void CYNull::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
485 CYWord::Output(out);
486}
487
652ec1ba 488void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
489 std::ostringstream str;
490 CYNumerify(str, Value());
9561f209
JF
491 std::string value(str.str());
492 out << value.c_str();
493 // XXX: this should probably also handle hex conversions and exponents
494 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
495 out << '.';
5999c315
JF
496}
497
652ec1ba 498void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 499 Output(out, CYNoFlags);
e5bc40db
JF
500}
501
652ec1ba 502void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
503 bool protect((flags & CYNoBrace) != 0);
504 if (protect)
505 out << '(';
c0bc320e
JF
506 out << '{' << '\n';
507 ++out.indent_;
3b52fd1a 508 out << properties_;
c0bc320e
JF
509 --out.indent_;
510 out << '\t' << '}';
b09da87b
JF
511 if (protect)
512 out << ')';
693d501b
JF
513}
514
4e11a430 515void CYOptionalFunctionParameter::Output(CYOutput &out) const {
6c093cce 516 out << *name_ << '=';
8351aa30 517 initializer_->Output(out, CYAssign::Precedence_, CYNoFlags);
4e11a430
JF
518 if (next_ != NULL)
519 out << ',' << ' ' << *next_;
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}