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