]> git.saurik.com Git - cycript.git/blob - Output.cpp
f648a575d35a55fea68369205210a189b20921d7
[cycript.git] / Output.cpp
1 #include "Parser.hpp"
2
3 #include <iostream>
4 #include <iomanip>
5
6 #include <objc/runtime.h>
7 #include <sstream>
8
9 _finline CYFlags operator ~(CYFlags rhs) {
10 return static_cast<CYFlags>(~static_cast<unsigned>(rhs));
11 }
12
13 _finline CYFlags operator &(CYFlags lhs, CYFlags rhs) {
14 return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs));
15 }
16
17 _finline CYFlags operator |(CYFlags lhs, CYFlags rhs) {
18 return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs));
19 }
20
21 _finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) {
22 return lhs = lhs | rhs;
23 }
24
25 _finline CYFlags CYLeft(CYFlags flags) {
26 return flags;
27 }
28
29 _finline CYFlags CYRight(CYFlags flags) {
30 return flags & ~CYNoBF;
31 }
32
33 _finline CYFlags CYCenter(CYFlags flags) {
34 return CYRight(flags);
35 }
36
37 #define CYPA 16
38
39 void CYOutput::Terminate() {
40 out_ << ';';
41 mode_ = NoMode;
42 }
43
44 CYOutput &CYOutput::operator <<(char rhs) {
45 if (rhs == ' ' || rhs == '\n')
46 if (pretty_)
47 out_ << rhs;
48 else goto done;
49 else if (rhs == '\t')
50 if (pretty_)
51 for (unsigned i(0); i != indent_; ++i)
52 out_ << " ";
53 else goto done;
54 else goto work;
55
56 mode_ = NoMode;
57 goto done;
58
59 work:
60 if (mode_ == Terminated && rhs != '}')
61 out_ << ';';
62
63 if (rhs == ';') {
64 if (pretty_)
65 goto none;
66 else {
67 mode_ = Terminated;
68 goto done;
69 }
70 } else if (rhs == '-') {
71 if (mode_ == NoHyphen)
72 out_ << ' ';
73 mode_ = NoHyphen;
74 } else if (WordEndRange_[rhs]) {
75 if (mode_ == NoLetter)
76 out_ << ' ';
77 mode_ = NoLetter;
78 } else none:
79 mode_ = NoMode;
80
81 out_ << rhs;
82 done:
83 return *this;
84 }
85
86 CYOutput &CYOutput::operator <<(const char *rhs) {
87 size_t size(strlen(rhs));
88
89 if (size == 1)
90 return *this << *rhs;
91
92 if (mode_ == Terminated)
93 out_ << ';';
94 else if (
95 mode_ == NoHyphen && *rhs == '-' ||
96 mode_ == NoLetter && WordEndRange_[*rhs]
97 )
98 out_ << ' ';
99
100 if (WordEndRange_[rhs[size - 1]])
101 mode_ = NoLetter;
102 else
103 mode_ = NoMode;
104
105 out_ << rhs;
106 return *this;
107 }
108
109 void OutputBody(CYOutput &out, CYStatement *body) {
110 out << ' ' << '{' << '\n';
111 ++out.indent_;
112 if (body != NULL)
113 body->Multiple(out);
114 --out.indent_;
115 out << '\t' << '}';
116 }
117
118 void CYAddressOf::Output(CYOutput &out, CYFlags flags) const {
119 rhs_->Output(out, 1, CYLeft(flags));
120 out << ".$cya()";
121 }
122
123 void CYArgument::Output(CYOutput &out) const {
124 if (name_ != NULL) {
125 out << *name_;
126 if (value_ != NULL)
127 out << ':' << ' ';
128 }
129 if (value_ != NULL)
130 value_->Output(out, CYPA, CYNoFlags);
131 if (next_ != NULL) {
132 if (next_->name_ == NULL)
133 out << ',';
134 out << ' ' << *next_;
135 }
136 }
137
138 void CYArray::Output(CYOutput &out, CYFlags flags) const {
139 out << '[' << elements_ << ']';
140 }
141
142 void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
143 // XXX: I don't necc. need the ()s
144 out << "(function($cyv";
145 for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
146 if (const char *name = comprehension->Name())
147 out << ',' << name;
148 out << "){";
149 out << "$cyv=[];";
150 comprehensions_->Output(out);
151 out << "$cyv.push(";
152 expression_->Output(out, CYPA, CYNoFlags);
153 out << ");";
154 for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_)
155 comprehension->End_(out);
156 out << "return $cyv;";
157 out << "}())";
158 }
159
160 void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
161 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
162 out << ' ' << Operator() << ' ';
163 rhs_->Output(out, Precedence(), CYRight(flags));
164 }
165
166 void CYBlock::Output(CYOutput &out, CYFlags flags) const {
167 statements_->Single(out, flags);
168 }
169
170 void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
171 out << (Value() ? "true" : "false");
172 }
173
174 void CYBreak::Output(CYOutput &out, CYFlags flags) const {
175 out << "break";
176 if (label_ != NULL)
177 out << ' ' << *label_;
178 out << ';';
179 }
180
181 void CYCall::Output(CYOutput &out, CYFlags flags) const {
182 bool protect((flags & CYNoCall) != 0);
183 if (protect)
184 out << '(';
185 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
186 out << '(' << arguments_ << ')';
187 if (protect)
188 out << ')';
189 }
190
191 void CYCatch::Output(CYOutput &out) const {
192 out << "catch" << ' ' << '(' << *name_ << ')' << ' ' << '{';
193 if (code_ != NULL)
194 code_->Multiple(out);
195 out << '}';
196 }
197
198 void CYCategory::Output(CYOutput &out, CYFlags flags) const {
199 out << "(function($cys,$cyp,$cyc,$cyn,$cyt){";
200 out << "$cyp=object_getClass($cys);";
201 out << "$cyc=$cys;";
202 if (messages_ != NULL)
203 messages_->Output(out, true);
204 out << "})(";
205 name_->ClassName(out, true);
206 out << ')';
207 out << ';';
208 }
209
210 void CYClass::Output(CYOutput &out, CYFlags flags) const {
211 // XXX: I don't necc. need the ()s
212 out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){";
213 out << "$cyp=object_getClass($cys);";
214 out << "$cyc=objc_allocateClassPair($cys,";
215 if (name_ != NULL)
216 name_->ClassName(out, false);
217 else
218 out << "$cyq(\"CY$\")";
219 out << ",0);";
220 out << "$cym=object_getClass($cyc);";
221 if (fields_ != NULL)
222 fields_->Output(out);
223 if (messages_ != NULL)
224 messages_->Output(out, false);
225 out << "objc_registerClassPair($cyc);";
226 out << "return $cyc;";
227 out << "}(";
228 if (super_ != NULL)
229 super_->Output(out, CYPA, CYNoFlags);
230 else
231 out << "null";
232 out << "))";
233 }
234
235 void CYClassExpression::Output(CYOutput &out, CYFlags flags) const {
236 CYClass::Output(out, flags);
237 }
238
239 void CYClassStatement::Output(CYOutput &out, CYFlags flags) const {
240 CYClass::Output(out, flags);
241 }
242
243 void CYCompound::Output(CYOutput &out, CYFlags flags) const {
244 if (CYExpression *expression = expressions_)
245 if (CYExpression *next = expression->next_) {
246 expression->Output(out, CYLeft(flags));
247 CYFlags center(CYCenter(flags));
248 while (next != NULL) {
249 expression = next;
250 out << ',' << ' ';
251 next = expression->next_;
252 CYFlags right(next != NULL ? center : CYRight(flags));
253 expression->Output(out, right);
254 }
255 } else
256 expression->Output(out, flags);
257 }
258
259 void CYComprehension::Output(CYOutput &out) const {
260 Begin_(out);
261 out << next_;
262 }
263
264 void CYCondition::Output(CYOutput &out, CYFlags flags) const {
265 test_->Output(out, Precedence() - 1, CYLeft(flags));
266 out << ' ' << '?' << ' ';
267 if (true_ != NULL)
268 true_->Output(out, CYPA, CYNoFlags);
269 out << ' ' << ':' << ' ';
270 false_->Output(out, CYPA, CYRight(flags));
271 }
272
273 void CYContinue::Output(CYOutput &out, CYFlags flags) const {
274 out << "continue";
275 if (label_ != NULL)
276 out << ' ' << *label_;
277 out << ';';
278 }
279
280 void CYClause::Output(CYOutput &out) const {
281 if (case_ != NULL)
282 out << "case" << ' ' << *case_;
283 else
284 out << "default";
285 out << ':' << '\n';
286 if (code_ != NULL)
287 code_->Multiple(out, CYNoFlags);
288 out << next_;
289 }
290
291 const char *CYDeclaration::ForEachIn() const {
292 return identifier_->Value();
293 }
294
295 void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
296 out << "var";
297 Output(out, CYRight(flags));
298 }
299
300 void CYDeclaration::ForEachIn(CYOutput &out) const {
301 out << *identifier_;
302 }
303
304 void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
305 out << *identifier_;
306 if (initialiser_ != NULL) {
307 out << ' ' << '=' << ' ';
308 initialiser_->Output(out, CYPA, CYRight(flags));
309 }
310 }
311
312 void CYDeclarations::For(CYOutput &out) const {
313 out << "var";
314 Output(out, CYNoIn);
315 }
316
317 void CYDeclarations::Output(CYOutput &out) const {
318 Output(out, CYNoFlags);
319 }
320
321 void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
322 const CYDeclarations *declaration(this);
323 bool first(true);
324 output:
325 CYDeclarations *next(declaration->next_);
326 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
327 first = false;
328 declaration->declaration_->Output(out, jacks);
329
330 if (next != NULL) {
331 out << ',' << ' ';
332 declaration = next;
333 goto output;
334 }
335 }
336
337 void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
338 object_->Output(out, Precedence(), CYLeft(flags));
339 if (const char *word = property_->Word())
340 out << '.' << word;
341 else
342 out << '[' << *property_ << ']';
343 }
344
345 void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
346 out << "do";
347 code_->Single(out, CYNoFlags);
348 out << "while" << ' ' << '(' << *test_ << ')';
349 }
350
351 void CYElement::Output(CYOutput &out) const {
352 if (value_ != NULL)
353 value_->Output(out, CYPA, CYNoFlags);
354 if (next_ != NULL || value_ == NULL) {
355 out << ',';
356 if (next_ != NULL && next_->value_ != NULL)
357 out << ' ';
358 }
359 if (next_ != NULL)
360 next_->Output(out);
361 }
362
363 void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
364 out.Terminate();
365 }
366
367 void CYExpress::Output(CYOutput &out, CYFlags flags) const {
368 expression_->Output(out, flags | CYNoBF);
369 out << ';';
370 }
371
372 void CYExpression::ClassName(CYOutput &out, bool object) const {
373 Output(out, CYPA, CYNoFlags);
374 }
375
376 const char *CYExpression::ForEachIn() const {
377 return NULL;
378 }
379
380 void CYExpression::For(CYOutput &out) const {
381 Output(out, CYNoIn);
382 }
383
384 void CYExpression::ForEachIn(CYOutput &out) const {
385 Output(out, CYPA, CYNoRightHand);
386 }
387
388 void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
389 Output(out, flags | CYNoRightHand);
390 }
391
392 void CYExpression::Output(CYOutput &out) const {
393 Output(out, CYNoFlags);
394 }
395
396 void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const {
397 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
398 out << '(' << *this << ')';
399 else
400 Output(out, flags);
401 }
402
403 void CYField::Output(CYOutput &out) const {
404 // XXX: implement!
405 }
406
407 void CYFinally::Output(CYOutput &out) const {
408 out << "finally" << ' ' << '{';
409 if (code_ != NULL)
410 code_->Multiple(out);
411 out << '}';
412 }
413
414 void CYFor::Output(CYOutput &out, CYFlags flags) const {
415 out << "for" << ' ' << '(';
416 if (initialiser_ != NULL)
417 initialiser_->For(out);
418 out.Terminate();
419 out << test_;
420 out.Terminate();
421 out << increment_;
422 out << ')';
423 code_->Single(out, CYNoFlags);
424 }
425
426 void CYForEachIn::Output(CYOutput &out, CYFlags flags) const {
427 out << "with({$cys:0,$cyt:0}){";
428
429 out << "$cys=";
430 set_->Output(out, CYPA, CYNoFlags);
431 out << ';';
432
433 out << "for($cyt in $cys){";
434
435 initialiser_->ForEachIn(out);
436 out << "=$cys[$cyt];";
437
438 code_->Multiple(out);
439
440 out << '}';
441
442 out << '}';
443 }
444
445 void CYForEachInComprehension::Begin_(CYOutput &out) const {
446 out << "(function($cys){";
447 out << "$cys=";
448 set_->Output(out, CYPA, CYNoFlags);
449 out << ';';
450
451 out << "for(" << *name_ << " in $cys){";
452 out << *name_ << "=$cys[" << *name_ << "];";
453 }
454
455 void CYForEachInComprehension::End_(CYOutput &out) const {
456 out << "}}());";
457 }
458
459 void CYForIn::Output(CYOutput &out, CYFlags flags) const {
460 out << "for" << ' ' << '(';
461 initialiser_->ForIn(out, CYNoIn);
462 out << "in" << *set_ << ')';
463 code_->Single(out, CYRight(flags));
464 }
465
466 void CYForInComprehension::Begin_(CYOutput &out) const {
467 out << "for" << ' ' << '(' << *name_ << "in" << *set_ << ')';
468 }
469
470 void CYFunction::Output(CYOutput &out, CYFlags flags) const {
471 // XXX: one could imagine using + here to save a byte
472 bool protect((flags & CYNoFunction) != 0);
473 if (protect)
474 out << '(';
475 out << "function";
476 if (name_ != NULL)
477 out << ' ' << *name_;
478 out << '(' << parameters_ << ')';
479 OutputBody(out, body_);
480 if (protect)
481 out << ')';
482 }
483
484 void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
485 CYFunction::Output(out, flags);
486 }
487
488 void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
489 CYFunction::Output(out, flags);
490 }
491
492 void CYFunctionParameter::Output(CYOutput &out) const {
493 out << *name_;
494 if (next_ != NULL)
495 out << ',' << ' ' << *next_;
496 }
497
498 void CYIf::Output(CYOutput &out, CYFlags flags) const {
499 bool protect(false);
500 if (false_ == NULL && (flags & CYNoDangle) != 0) {
501 protect = true;
502 out << '{';
503 }
504
505 out << "if" << ' ' << '(' << *test_ << ')';
506
507 CYFlags right(protect ? CYNoFlags : CYRight(flags));
508 CYFlags jacks(CYNoDangle);
509 if (false_ == NULL)
510 jacks |= right;
511
512 bool single(true_->Single(out, jacks));
513
514 if (false_ != NULL) {
515 out << (single ? '\t' : ' ');
516 out << "else";
517 false_->Single(out, right);
518 }
519
520 if (protect)
521 out << '}';
522 }
523
524 void CYIfComprehension::Begin_(CYOutput &out) const {
525 out << "if" << '(' << *test_ << ')';
526 }
527
528 void CYIndirect::Output(CYOutput &out, CYFlags flags) const {
529 rhs_->Output(out, 1, CYLeft(flags));
530 out << ".$cyi";
531 }
532
533 void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
534 object_->Output(out, Precedence(), CYLeft(flags));
535 out << ".$cyi";
536 if (const char *word = property_->Word())
537 out << '.' << word;
538 else
539 out << '[' << *property_ << ']';
540 }
541
542 void CYInfix::Output(CYOutput &out, CYFlags flags) const {
543 const char *name(Operator());
544 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in"));
545 if (protect)
546 out << '(';
547 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
548 lhs_->Output(out, Precedence(), left);
549 out << ' ' << name << ' ';
550 CYFlags right(protect ? CYNoFlags : CYRight(flags));
551 rhs_->Output(out, Precedence() - 1, right);
552 if (protect)
553 out << ')';
554 }
555
556 void CYLet::Output(CYOutput &out, CYFlags flags) const {
557 out << "let" << ' ' << '(' << *declarations_ << ')' << ' ' << '{';
558 if (statements_ != NULL)
559 statements_->Multiple(out);
560 out << '}';
561 }
562
563 void CYMessage::Output(CYOutput &out, bool replace) const {
564 if (next_ != NULL)
565 next_->Output(out, replace);
566 out << "$cyn=new Selector(\"";
567 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
568 if (parameter->tag_ != NULL) {
569 out << *parameter->tag_;
570 if (parameter->name_ != NULL)
571 out << ':';
572 }
573 out << "\");";
574 out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ");";
575 out << "class_" << (replace ? "replace" : "add") << "Method($cy" << (instance_ ? 'c' : 'm') << ",$cyn,";
576 out << "new Functor(function(self,_cmd";
577 for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_)
578 if (parameter->name_ != NULL)
579 out << ',' << *parameter->name_;
580 out << "){return function(){";
581 if (body_ != NULL)
582 body_->Multiple(out);
583 out << "}.call(self);},$cyt),$cyt);";
584 }
585
586 void CYNew::Output(CYOutput &out, CYFlags flags) const {
587 out << "new" << ' ';
588 CYFlags jacks(CYNoCall | CYCenter(flags));
589 constructor_->Output(out, Precedence(), jacks);
590 if (arguments_ != NULL)
591 out << '(' << *arguments_ << ')';
592 }
593
594 void CYNull::Output(CYOutput &out, CYFlags flags) const {
595 CYWord::Output(out);
596 }
597
598 void CYNumber::Output(CYOutput &out, CYFlags flags) const {
599 char value[32];
600 sprintf(value, "%.17g", Value());
601 out << value;
602 }
603
604 void CYNumber::PropertyName(CYOutput &out) const {
605 Output(out, CYNoFlags);
606 }
607
608 void CYObject::Output(CYOutput &out, CYFlags flags) const {
609 bool protect((flags & CYNoBrace) != 0);
610 if (protect)
611 out << '(';
612 out << '{';
613 out << property_;
614 out << '}';
615 if (protect)
616 out << ')';
617 }
618
619 void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
620 lhs_->Output(out, Precedence(), CYLeft(flags));
621 out << Operator();
622 }
623
624 void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
625 const char *name(Operator());
626 out << name;
627 if (Alphabetic())
628 out << ' ';
629 rhs_->Output(out, Precedence(), CYRight(flags));
630 }
631
632 void CYProperty::Output(CYOutput &out) const {
633 name_->PropertyName(out);
634 out << ':' << ' ';
635 value_->Output(out, CYPA, CYNoFlags);
636 if (next_ != NULL)
637 out << ',' << ' ' << *next_;
638 }
639
640 void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
641 out << Value();
642 }
643
644 void CYReturn::Output(CYOutput &out, CYFlags flags) const {
645 out << "return" << value_ << ';';
646 }
647
648 void CYSelector::Output(CYOutput &out, CYFlags flags) const {
649 out << "new Selector(\"";
650 if (name_ != NULL)
651 name_->Output(out);
652 out << "\")";
653 }
654
655 void CYSelectorPart::Output(CYOutput &out) const {
656 out << name_;
657 if (value_)
658 out << ':';
659 out << next_;
660 }
661
662 void CYSend::Output(CYOutput &out, CYFlags flags) const {
663 out << "objc_msgSend(";
664 self_->Output(out, CYPA, CYNoFlags);
665 out << ',';
666 std::ostringstream name;
667 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
668 if (argument->name_ != NULL) {
669 name << *argument->name_;
670 if (argument->value_ != NULL)
671 name << ':';
672 }
673 out.out_ << reinterpret_cast<void *>(sel_registerName(name.str().c_str()));
674 for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_)
675 if (argument->value_ != NULL) {
676 out << ',';
677 argument->value_->Output(out, CYPA, CYNoFlags);
678 }
679 out << ')';
680 }
681
682 void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
683 bool first(true);
684 for (const CYStatement *next(this); next != NULL; next = next->next_) {
685 bool last(next->next_ == NULL);
686 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYCenter(flags) : CYRight(flags));
687 first = false;
688 out << '\t';
689 next->Output(out, jacks);
690 out << '\n';
691 }
692 }
693
694 bool CYStatement::Single(CYOutput &out, CYFlags flags) const {
695 if (next_ != NULL) {
696 out << ' ' << '{' << '\n';
697 ++out.indent_;
698 Multiple(out);
699 --out.indent_;
700 out << '\t' << '}';
701 return false;
702 } else {
703 for (CYLabel *label(labels_); label != NULL; label = label->next_)
704 out << ' ' << *label->name_ << ':';
705 out << '\n';
706 ++out.indent_;
707 out << '\t';
708 Output(out, flags);
709 out << '\n';
710 --out.indent_;
711 return true;
712 }
713 }
714
715 void CYString::Output(CYOutput &out, CYFlags flags) const {
716 unsigned quot(0), apos(0);
717 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
718 if (*value == '"')
719 ++quot;
720 else if (*value == '\'')
721 ++apos;
722
723 bool single(quot > apos);
724
725 std::ostringstream str;
726
727 str << (single ? '\'' : '"');
728 for (const char *value(value_), *end(value_ + size_); value != end; ++value)
729 switch (*value) {
730 case '\\': str << "\\\\"; break;
731 case '\b': str << "\\b"; break;
732 case '\f': str << "\\f"; break;
733 case '\n': str << "\\n"; break;
734 case '\r': str << "\\r"; break;
735 case '\t': str << "\\t"; break;
736 case '\v': str << "\\v"; break;
737
738 case '"':
739 if (!single)
740 str << "\\\"";
741 else goto simple;
742 break;
743
744 case '\'':
745 if (single)
746 str << "\\'";
747 else goto simple;
748 break;
749
750 default:
751 if (*value < 0x20 || *value >= 0x7f)
752 str << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value);
753 else simple:
754 str << *value;
755 }
756 str << (single ? '\'' : '"');
757
758 out << str.str().c_str();
759 }
760
761 void CYString::PropertyName(CYOutput &out) const {
762 if (const char *word = Word())
763 out << word;
764 else
765 out << *this;
766 }
767
768 const char *CYString::Word() const {
769 if (size_ == 0 || !WordStartRange_[value_[0]])
770 return NULL;
771 for (size_t i(1); i != size_; ++i)
772 if (!WordEndRange_[value_[i]])
773 return NULL;
774 const char *value(Value());
775 // XXX: we should probably include the full ECMAScript3+5 list.
776 static const char *reserveds[] = {"class", "const", "enum", "export", "extends", "import", "super", NULL};
777 for (const char **reserved(reserveds); *reserved != NULL; ++reserved)
778 if (strcmp(*reserved, value) == 0)
779 return NULL;
780 return value;
781 }
782
783 void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
784 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{';
785 out << clauses_;
786 out << '}';
787 }
788
789 void CYThis::Output(CYOutput &out, CYFlags flags) const {
790 CYWord::Output(out);
791 }
792
793 void CYThrow::Output(CYOutput &out, CYFlags flags) const {
794 out << "throw" << value_ << ';';
795 }
796
797 void CYTry::Output(CYOutput &out, CYFlags flags) const {
798 out << "try" << ' ' << '{';
799 if (code_ != NULL)
800 code_->Multiple(out);
801 out << '}';
802 out << catch_;
803 out << finally_;
804 }
805
806 void CYVar::Output(CYOutput &out, CYFlags flags) const {
807 out << "var";
808 declarations_->Output(out, flags);
809 out << ';';
810 }
811
812 void CYVariable::Output(CYOutput &out, CYFlags flags) const {
813 out << *name_;
814 }
815
816 void CYWhile::Output(CYOutput &out, CYFlags flags) const {
817 out << "while" << '(' << *test_ << ')';
818 code_->Single(out, CYRight(flags));
819 }
820
821 void CYWith::Output(CYOutput &out, CYFlags flags) const {
822 out << "with" << '(' << *scope_ << ')';
823 code_->Single(out, CYRight(flags));
824 }
825
826 void CYWord::ClassName(CYOutput &out, bool object) const {
827 if (object)
828 out << "objc_getClass(";
829 out << '"' << Value() << '"';
830 if (object)
831 out << ')';
832 }
833
834 void CYWord::Output(CYOutput &out) const {
835 out << Value();
836 }
837
838 void CYWord::PropertyName(CYOutput &out) const {
839 Output(out);
840 }