]> git.saurik.com Git - cycript.git/blob - Output.cpp
Catch errors during replace and output to console.
[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::Output(CYOutput &out, CYFlags flags) const {
272 out << *identifier_;
273 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
274 if (initialiser_ != NULL) {
275 out << ' ' << '=' << ' ';
276 initialiser_->Output(out, CYAssign::Precedence_, CYRight(flags));
277 }
278 }
279
280 void CYDeclarations::Output(CYOutput &out) const {
281 Output(out, CYNoFlags);
282 }
283
284 void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
285 const CYDeclarations *declaration(this);
286 bool first(true);
287
288 for (;;) {
289 CYDeclarations *next(declaration->next_);
290
291 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
292 first = false;
293 declaration->declaration_->Output(out, jacks);
294
295 if (next == NULL)
296 break;
297
298 out << ',' << ' ';
299 declaration = next;
300 }
301 }
302
303 void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
304 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
305 if (const char *word = property_->Word())
306 out << '.' << word;
307 else
308 out << '[' << *property_ << ']';
309 }
310
311 void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
312 out << "do";
313
314 unsigned line(out.position_.line);
315 unsigned indent(out.indent_);
316 code_->Single(out, CYCenter(flags), CYCompactLong);
317
318 if (out.position_.line != line && out.recent_ == indent)
319 out << ' ';
320 else
321 out << '\n' << '\t';
322
323 out << "while" << ' ' << '(' << *test_ << ')';
324 }
325
326 void CYElementSpread::Output(CYOutput &out) const {
327 out << "..." << value_;
328 }
329
330 void CYElementValue::Output(CYOutput &out) const {
331 if (value_ != NULL)
332 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
333 if (next_ != NULL || value_ == NULL) {
334 out << ',';
335 if (next_ != NULL && !next_->Elision())
336 out << ' ';
337 }
338 if (next_ != NULL)
339 next_->Output(out);
340 }
341
342 void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
343 out.Terminate();
344 }
345
346 void CYEval::Output(CYOutput &out, CYFlags flags) const {
347 _assert(false);
348 }
349
350 void CYExpress::Output(CYOutput &out, CYFlags flags) const {
351 expression_->Output(out, flags | CYNoBFC);
352 out << ';';
353 }
354
355 void CYExpression::Output(CYOutput &out) const {
356 Output(out, CYNoFlags);
357 }
358
359 void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const {
360 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
361 out << '(' << *this << ')';
362 else
363 Output(out, flags);
364 }
365
366 void CYExternal::Output(CYOutput &out, CYFlags flags) const {
367 out << "extern" << abi_ << typed_ << ';';
368 }
369
370 void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
371 out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << '{' << code_ << '}';
372 }
373
374 void CYFinally::Output(CYOutput &out) const {
375 out << ' ' << "finally" << ' ';
376 out << '{' << '\n';
377 ++out.indent_;
378 out << code_;
379 --out.indent_;
380 out << '\t' << '}';
381 }
382
383 void CYFor::Output(CYOutput &out, CYFlags flags) const {
384 out << "for" << ' ' << '(';
385 if (initialiser_ != NULL)
386 initialiser_->Output(out, CYNoIn);
387 out.Terminate();
388 if (test_ != NULL)
389 out << ' ';
390 out << test_;
391 out.Terminate();
392 if (increment_ != NULL)
393 out << ' ';
394 out << increment_;
395 out << ')';
396 code_->Single(out, CYRight(flags), CYCompactShort);
397 }
398
399 void CYForDeclarations::Output(CYOutput &out, CYFlags flags) const {
400 out << "var" << ' ';
401 declarations_->Output(out, CYRight(flags));
402 }
403
404 void CYForLexical::Output(CYOutput &out, CYFlags flags) const {
405 out << (constant_ ? "const" : "let") << ' ';
406 declaration_->Output(out, CYRight(flags));
407 }
408
409 void CYForIn::Output(CYOutput &out, CYFlags flags) const {
410 out << "for" << ' ' << '(';
411 initialiser_->Output(out, CYNoIn | CYNoRightHand);
412 out << ' ' << "in" << ' ' << *set_ << ')';
413 code_->Single(out, CYRight(flags), CYCompactShort);
414 }
415
416 void CYForInComprehension::Output(CYOutput &out) const {
417 out << "for" << ' ' << '(';
418 declaration_->Output(out, CYNoIn | CYNoRightHand);
419 out << ' ' << "in" << ' ' << *set_ << ')';
420 }
421
422 void CYForOf::Output(CYOutput &out, CYFlags flags) const {
423 out << "for" << ' ' << '(';
424 initialiser_->Output(out, CYNoRightHand);
425 out << ' ' << "of" << ' ' << *set_ << ')';
426 code_->Single(out, CYRight(flags), CYCompactShort);
427 }
428
429 void CYForOfComprehension::Output(CYOutput &out) const {
430 out << "for" << ' ' << '(';
431 declaration_->Output(out, CYNoRightHand);
432 out << ' ' << "of" << ' ' << *set_ << ')' << next_;
433 }
434
435 void CYForVariable::Output(CYOutput &out, CYFlags flags) const {
436 out << "var" << ' ';
437 declaration_->Output(out, CYRight(flags));
438 }
439
440 void CYFunction::Output(CYOutput &out) const {
441 out << '(' << parameters_ << ')' << ' ';
442 out << '{' << '\n';
443 ++out.indent_;
444 out << code_;
445 --out.indent_;
446 out << '\t' << '}';
447 }
448
449 void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
450 // XXX: one could imagine using + here to save a byte
451 bool protect((flags & CYNoFunction) != 0);
452 if (protect)
453 out << '(';
454 out << "function";
455 if (name_ != NULL)
456 out << ' ' << *name_;
457 CYFunction::Output(out);
458 if (protect)
459 out << ')';
460 }
461
462 void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
463 out << "function" << ' ' << *name_;
464 CYFunction::Output(out);
465 }
466
467 void CYFunctionParameter::Output(CYOutput &out) const {
468 initialiser_->Output(out, CYNoFlags);
469 if (next_ != NULL)
470 out << ',' << ' ' << *next_;
471 }
472
473 const char *CYIdentifier::Word() const {
474 return next_ == NULL || next_ == this ? CYWord::Word() : next_->Word();
475 }
476
477 void CYIf::Output(CYOutput &out, CYFlags flags) const {
478 bool protect(false);
479 if (false_ == NULL && (flags & CYNoDangle) != 0) {
480 protect = true;
481 out << '{';
482 }
483
484 out << "if" << ' ' << '(' << *test_ << ')';
485
486 CYFlags right(protect ? CYNoFlags : CYRight(flags));
487
488 CYFlags jacks(CYNoDangle);
489 if (false_ == NULL)
490 jacks |= right;
491 else
492 jacks |= protect ? CYNoFlags : CYCenter(flags);
493
494 unsigned line(out.position_.line);
495 unsigned indent(out.indent_);
496 true_->Single(out, jacks, CYCompactShort);
497
498 if (false_ != NULL) {
499 if (out.position_.line != line && out.recent_ == indent)
500 out << ' ';
501 else
502 out << '\n' << '\t';
503
504 out << "else";
505 false_->Single(out, right, CYCompactLong);
506 }
507
508 if (protect)
509 out << '}';
510 }
511
512 void CYIfComprehension::Output(CYOutput &out) const {
513 out << "if" << ' ' << '(' << *test_ << ')' << next_;
514 }
515
516 void CYImport::Output(CYOutput &out, CYFlags flags) const {
517 out << "@import";
518 }
519
520 void CYIndirect::Output(CYOutput &out, CYFlags flags) const {
521 out << "*";
522 rhs_->Output(out, Precedence(), CYRight(flags));
523 }
524
525 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
526 object_->Output(out, Precedence(), CYLeft(flags));
527 if (const char *word = property_->Word())
528 out << "->" << word;
529 else
530 out << "->" << '[' << *property_ << ']';
531 }
532
533 void CYInfix::Output(CYOutput &out, CYFlags flags) const {
534 const char *name(Operator());
535 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
536 if (protect)
537 out << '(';
538 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
539 lhs_->Output(out, Precedence(), left);
540 out << ' ' << name << ' ';
541 CYFlags right(protect ? CYNoFlags : CYRight(flags));
542 rhs_->Output(out, Precedence() - 1, right);
543 if (protect)
544 out << ')';
545 }
546
547 void CYLabel::Output(CYOutput &out, CYFlags flags) const {
548 out << *name_ << ':';
549 statement_->Single(out, CYRight(flags), CYCompactShort);
550 }
551
552 void CYParenthetical::Output(CYOutput &out, CYFlags flags) const {
553 out << '(';
554 expression_->Output(out, CYCompound::Precedence_, CYNoFlags);
555 out << ')';
556 }
557
558 void CYStatement::Output(CYOutput &out) const {
559 Multiple(out);
560 }
561
562 void CYTemplate::Output(CYOutput &out, CYFlags flags) const {
563 _assert(false);
564 }
565
566 void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
567 next_->Output(out, Precedence(), identifier);
568 out << '[';
569 out << size_;
570 out << ']';
571 }
572
573 void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
574 out << '(' << '^';
575 next_->Output(out, Precedence(), identifier);
576 out << ')' << '(' << parameters_ << ')';
577 }
578
579 void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
580 out << "const" << ' ';
581 next_->Output(out, Precedence(), identifier);
582 }
583
584 void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
585 next_->Output(out, Precedence(), identifier);
586 out << '(' << parameters_ << ')';
587 }
588
589 void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
590 out << '*';
591 next_->Output(out, Precedence(), identifier);
592 }
593
594 void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
595 out << "volatile";
596 next_->Output(out, Precedence(), identifier);
597 }
598
599 void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
600 if (this == NULL) {
601 out << identifier;
602 return;
603 }
604
605 bool protect(precedence > Precedence());
606
607 if (protect)
608 out << '(';
609 Output(out, identifier);
610 if (protect)
611 out << ')';
612 }
613
614 void CYTypedIdentifier::Output(CYOutput &out) const {
615 specifier_->Output(out);
616 modifier_->Output(out, 0, identifier_);
617 }
618
619 void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
620 out << "@encode(" << typed_ << ")";
621 }
622
623 void CYTypedParameter::Output(CYOutput &out) const {
624 out << typed_;
625 if (next_ != NULL)
626 out << ',' << ' ' << next_;
627 }
628
629 void CYLambda::Output(CYOutput &out, CYFlags flags) const {
630 // XXX: this is seriously wrong
631 out << "[](";
632 out << ")->";
633 out << "{";
634 out << "}";
635 }
636
637 void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
638 out << "typedef" << ' ' << *typed_;
639 }
640
641 void CYLet::Output(CYOutput &out, CYFlags flags) const {
642 out << "let" << ' ';
643 declarations_->Output(out, flags); // XXX: flags
644 out << ';';
645 }
646
647 void CYModule::Output(CYOutput &out) const {
648 out << part_;
649 if (next_ != NULL)
650 out << '.' << next_;
651 }
652
653 namespace cy {
654 namespace Syntax {
655
656 void New::Output(CYOutput &out, CYFlags flags) const {
657 out << "new" << ' ';
658 CYFlags jacks(CYNoCall | CYCenter(flags));
659 constructor_->Output(out, Precedence(), jacks);
660 if (arguments_ != NULL)
661 out << '(' << *arguments_ << ')';
662 }
663
664 } }
665
666 void CYNull::Output(CYOutput &out, CYFlags flags) const {
667 out << "null";
668 }
669
670 void CYNumber::Output(CYOutput &out, CYFlags flags) const {
671 std::ostringstream str;
672 CYNumerify(str, Value());
673 std::string value(str.str());
674 out << value.c_str();
675 // XXX: this should probably also handle hex conversions and exponents
676 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
677 out << '.';
678 }
679
680 void CYNumber::PropertyName(CYOutput &out) const {
681 Output(out, CYNoFlags);
682 }
683
684 void CYObject::Output(CYOutput &out, CYFlags flags) const {
685 bool protect((flags & CYNoBrace) != 0);
686 if (protect)
687 out << '(';
688 out << '{' << '\n';
689 ++out.indent_;
690 out << properties_;
691 --out.indent_;
692 out << '\t' << '}';
693 if (protect)
694 out << ')';
695 }
696
697 void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
698 lhs_->Output(out, Precedence(), CYLeft(flags));
699 out << Operator();
700 }
701
702 void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
703 const char *name(Operator());
704 out << name;
705 if (Alphabetic())
706 out << ' ';
707 rhs_->Output(out, Precedence(), CYRight(flags));
708 }
709
710 void CYScript::Output(CYOutput &out) const {
711 out << code_;
712 }
713
714 void CYProperty::Output(CYOutput &out) const {
715 if (next_ != NULL || out.pretty_)
716 out << ',';
717 out << '\n' << next_;
718 }
719
720 void CYPropertyGetter::Output(CYOutput &out) const {
721 out << "get" << ' ';
722 name_->PropertyName(out);
723 CYFunction::Output(out);
724 CYProperty::Output(out);
725 }
726
727 void CYPropertyMethod::Output(CYOutput &out) const {
728 name_->PropertyName(out);
729 CYFunction::Output(out);
730 CYProperty::Output(out);
731 }
732
733 void CYPropertySetter::Output(CYOutput &out) const {
734 out << "set" << ' ';
735 name_->PropertyName(out);
736 CYFunction::Output(out);
737 CYProperty::Output(out);
738 }
739
740 void CYPropertyValue::Output(CYOutput &out) const {
741 out << '\t';
742 name_->PropertyName(out);
743 out << ':' << ' ';
744 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
745 CYProperty::Output(out);
746 }
747
748 void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
749 out << Value();
750 }
751
752 void CYReturn::Output(CYOutput &out, CYFlags flags) const {
753 out << "return";
754 if (value_ != NULL)
755 out << ' ' << *value_;
756 out << ';';
757 }
758
759 void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
760 call_->Output(out, CYLeft(flags));
761 out << ' ';
762 proc_->Output(out, CYRight(flags));
763 }
764
765 void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
766 out << '{' << ' ' << '|' << parameters_ << '|' << '\n';
767 ++out.indent_;
768 out << code_;
769 --out.indent_;
770 out << '\t' << '}';
771 }
772
773 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
774 bool first(true);
775 CYForEach (next, this) {
776 bool last(next->next_ == NULL);
777 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
778 first = false;
779 out << '\t';
780 next->Output(out, jacks);
781 out << '\n';
782 }
783 }
784
785 void CYStatement::Single(CYOutput &out, CYFlags flags, CYCompactType request) const {
786 if (this == NULL)
787 return out.Terminate();
788
789 _assert(next_ == NULL);
790
791 CYCompactType compact(Compact());
792
793 if (compact >= request)
794 out << ' ';
795 else {
796 out << '\n';
797 ++out.indent_;
798 out << '\t';
799 }
800
801 Output(out, flags);
802
803 if (compact < request)
804 --out.indent_;
805 }
806
807 void CYString::Output(CYOutput &out, CYFlags flags) const {
808 std::ostringstream str;
809 CYStringify(str, value_, size_);
810 out << str.str().c_str();
811 }
812
813 void CYString::PropertyName(CYOutput &out) const {
814 if (const char *word = Word())
815 out << word;
816 else
817 out << *this;
818 }
819
820 static const char *Reserved_[] = {
821 "false", "null", "true",
822
823 "break", "case", "catch", "continue", "default",
824 "delete", "do", "else", "finally", "for", "function",
825 "if", "in", "instanceof", "new", "return", "switch",
826 "this", "throw", "try", "typeof", "var", "void",
827 "while", "with",
828
829 "debugger", "const",
830
831 "class", "enum", "export", "extends", "import", "super",
832
833 "abstract", "boolean", "byte", "char", "double", "final",
834 "float", "goto", "int", "long", "native", "short",
835 "synchronized", "throws", "transient", "volatile",
836
837 "let", "yield",
838
839 NULL
840 };
841
842 const char *CYString::Word() const {
843 if (size_ == 0 || !WordStartRange_[value_[0]])
844 return NULL;
845 for (size_t i(1); i != size_; ++i)
846 if (!WordEndRange_[value_[i]])
847 return NULL;
848 const char *value(Value());
849 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
850 if (strcmp(*reserved, value) == 0)
851 return NULL;
852 return value;
853 }
854
855 void CYSuperAccess::Output(CYOutput &out, CYFlags flags) const {
856 out << "super";
857 if (const char *word = property_->Word())
858 out << '.' << word;
859 else
860 out << '[' << *property_ << ']';
861 }
862
863 void CYSuperCall::Output(CYOutput &out, CYFlags flags) const {
864 out << "super" << '(' << arguments_ << ')';
865 }
866
867 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
868 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{' << '\n';
869 ++out.indent_;
870 out << clauses_;
871 --out.indent_;
872 out << '\t' << '}';
873 }
874
875 void CYThis::Output(CYOutput &out, CYFlags flags) const {
876 out << "this";
877 }
878
879 namespace cy {
880 namespace Syntax {
881
882 void Throw::Output(CYOutput &out, CYFlags flags) const {
883 out << "throw";
884 if (value_ != NULL)
885 out << ' ' << *value_;
886 out << ';';
887 }
888
889 void Try::Output(CYOutput &out, CYFlags flags) const {
890 out << "try" << ' ';
891 out << '{' << '\n';
892 ++out.indent_;
893 out << code_;
894 --out.indent_;
895 out << '\t' << '}';
896 out << catch_ << finally_;
897 }
898
899 } }
900
901 void CYTypeError::Output(CYOutput &out) const {
902 out << "@error";
903 }
904
905 void CYTypeLong::Output(CYOutput &out) const {
906 out << "long" << specifier_;
907 }
908
909 void CYTypeShort::Output(CYOutput &out) const {
910 out << "short" << specifier_;
911 }
912
913 void CYTypeSigned::Output(CYOutput &out) const {
914 out << "signed" << specifier_;
915 }
916
917 void CYTypeUnsigned::Output(CYOutput &out) const {
918 out << "unsigned" << specifier_;
919 }
920
921 void CYTypeVariable::Output(CYOutput &out) const {
922 out << *name_;
923 }
924
925 void CYTypeVoid::Output(CYOutput &out) const {
926 out << "void";
927 }
928
929 void CYVar::Output(CYOutput &out, CYFlags flags) const {
930 out << "var" << ' ';
931 declarations_->Output(out, flags); // XXX: flags
932 out << ';';
933 }
934
935 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
936 out << *name_;
937 }
938
939 void CYWhile::Output(CYOutput &out, CYFlags flags) const {
940 out << "while" << ' ' << '(' << *test_ << ')';
941 code_->Single(out, CYRight(flags), CYCompactShort);
942 }
943
944 void CYWith::Output(CYOutput &out, CYFlags flags) const {
945 out << "with" << ' ' << '(' << *scope_ << ')';
946 code_->Single(out, CYRight(flags), CYCompactShort);
947 }
948
949 void CYWord::Output(CYOutput &out) const {
950 out << Word();
951 if (out.options_.verbose_) {
952 out('@');
953 char number[32];
954 sprintf(number, "%p", this);
955 out(number);
956 }
957 }
958
959 void CYWord::PropertyName(CYOutput &out) const {
960 Output(out);
961 }
962
963 const char *CYWord::Word() const {
964 return word_;
965 }