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