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