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