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