]> git.saurik.com Git - cycript.git/blob - Output.cpp
Avoid crashing when the user types a mismatched }.
[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" << ' ' << '(';
381 declaration_->Output(out, CYNoIn);
382 out << ' ' << "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" << ' ' << '(';
395 declaration_->Output(out, CYNoIn);
396 out << ' ' << "in" << ' ' << *set_ << ')';
397 }
398
399 void CYFunction::Output(CYOutput &out, CYFlags flags) const {
400 // XXX: one could imagine using + here to save a byte
401 bool protect((flags & CYNoFunction) != 0);
402 if (protect)
403 out << '(';
404 out << "function";
405 if (name_ != NULL)
406 out << ' ' << *name_;
407 out << '(' << parameters_ << ')' << ' ';
408 out << '{' << '\n';
409 ++out.indent_;
410 out << code_;
411 --out.indent_;
412 out << '\t' << '}';
413 if (protect)
414 out << ')';
415 }
416
417 void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
418 CYFunction::Output(out, flags);
419 }
420
421 void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
422 CYFunction::Output(out, flags);
423 }
424
425 void CYFunctionParameter::Output(CYOutput &out) const {
426 initialiser_->Output(out, CYNoFlags);
427 if (next_ != NULL)
428 out << ',' << ' ' << *next_;
429 }
430
431 const char *CYIdentifier::Word() const {
432 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
433 }
434
435 void CYIf::Output(CYOutput &out, CYFlags flags) const {
436 bool protect(false);
437 if (false_ == NULL && (flags & CYNoDangle) != 0) {
438 protect = true;
439 out << '{';
440 }
441
442 out << "if" << ' ' << '(' << *test_ << ')';
443
444 CYFlags right(protect ? CYNoFlags : CYRight(flags));
445
446 CYFlags jacks(CYNoDangle);
447 if (false_ == NULL)
448 jacks |= right;
449 else
450 jacks |= protect ? CYNoFlags : CYCenter(flags);
451
452 unsigned line(out.position_.line);
453 unsigned indent(out.indent_);
454 true_->Single(out, jacks, CYCompactShort);
455
456 if (false_ != NULL) {
457 if (out.position_.line != line && out.recent_ == indent)
458 out << ' ';
459 else
460 out << '\n' << '\t';
461
462 out << "else";
463 false_->Single(out, right, CYCompactLong);
464 }
465
466 if (protect)
467 out << '}';
468 }
469
470 void CYIfComprehension::Output(CYOutput &out) const {
471 out << "if" << ' ' << '(' << *test_ << ')' << next_;
472 }
473
474 void CYImport::Output(CYOutput &out, CYFlags flags) const {
475 out << "@import";
476 }
477
478 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
479 object_->Output(out, Precedence(), CYLeft(flags));
480 if (const char *word = property_->Word())
481 out << "->" << word;
482 else
483 out << "->" << '[' << *property_ << ']';
484 }
485
486 void CYInfix::Output(CYOutput &out, CYFlags flags) const {
487 const char *name(Operator());
488 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
489 if (protect)
490 out << '(';
491 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
492 lhs_->Output(out, Precedence(), left);
493 out << ' ' << name << ' ';
494 CYFlags right(protect ? CYNoFlags : CYRight(flags));
495 rhs_->Output(out, Precedence() - 1, right);
496 if (protect)
497 out << ')';
498 }
499
500 void CYLabel::Output(CYOutput &out, CYFlags flags) const {
501 out << *name_ << ':';
502 statement_->Single(out, CYRight(flags), CYCompactShort);
503 }
504
505 void CYParenthetical::Output(CYOutput &out, CYFlags flags) const {
506 out << '(';
507 expression_->Output(out, CYCompound::Precedence_, CYNoFlags);
508 out << ')';
509 }
510
511 void CYStatement::Output(CYOutput &out) const {
512 Multiple(out);
513 }
514
515 void CYTemplate::Output(CYOutput &out, CYFlags flags) const {
516 _assert(false);
517 }
518
519 void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
520 next_->Output(out, Precedence(), identifier);
521 out << '[';
522 out << size_;
523 out << ']';
524 }
525
526 void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
527 out << '(' << '^';
528 next_->Output(out, Precedence(), identifier);
529 out << ')' << '(' << parameters_ << ')';
530 }
531
532 void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
533 out << "const" << ' ';
534 next_->Output(out, Precedence(), identifier);
535 }
536
537 void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
538 next_->Output(out, Precedence(), identifier);
539 out << '(' << parameters_ << ')';
540 }
541
542 void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
543 out << '*';
544 next_->Output(out, Precedence(), identifier);
545 }
546
547 void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
548 out << "volatile";
549 next_->Output(out, Precedence(), identifier);
550 }
551
552 void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
553 if (this == NULL) {
554 out << identifier;
555 return;
556 }
557
558 bool protect(precedence > Precedence());
559
560 if (protect)
561 out << '(';
562 Output(out, identifier);
563 if (protect)
564 out << ')';
565 }
566
567 void CYTypedIdentifier::Output(CYOutput &out) const {
568 specifier_->Output(out);
569 modifier_->Output(out, 0, identifier_);
570 }
571
572 void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
573 out << "@encode(" << typed_ << ")";
574 }
575
576 void CYTypedParameter::Output(CYOutput &out) const {
577 out << typed_;
578 if (next_ != NULL)
579 out << ',' << ' ' << next_;
580 }
581
582 void CYLambda::Output(CYOutput &out, CYFlags flags) const {
583 // XXX: this is seriously wrong
584 out << "[](";
585 out << ")->";
586 out << "{";
587 out << "}";
588 }
589
590 void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
591 out << "typedef" << ' ' << *typed_;
592 }
593
594 void CYLetStatement::Output(CYOutput &out, CYFlags flags) const {
595 out << "let" << ' ' << '(' << *declarations_ << ')';
596 code_->Single(out, CYRight(flags), CYCompactShort);
597 }
598
599 void CYModule::Output(CYOutput &out) const {
600 out << part_;
601 if (next_ != NULL)
602 out << '.' << next_;
603 }
604
605 namespace cy {
606 namespace Syntax {
607
608 void New::Output(CYOutput &out, CYFlags flags) const {
609 out << "new" << ' ';
610 CYFlags jacks(CYNoCall | CYCenter(flags));
611 constructor_->Output(out, Precedence(), jacks);
612 if (arguments_ != NULL)
613 out << '(' << *arguments_ << ')';
614 }
615
616 } }
617
618 void CYNull::Output(CYOutput &out, CYFlags flags) const {
619 out << "null";
620 }
621
622 void CYNumber::Output(CYOutput &out, CYFlags flags) const {
623 std::ostringstream str;
624 CYNumerify(str, Value());
625 std::string value(str.str());
626 out << value.c_str();
627 // XXX: this should probably also handle hex conversions and exponents
628 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
629 out << '.';
630 }
631
632 void CYNumber::PropertyName(CYOutput &out) const {
633 Output(out, CYNoFlags);
634 }
635
636 void CYObject::Output(CYOutput &out, CYFlags flags) const {
637 bool protect((flags & CYNoBrace) != 0);
638 if (protect)
639 out << '(';
640 out << '{' << '\n';
641 ++out.indent_;
642 out << properties_;
643 --out.indent_;
644 out << '\t' << '}';
645 if (protect)
646 out << ')';
647 }
648
649 void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
650 lhs_->Output(out, Precedence(), CYLeft(flags));
651 out << Operator();
652 }
653
654 void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
655 const char *name(Operator());
656 out << name;
657 if (Alphabetic())
658 out << ' ';
659 rhs_->Output(out, Precedence(), CYRight(flags));
660 }
661
662 void CYScript::Output(CYOutput &out) const {
663 out << code_;
664 }
665
666 void CYProperty::Output(CYOutput &out) const {
667 out << '\t';
668 name_->PropertyName(out);
669 out << ':' << ' ';
670 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
671 if (next_ != NULL)
672 out << ',' << '\n' << *next_;
673 else
674 out << '\n';
675 }
676
677 void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
678 out << Value();
679 }
680
681 void CYReturn::Output(CYOutput &out, CYFlags flags) const {
682 out << "return";
683 if (value_ != NULL)
684 out << ' ' << *value_;
685 out << ';';
686 }
687
688 void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
689 call_->Output(out, CYLeft(flags));
690 out << ' ';
691 proc_->Output(out, CYRight(flags));
692 }
693
694 void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
695 out << '{' << ' ' << '|' << parameters_ << '|' << '\n';
696 ++out.indent_;
697 out << code_;
698 --out.indent_;
699 out << '\t' << '}';
700 }
701
702 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
703 bool first(true);
704 CYForEach (next, this) {
705 bool last(next->next_ == NULL);
706 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
707 first = false;
708 out << '\t';
709 next->Output(out, jacks);
710 out << '\n';
711 }
712 }
713
714 void CYStatement::Single(CYOutput &out, CYFlags flags, CYCompactType request) const {
715 if (this == NULL)
716 return out.Terminate();
717
718 _assert(next_ == NULL);
719
720 CYCompactType compact(Compact());
721
722 if (compact >= request)
723 out << ' ';
724 else {
725 out << '\n';
726 ++out.indent_;
727 out << '\t';
728 }
729
730 Output(out, flags);
731
732 if (compact < request)
733 --out.indent_;
734 }
735
736 void CYString::Output(CYOutput &out, CYFlags flags) const {
737 std::ostringstream str;
738 CYStringify(str, value_, size_);
739 out << str.str().c_str();
740 }
741
742 void CYString::PropertyName(CYOutput &out) const {
743 if (const char *word = Word())
744 out << word;
745 else
746 out << *this;
747 }
748
749 static const char *Reserved_[] = {
750 "false", "null", "true",
751
752 "break", "case", "catch", "continue", "default",
753 "delete", "do", "else", "finally", "for", "function",
754 "if", "in", "instanceof", "new", "return", "switch",
755 "this", "throw", "try", "typeof", "var", "void",
756 "while", "with",
757
758 "debugger", "const",
759
760 "class", "enum", "export", "extends", "import", "super",
761
762 "abstract", "boolean", "byte", "char", "double", "final",
763 "float", "goto", "int", "long", "native", "short",
764 "synchronized", "throws", "transient", "volatile",
765
766 "let", "yield",
767
768 NULL
769 };
770
771 const char *CYString::Word() const {
772 if (size_ == 0 || !WordStartRange_[value_[0]])
773 return NULL;
774 for (size_t i(1); i != size_; ++i)
775 if (!WordEndRange_[value_[i]])
776 return NULL;
777 const char *value(Value());
778 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
779 if (strcmp(*reserved, value) == 0)
780 return NULL;
781 return value;
782 }
783
784 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
785 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{' << '\n';
786 ++out.indent_;
787 out << clauses_;
788 --out.indent_;
789 out << '\t' << '}';
790 }
791
792 void CYThis::Output(CYOutput &out, CYFlags flags) const {
793 out << "this";
794 }
795
796 namespace cy {
797 namespace Syntax {
798
799 void Throw::Output(CYOutput &out, CYFlags flags) const {
800 out << "throw";
801 if (value_ != NULL)
802 out << ' ' << *value_;
803 out << ';';
804 }
805
806 void Try::Output(CYOutput &out, CYFlags flags) const {
807 out << "try" << ' ';
808 out << '{' << '\n';
809 ++out.indent_;
810 out << code_;
811 --out.indent_;
812 out << '\t' << '}';
813 out << catch_ << finally_;
814 }
815
816 } }
817
818 void CYTypeError::Output(CYOutput &out) const {
819 out << "@error";
820 }
821
822 void CYTypeLong::Output(CYOutput &out) const {
823 out << "long" << specifier_;
824 }
825
826 void CYTypeShort::Output(CYOutput &out) const {
827 out << "short" << specifier_;
828 }
829
830 void CYTypeSigned::Output(CYOutput &out) const {
831 out << "signed" << specifier_;
832 }
833
834 void CYTypeUnsigned::Output(CYOutput &out) const {
835 out << "unsigned" << specifier_;
836 }
837
838 void CYTypeVariable::Output(CYOutput &out) const {
839 out << *name_;
840 }
841
842 void CYTypeVoid::Output(CYOutput &out) const {
843 out << "void";
844 }
845
846 void CYVar::Output(CYOutput &out, CYFlags flags) const {
847 out << "var" << ' ';
848 declarations_->Output(out, flags);
849 out << ';';
850 }
851
852 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
853 out << *name_;
854 }
855
856 void CYWhile::Output(CYOutput &out, CYFlags flags) const {
857 out << "while" << ' ' << '(' << *test_ << ')';
858 code_->Single(out, CYRight(flags), CYCompactShort);
859 }
860
861 void CYWith::Output(CYOutput &out, CYFlags flags) const {
862 out << "with" << ' ' << '(' << *scope_ << ')';
863 code_->Single(out, CYRight(flags), CYCompactShort);
864 }
865
866 void CYWord::ClassName(CYOutput &out, bool object) const {
867 if (object)
868 out << "objc_getClass(";
869 out << '"' << Word() << '"';
870 if (object)
871 out << ')';
872 }
873
874 void CYWord::Output(CYOutput &out) const {
875 out << Word();
876 if (out.options_.verbose_) {
877 out('@');
878 char number[32];
879 sprintf(number, "%p", this);
880 out(number);
881 }
882 }
883
884 void CYWord::PropertyName(CYOutput &out) const {
885 Output(out);
886 }
887
888 const char *CYWord::Word() const {
889 return word_;
890 }