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