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