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