]> git.saurik.com Git - cycript.git/blob - Output.cpp
Implement ECMAScript 6 class syntax (sort of?...).
[cycript.git] / Output.cpp
1 /* Cycript - Optimizing JavaScript Compiler/Runtime
2 * Copyright (C) 2009-2015 Jay Freeman (saurik)
3 */
4
5 /* GNU Affero General Public License, Version 3 {{{ */
6 /*
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 **/
20 /* }}} */
21
22 #include "cycript.hpp"
23
24 #include <sstream>
25
26 #include "Syntax.hpp"
27
28 void CYOutput::Terminate() {
29 operator ()(';');
30 mode_ = NoMode;
31 }
32
33 CYOutput &CYOutput::operator <<(char rhs) {
34 if (rhs == ' ' || rhs == '\n')
35 if (pretty_)
36 operator ()(rhs);
37 else goto done;
38 else if (rhs == '\t')
39 if (pretty_)
40 for (unsigned i(0); i != indent_; ++i)
41 operator ()(" ", 4);
42 else goto done;
43 else if (rhs == '\r') {
44 if (right_) {
45 operator ()('\n');
46 right_ = false;
47 } goto done;
48 } else goto work;
49
50 right_ = true;
51 mode_ = NoMode;
52 goto done;
53
54 work:
55 if (mode_ == Terminated && rhs != '}') {
56 right_ = true;
57 operator ()(';');
58 }
59
60 if (rhs == ';') {
61 if (pretty_)
62 goto none;
63 else {
64 mode_ = Terminated;
65 goto done;
66 }
67 } else if (rhs == '+') {
68 if (mode_ == NoPlus)
69 operator ()(' ');
70 mode_ = NoPlus;
71 } else if (rhs == '-') {
72 if (mode_ == NoHyphen)
73 operator ()(' ');
74 mode_ = NoHyphen;
75 } else if (WordEndRange_[rhs]) {
76 if (mode_ == NoLetter)
77 operator ()(' ');
78 mode_ = NoLetter;
79 } else none:
80 mode_ = NoMode;
81
82 right_ = true;
83 operator ()(rhs);
84 done:
85 return *this;
86 }
87
88 CYOutput &CYOutput::operator <<(const char *rhs) {
89 size_t size(strlen(rhs));
90
91 if (size == 1)
92 return *this << *rhs;
93
94 if (mode_ == Terminated)
95 operator ()(';');
96 else if (
97 mode_ == NoPlus && *rhs == '+' ||
98 mode_ == NoHyphen && *rhs == '-' ||
99 mode_ == NoLetter && WordEndRange_[*rhs]
100 )
101 operator ()(' ');
102
103 char last(rhs[size - 1]);
104 if (WordEndRange_[last] || last == '/')
105 mode_ = NoLetter;
106 else
107 mode_ = NoMode;
108
109 right_ = true;
110 operator ()(rhs, size);
111 return *this;
112 }
113
114 void CYArgument::Output(CYOutput &out) const {
115 if (name_ != NULL) {
116 out << *name_;
117 if (value_ != NULL)
118 out << ':' << ' ';
119 }
120 if (value_ != NULL)
121 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
122 if (next_ != NULL) {
123 out << ',';
124 out << ' ' << *next_;
125 }
126 }
127
128 void CYArray::Output(CYOutput &out, CYFlags flags) const {
129 out << '[' << elements_ << ']';
130 }
131
132 void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
133 out << '[' << *expression_ << ' ' << *comprehensions_ << ']';
134 }
135
136 void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
137 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
138 out << ' ' << Operator() << ' ';
139 rhs_->Output(out, Precedence(), CYRight(flags));
140 }
141
142 void CYBlock::Output(CYOutput &out, CYFlags flags) const {
143 out << '{' << '\n';
144 ++out.indent_;
145 out << code_;
146 --out.indent_;
147 out << '\t' << '}';
148 }
149
150 void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
151 out << '!' << (Value() ? "0" : "1");
152 if ((flags & CYNoInteger) != 0)
153 out << '.';
154 }
155
156 void CYBreak::Output(CYOutput &out, CYFlags flags) const {
157 out << "break";
158 if (label_ != NULL)
159 out << ' ' << *label_;
160 out << ';';
161 }
162
163 void CYCall::Output(CYOutput &out, CYFlags flags) const {
164 bool protect((flags & CYNoCall) != 0);
165 if (protect)
166 out << '(';
167 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
168 out << '(' << arguments_ << ')';
169 if (protect)
170 out << ')';
171 }
172
173 namespace cy {
174 namespace Syntax {
175
176 void Catch::Output(CYOutput &out) const {
177 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ';
178 out << '{' << '\n';
179 ++out.indent_;
180 out << code_;
181 --out.indent_;
182 out << '\t' << '}';
183 }
184
185 } }
186
187 void CYClassExpression::Output(CYOutput &out, CYFlags flags) const {
188 bool protect((flags & CYNoClass) != 0);
189 if (protect)
190 out << '(';
191 out << "class";
192 if (name_ != NULL)
193 out << ' ' << *name_;
194 out << *tail_;;
195 if (protect)
196 out << ')';
197 }
198
199 void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
200 out << "class" << ' ' << *name_ << *tail_;
201 }
202
203 void CYClassTail::Output(CYOutput &out) const {
204 if (extends_ == NULL)
205 out << ' ';
206 else {
207 out << '\n';
208 ++out.indent_;
209 out << "extends" << ' ';
210 extends_->Output(out, CYAssign::Precedence_ - 1, CYNoFlags);
211 out << '\n';
212 --out.indent_;
213 }
214
215 out << '{' << '\n';
216 ++out.indent_;
217
218 --out.indent_;
219 out << '}';
220 }
221
222 void CYCompound::Output(CYOutput &out, CYFlags flags) const {
223 if (next_ == NULL)
224 expression_->Output(out, flags);
225 else {
226 expression_->Output(out, CYLeft(flags));
227 out << ',' << ' ';
228 next_->Output(out, CYRight(flags));
229 }
230 }
231
232 void CYComputed::PropertyName(CYOutput &out) const {
233 out << '[';
234 expression_->Output(out, CYAssign::Precedence_, CYNoFlags);
235 out << ']';
236 }
237
238 void CYCondition::Output(CYOutput &out, CYFlags flags) const {
239 test_->Output(out, Precedence() - 1, CYLeft(flags));
240 out << ' ' << '?' << ' ';
241 if (true_ != NULL)
242 true_->Output(out, CYAssign::Precedence_, CYNoFlags);
243 out << ' ' << ':' << ' ';
244 false_->Output(out, CYAssign::Precedence_, CYRight(flags));
245 }
246
247 void CYContinue::Output(CYOutput &out, CYFlags flags) const {
248 out << "continue";
249 if (label_ != NULL)
250 out << ' ' << *label_;
251 out << ';';
252 }
253
254 void CYClause::Output(CYOutput &out) const {
255 out << '\t';
256 if (case_ != NULL)
257 out << "case" << ' ' << *case_;
258 else
259 out << "default";
260 out << ':' << '\n';
261 ++out.indent_;
262 out << code_;
263 --out.indent_;
264 out << next_;
265 }
266
267 void CYDebugger::Output(CYOutput &out, CYFlags flags) const {
268 out << "debugger" << ';';
269 }
270
271 void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
272 out << "var" << ' ';
273 Output(out, CYRight(flags));
274 }
275
276 void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
277 out << *identifier_;
278 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
279 if (initialiser_ != NULL) {
280 out << ' ' << '=' << ' ';
281 initialiser_->Output(out, CYAssign::Precedence_, CYRight(flags));
282 }
283 }
284
285 void CYForDeclarations::Output(CYOutput &out, CYFlags flags) const {
286 out << "var" << ' ';
287 declarations_->Output(out, CYRight(flags));
288 }
289
290 void CYDeclarations::Output(CYOutput &out) const {
291 Output(out, CYNoFlags);
292 }
293
294 void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
295 const CYDeclarations *declaration(this);
296 bool first(true);
297
298 for (;;) {
299 CYDeclarations *next(declaration->next_);
300
301 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
302 first = false;
303 declaration->declaration_->Output(out, jacks);
304
305 if (next == NULL)
306 break;
307
308 out << ',' << ' ';
309 declaration = next;
310 }
311 }
312
313 void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
314 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
315 if (const char *word = property_->Word())
316 out << '.' << word;
317 else
318 out << '[' << *property_ << ']';
319 }
320
321 void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
322 out << "do";
323
324 unsigned line(out.position_.line);
325 unsigned indent(out.indent_);
326 code_->Single(out, CYCenter(flags), CYCompactLong);
327
328 if (out.position_.line != line && out.recent_ == indent)
329 out << ' ';
330 else
331 out << '\n' << '\t';
332
333 out << "while" << ' ' << '(' << *test_ << ')';
334 }
335
336 void CYElementSpread::Output(CYOutput &out) const {
337 out << "..." << value_;
338 }
339
340 void CYElementValue::Output(CYOutput &out) const {
341 if (value_ != NULL)
342 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
343 if (next_ != NULL || value_ == NULL) {
344 out << ',';
345 if (next_ != NULL && !next_->Elision())
346 out << ' ';
347 }
348 if (next_ != NULL)
349 next_->Output(out);
350 }
351
352 void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
353 out.Terminate();
354 }
355
356 void CYExpress::Output(CYOutput &out, CYFlags flags) const {
357 expression_->Output(out, flags | CYNoBFC);
358 out << ';';
359 }
360
361 void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
362 Output(out, flags | CYNoRightHand);
363 }
364
365 void CYExpression::Output(CYOutput &out) const {
366 Output(out, CYNoFlags);
367 }
368
369 void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const {
370 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
371 out << '(' << *this << ')';
372 else
373 Output(out, flags);
374 }
375
376 void CYExternal::Output(CYOutput &out, CYFlags flags) const {
377 out << "extern" << abi_ << typed_ << ';';
378 }
379
380 void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
381 out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << '{' << code_ << '}';
382 }
383
384 void CYFinally::Output(CYOutput &out) const {
385 out << ' ' << "finally" << ' ';
386 out << '{' << '\n';
387 ++out.indent_;
388 out << code_;
389 --out.indent_;
390 out << '\t' << '}';
391 }
392
393 void CYFor::Output(CYOutput &out, CYFlags flags) const {
394 out << "for" << ' ' << '(';
395 if (initialiser_ != NULL)
396 initialiser_->Output(out, CYNoIn);
397 out.Terminate();
398 if (test_ != NULL)
399 out << ' ';
400 out << test_;
401 out.Terminate();
402 if (increment_ != NULL)
403 out << ' ';
404 out << increment_;
405 out << ')';
406 code_->Single(out, CYRight(flags), CYCompactShort);
407 }
408
409 void CYForOf::Output(CYOutput &out, CYFlags flags) const {
410 out << "for" << ' ' << "each" << ' ' << '(';
411 initialiser_->ForIn(out, CYNoIn);
412 out << ' ' << "in" << ' ' << *set_ << ')';
413 code_->Single(out, CYRight(flags), CYCompactShort);
414 }
415
416 void CYForOfComprehension::Output(CYOutput &out) const {
417 out << "for" << ' ' << "each" << ' ' << '(';
418 declaration_->Output(out, CYNoIn);
419 out << ' ' << "in" << ' ' << *set_ << ')' << next_;
420 }
421
422 void CYForIn::Output(CYOutput &out, CYFlags flags) const {
423 out << "for" << ' ' << '(';
424 if (initialiser_ != NULL)
425 initialiser_->ForIn(out, CYNoIn);
426 out << ' ' << "in" << ' ' << *set_ << ')';
427 code_->Single(out, CYRight(flags), CYCompactShort);
428 }
429
430 void CYForInComprehension::Output(CYOutput &out) const {
431 out << "for" << ' ' << '(';
432 declaration_->Output(out, CYNoIn);
433 out << ' ' << "in" << ' ' << *set_ << ')';
434 }
435
436 void CYFunction::Output(CYOutput &out) const {
437 out << '(' << parameters_ << ')' << ' ';
438 out << '{' << '\n';
439 ++out.indent_;
440 out << code_;
441 --out.indent_;
442 out << '\t' << '}';
443 }
444
445 void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
446 // XXX: one could imagine using + here to save a byte
447 bool protect((flags & CYNoFunction) != 0);
448 if (protect)
449 out << '(';
450 out << "function";
451 if (name_ != NULL)
452 out << ' ' << *name_;
453 CYFunction::Output(out);
454 if (protect)
455 out << ')';
456 }
457
458 void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
459 out << "function" << ' ' << *name_;
460 CYFunction::Output(out);
461 }
462
463 void CYFunctionParameter::Output(CYOutput &out) const {
464 initialiser_->Output(out, CYNoFlags);
465 if (next_ != NULL)
466 out << ',' << ' ' << *next_;
467 }
468
469 const char *CYIdentifier::Word() const {
470 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
471 }
472
473 void CYIf::Output(CYOutput &out, CYFlags flags) const {
474 bool protect(false);
475 if (false_ == NULL && (flags & CYNoDangle) != 0) {
476 protect = true;
477 out << '{';
478 }
479
480 out << "if" << ' ' << '(' << *test_ << ')';
481
482 CYFlags right(protect ? CYNoFlags : CYRight(flags));
483
484 CYFlags jacks(CYNoDangle);
485 if (false_ == NULL)
486 jacks |= right;
487 else
488 jacks |= protect ? CYNoFlags : CYCenter(flags);
489
490 unsigned line(out.position_.line);
491 unsigned indent(out.indent_);
492 true_->Single(out, jacks, CYCompactShort);
493
494 if (false_ != NULL) {
495 if (out.position_.line != line && out.recent_ == indent)
496 out << ' ';
497 else
498 out << '\n' << '\t';
499
500 out << "else";
501 false_->Single(out, right, CYCompactLong);
502 }
503
504 if (protect)
505 out << '}';
506 }
507
508 void CYIfComprehension::Output(CYOutput &out) const {
509 out << "if" << ' ' << '(' << *test_ << ')' << next_;
510 }
511
512 void CYImport::Output(CYOutput &out, CYFlags flags) const {
513 out << "@import";
514 }
515
516 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
517 object_->Output(out, Precedence(), CYLeft(flags));
518 if (const char *word = property_->Word())
519 out << "->" << word;
520 else
521 out << "->" << '[' << *property_ << ']';
522 }
523
524 void CYInfix::Output(CYOutput &out, CYFlags flags) const {
525 const char *name(Operator());
526 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
527 if (protect)
528 out << '(';
529 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
530 lhs_->Output(out, Precedence(), left);
531 out << ' ' << name << ' ';
532 CYFlags right(protect ? CYNoFlags : CYRight(flags));
533 rhs_->Output(out, Precedence() - 1, right);
534 if (protect)
535 out << ')';
536 }
537
538 void CYLabel::Output(CYOutput &out, CYFlags flags) const {
539 out << *name_ << ':';
540 statement_->Single(out, CYRight(flags), CYCompactShort);
541 }
542
543 void CYParenthetical::Output(CYOutput &out, CYFlags flags) const {
544 out << '(';
545 expression_->Output(out, CYCompound::Precedence_, CYNoFlags);
546 out << ')';
547 }
548
549 void CYStatement::Output(CYOutput &out) const {
550 Multiple(out);
551 }
552
553 void CYTemplate::Output(CYOutput &out, CYFlags flags) const {
554 _assert(false);
555 }
556
557 void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
558 next_->Output(out, Precedence(), identifier);
559 out << '[';
560 out << size_;
561 out << ']';
562 }
563
564 void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
565 out << '(' << '^';
566 next_->Output(out, Precedence(), identifier);
567 out << ')' << '(' << parameters_ << ')';
568 }
569
570 void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
571 out << "const" << ' ';
572 next_->Output(out, Precedence(), identifier);
573 }
574
575 void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
576 next_->Output(out, Precedence(), identifier);
577 out << '(' << parameters_ << ')';
578 }
579
580 void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
581 out << '*';
582 next_->Output(out, Precedence(), identifier);
583 }
584
585 void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
586 out << "volatile";
587 next_->Output(out, Precedence(), identifier);
588 }
589
590 void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
591 if (this == NULL) {
592 out << identifier;
593 return;
594 }
595
596 bool protect(precedence > Precedence());
597
598 if (protect)
599 out << '(';
600 Output(out, identifier);
601 if (protect)
602 out << ')';
603 }
604
605 void CYTypedIdentifier::Output(CYOutput &out) const {
606 specifier_->Output(out);
607 modifier_->Output(out, 0, identifier_);
608 }
609
610 void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
611 out << "@encode(" << typed_ << ")";
612 }
613
614 void CYTypedParameter::Output(CYOutput &out) const {
615 out << typed_;
616 if (next_ != NULL)
617 out << ',' << ' ' << next_;
618 }
619
620 void CYLambda::Output(CYOutput &out, CYFlags flags) const {
621 // XXX: this is seriously wrong
622 out << "[](";
623 out << ")->";
624 out << "{";
625 out << "}";
626 }
627
628 void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
629 out << "typedef" << ' ' << *typed_;
630 }
631
632 void CYLetStatement::Output(CYOutput &out, CYFlags flags) const {
633 out << "let" << ' ' << '(' << *declarations_ << ')';
634 code_->Single(out, CYRight(flags), CYCompactShort);
635 }
636
637 void CYModule::Output(CYOutput &out) const {
638 out << part_;
639 if (next_ != NULL)
640 out << '.' << next_;
641 }
642
643 namespace cy {
644 namespace Syntax {
645
646 void New::Output(CYOutput &out, CYFlags flags) const {
647 out << "new" << ' ';
648 CYFlags jacks(CYNoCall | CYCenter(flags));
649 constructor_->Output(out, Precedence(), jacks);
650 if (arguments_ != NULL)
651 out << '(' << *arguments_ << ')';
652 }
653
654 } }
655
656 void CYNull::Output(CYOutput &out, CYFlags flags) const {
657 out << "null";
658 }
659
660 void CYNumber::Output(CYOutput &out, CYFlags flags) const {
661 std::ostringstream str;
662 CYNumerify(str, Value());
663 std::string value(str.str());
664 out << value.c_str();
665 // XXX: this should probably also handle hex conversions and exponents
666 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
667 out << '.';
668 }
669
670 void CYNumber::PropertyName(CYOutput &out) const {
671 Output(out, CYNoFlags);
672 }
673
674 void CYObject::Output(CYOutput &out, CYFlags flags) const {
675 bool protect((flags & CYNoBrace) != 0);
676 if (protect)
677 out << '(';
678 out << '{' << '\n';
679 ++out.indent_;
680 out << properties_;
681 --out.indent_;
682 out << '\t' << '}';
683 if (protect)
684 out << ')';
685 }
686
687 void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
688 lhs_->Output(out, Precedence(), CYLeft(flags));
689 out << Operator();
690 }
691
692 void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
693 const char *name(Operator());
694 out << name;
695 if (Alphabetic())
696 out << ' ';
697 rhs_->Output(out, Precedence(), CYRight(flags));
698 }
699
700 void CYScript::Output(CYOutput &out) const {
701 out << code_;
702 }
703
704 void CYProperty::Output(CYOutput &out) const {
705 if (next_ != NULL || out.pretty_)
706 out << ',';
707 out << '\n' << next_;
708 }
709
710 void CYPropertyGetter::Output(CYOutput &out) const {
711 out << "get" << ' ';
712 name_->PropertyName(out);
713 CYFunction::Output(out);
714 CYProperty::Output(out);
715 }
716
717 void CYPropertyMethod::Output(CYOutput &out) const {
718 name_->PropertyName(out);
719 CYFunction::Output(out);
720 CYProperty::Output(out);
721 }
722
723 void CYPropertySetter::Output(CYOutput &out) const {
724 out << "set" << ' ';
725 name_->PropertyName(out);
726 CYFunction::Output(out);
727 CYProperty::Output(out);
728 }
729
730 void CYPropertyValue::Output(CYOutput &out) const {
731 out << '\t';
732 name_->PropertyName(out);
733 out << ':' << ' ';
734 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
735 CYProperty::Output(out);
736 }
737
738 void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
739 out << Value();
740 }
741
742 void CYReturn::Output(CYOutput &out, CYFlags flags) const {
743 out << "return";
744 if (value_ != NULL)
745 out << ' ' << *value_;
746 out << ';';
747 }
748
749 void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
750 call_->Output(out, CYLeft(flags));
751 out << ' ';
752 proc_->Output(out, CYRight(flags));
753 }
754
755 void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
756 out << '{' << ' ' << '|' << parameters_ << '|' << '\n';
757 ++out.indent_;
758 out << code_;
759 --out.indent_;
760 out << '\t' << '}';
761 }
762
763 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
764 bool first(true);
765 CYForEach (next, this) {
766 bool last(next->next_ == NULL);
767 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
768 first = false;
769 out << '\t';
770 next->Output(out, jacks);
771 out << '\n';
772 }
773 }
774
775 void CYStatement::Single(CYOutput &out, CYFlags flags, CYCompactType request) const {
776 if (this == NULL)
777 return out.Terminate();
778
779 _assert(next_ == NULL);
780
781 CYCompactType compact(Compact());
782
783 if (compact >= request)
784 out << ' ';
785 else {
786 out << '\n';
787 ++out.indent_;
788 out << '\t';
789 }
790
791 Output(out, flags);
792
793 if (compact < request)
794 --out.indent_;
795 }
796
797 void CYString::Output(CYOutput &out, CYFlags flags) const {
798 std::ostringstream str;
799 CYStringify(str, value_, size_);
800 out << str.str().c_str();
801 }
802
803 void CYString::PropertyName(CYOutput &out) const {
804 if (const char *word = Word())
805 out << word;
806 else
807 out << *this;
808 }
809
810 static const char *Reserved_[] = {
811 "false", "null", "true",
812
813 "break", "case", "catch", "continue", "default",
814 "delete", "do", "else", "finally", "for", "function",
815 "if", "in", "instanceof", "new", "return", "switch",
816 "this", "throw", "try", "typeof", "var", "void",
817 "while", "with",
818
819 "debugger", "const",
820
821 "class", "enum", "export", "extends", "import", "super",
822
823 "abstract", "boolean", "byte", "char", "double", "final",
824 "float", "goto", "int", "long", "native", "short",
825 "synchronized", "throws", "transient", "volatile",
826
827 "let", "yield",
828
829 NULL
830 };
831
832 const char *CYString::Word() const {
833 if (size_ == 0 || !WordStartRange_[value_[0]])
834 return NULL;
835 for (size_t i(1); i != size_; ++i)
836 if (!WordEndRange_[value_[i]])
837 return NULL;
838 const char *value(Value());
839 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
840 if (strcmp(*reserved, value) == 0)
841 return NULL;
842 return value;
843 }
844
845 void CYSuperAccess::Output(CYOutput &out, CYFlags flags) const {
846 out << "super";
847 if (const char *word = property_->Word())
848 out << '.' << word;
849 else
850 out << '[' << *property_ << ']';
851 }
852
853 void CYSuperCall::Output(CYOutput &out, CYFlags flags) const {
854 out << "super" << '(' << arguments_ << ')';
855 }
856
857 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
858 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{' << '\n';
859 ++out.indent_;
860 out << clauses_;
861 --out.indent_;
862 out << '\t' << '}';
863 }
864
865 void CYThis::Output(CYOutput &out, CYFlags flags) const {
866 out << "this";
867 }
868
869 namespace cy {
870 namespace Syntax {
871
872 void Throw::Output(CYOutput &out, CYFlags flags) const {
873 out << "throw";
874 if (value_ != NULL)
875 out << ' ' << *value_;
876 out << ';';
877 }
878
879 void Try::Output(CYOutput &out, CYFlags flags) const {
880 out << "try" << ' ';
881 out << '{' << '\n';
882 ++out.indent_;
883 out << code_;
884 --out.indent_;
885 out << '\t' << '}';
886 out << catch_ << finally_;
887 }
888
889 } }
890
891 void CYTypeError::Output(CYOutput &out) const {
892 out << "@error";
893 }
894
895 void CYTypeLong::Output(CYOutput &out) const {
896 out << "long" << specifier_;
897 }
898
899 void CYTypeShort::Output(CYOutput &out) const {
900 out << "short" << specifier_;
901 }
902
903 void CYTypeSigned::Output(CYOutput &out) const {
904 out << "signed" << specifier_;
905 }
906
907 void CYTypeUnsigned::Output(CYOutput &out) const {
908 out << "unsigned" << specifier_;
909 }
910
911 void CYTypeVariable::Output(CYOutput &out) const {
912 out << *name_;
913 }
914
915 void CYTypeVoid::Output(CYOutput &out) const {
916 out << "void";
917 }
918
919 void CYVar::Output(CYOutput &out, CYFlags flags) const {
920 out << "var" << ' ';
921 declarations_->Output(out, flags);
922 out << ';';
923 }
924
925 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
926 out << *name_;
927 }
928
929 void CYWhile::Output(CYOutput &out, CYFlags flags) const {
930 out << "while" << ' ' << '(' << *test_ << ')';
931 code_->Single(out, CYRight(flags), CYCompactShort);
932 }
933
934 void CYWith::Output(CYOutput &out, CYFlags flags) const {
935 out << "with" << ' ' << '(' << *scope_ << ')';
936 code_->Single(out, CYRight(flags), CYCompactShort);
937 }
938
939 void CYWord::Output(CYOutput &out) const {
940 out << Word();
941 if (out.options_.verbose_) {
942 out('@');
943 char number[32];
944 sprintf(number, "%p", this);
945 out(number);
946 }
947 }
948
949 void CYWord::PropertyName(CYOutput &out) const {
950 Output(out);
951 }
952
953 const char *CYWord::Word() const {
954 return word_;
955 }