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