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