]>
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) { | |
26 | return flags & ~CYNoTrailer; | |
27 | } | |
28 | ||
29 | _finline CYFlags CYCenter(CYFlags flags) { | |
30 | return flags & CYNoIn; | |
31 | } | |
32 | ||
33 | _finline CYFlags CYRight(CYFlags flags) { | |
fb98ac0c | 34 | return flags & (CYNoIn | CYNoTrailer | CYNoTerminator); |
b09da87b JF |
35 | } |
36 | ||
37 | bool CYFalse::Value() const { | |
38 | return false; | |
39 | } | |
40 | ||
41 | bool CYTrue::Value() const { | |
42 | return true; | |
43 | } | |
44 | ||
d35a3b07 JF |
45 | #define CYPA 16 |
46 | ||
652ec1ba | 47 | void CYAddressOf::Output(CYOutput &out, CYFlags flags) const { |
b09da87b | 48 | rhs_->Output(out, 1, CYLeft(flags)); |
9b5527f0 | 49 | out << ".$cya()"; |
5999c315 JF |
50 | } |
51 | ||
652ec1ba | 52 | void CYArgument::Output(CYOutput &out) const { |
d35a3b07 | 53 | if (name_ != NULL) { |
5999c315 JF |
54 | out << *name_; |
55 | if (value_ != NULL) | |
56 | out << ":"; | |
57 | } | |
d35a3b07 | 58 | if (value_ != NULL) |
b09da87b | 59 | value_->Output(out, CYPA, CYNoFlags); |
5999c315 | 60 | if (next_ != NULL) { |
d35a3b07 JF |
61 | if (next_->name_ == NULL) |
62 | out << ','; | |
63 | else | |
64 | out << ' '; | |
65 | next_->Output(out); | |
5999c315 JF |
66 | } |
67 | } | |
68 | ||
652ec1ba | 69 | void CYArray::Output(CYOutput &out, CYFlags flags) const { |
5befe15e JF |
70 | out << '['; |
71 | if (elements_ != NULL) | |
72 | elements_->Output(out); | |
73 | out << ']'; | |
74 | } | |
75 | ||
652ec1ba | 76 | void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const { |
75b0a457 JF |
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 << "){"; | |
dc81e1c2 | 83 | out << "$cyv=[];"; |
75b0a457 | 84 | comprehensions_->Output(out); |
dc81e1c2 | 85 | out << "$cyv.push("; |
75b0a457 JF |
86 | expression_->Output(out, CYPA, CYNoFlags); |
87 | out << ");"; | |
88 | for (CYComprehension *comprehension(comprehensions_); comprehension != NULL; comprehension = comprehension->next_) | |
89 | comprehension->End_(out); | |
dc81e1c2 | 90 | out << "return $cyv;"; |
75b0a457 JF |
91 | out << "}())"; |
92 | } | |
93 | ||
652ec1ba | 94 | void CYAssignment::Output(CYOutput &out, CYFlags flags) const { |
fb98ac0c | 95 | lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand); |
d35a3b07 | 96 | out << Operator(); |
b09da87b | 97 | rhs_->Output(out, Precedence(), CYRight(flags)); |
d35a3b07 JF |
98 | } |
99 | ||
fb98ac0c JF |
100 | void CYBlock::Output(CYOutput &out, CYFlags flags) const { |
101 | statements_->Single(out, flags); | |
9e562cfc JF |
102 | } |
103 | ||
652ec1ba | 104 | void CYBoolean::Output(CYOutput &out, CYFlags flags) const { |
b09da87b JF |
105 | if ((flags & CYNoLeader) != 0) |
106 | out << ' '; | |
5999c315 | 107 | out << (Value() ? "true" : "false"); |
b09da87b JF |
108 | if ((flags & CYNoTrailer) != 0) |
109 | out << ' '; | |
5999c315 JF |
110 | } |
111 | ||
fb98ac0c JF |
112 | void CYBreak::Output(CYOutput &out, CYFlags flags) const { |
113 | if ((flags & CYNoLeader) != 0) | |
114 | out << ' '; | |
5999c315 JF |
115 | out << "break"; |
116 | if (label_ != NULL) | |
117 | out << ' ' << *label_; | |
fb98ac0c JF |
118 | if ((flags & CYNoTerminator) == 0) |
119 | out << ';'; | |
120 | else if ((flags & CYNoTrailer) != 0) | |
121 | out << ' '; | |
5999c315 JF |
122 | } |
123 | ||
652ec1ba | 124 | void CYCall::Output(CYOutput &out, CYFlags flags) const { |
fb98ac0c JF |
125 | bool protect((flags & CYNoCall) != 0); |
126 | if (protect) | |
127 | out << '('; | |
128 | function_->Output(out, Precedence(), protect ? CYNoFlags : flags); | |
d35a3b07 | 129 | out << '('; |
5999c315 | 130 | if (arguments_ != NULL) |
d35a3b07 | 131 | arguments_->Output(out); |
5999c315 | 132 | out << ')'; |
fb98ac0c JF |
133 | if (protect) |
134 | out << ')'; | |
5999c315 JF |
135 | } |
136 | ||
652ec1ba | 137 | void CYCatch::Output(CYOutput &out) const { |
b10bd496 JF |
138 | out << "catch(" << *name_ << "){"; |
139 | if (code_ != NULL) | |
fb98ac0c | 140 | code_->Multiple(out); |
b10bd496 | 141 | out << "}"; |
5999c315 JF |
142 | } |
143 | ||
fb98ac0c | 144 | void CYCategory::Output(CYOutput &out, CYFlags flags) const { |
e5bc40db JF |
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 << "})("; | |
367eebb1 | 151 | name_->ClassName(out, true); |
fb98ac0c JF |
152 | out << ')'; |
153 | if ((flags & CYNoTerminator) == 0) | |
154 | out << ';'; | |
365abb0a JF |
155 | } |
156 | ||
652ec1ba | 157 | void CYClass::Output(CYOutput &out, CYFlags flags) const { |
367eebb1 | 158 | // XXX: I don't necc. need the ()s |
e5bc40db JF |
159 | out << "(function($cys,$cyp,$cyc,$cyn,$cyt,$cym){"; |
160 | out << "$cyp=object_getClass($cys);"; | |
367eebb1 JF |
161 | out << "$cyc=objc_allocateClassPair($cys,"; |
162 | if (name_ != NULL) | |
163 | name_->ClassName(out, false); | |
164 | else | |
165 | out << "$cyq(\"CY$\")"; | |
166 | out << ",0);"; | |
b09da87b JF |
167 | out << "$cym=object_getClass($cyc);"; |
168 | if (fields_ != NULL) | |
169 | fields_->Output(out); | |
170 | if (messages_ != NULL) | |
e5bc40db | 171 | messages_->Output(out, false); |
b09da87b | 172 | out << "objc_registerClassPair($cyc);"; |
367eebb1 JF |
173 | out << "return $cyc;"; |
174 | out << "}("; | |
b09da87b JF |
175 | if (super_ != NULL) |
176 | super_->Output(out, CYPA, CYNoFlags); | |
177 | else | |
178 | out << "null"; | |
367eebb1 | 179 | out << "))"; |
b09da87b JF |
180 | } |
181 | ||
fb98ac0c JF |
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 | ||
652ec1ba | 190 | void CYCompound::Output(CYOutput &out, CYFlags flags) const { |
e5bc40db JF |
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 | ||
652ec1ba | 206 | void CYComprehension::Output(CYOutput &out) const { |
75b0a457 JF |
207 | Begin_(out); |
208 | if (next_ != NULL) | |
209 | next_->Output(out); | |
210 | } | |
211 | ||
652ec1ba | 212 | void CYCondition::Output(CYOutput &out, CYFlags flags) const { |
b09da87b | 213 | test_->Output(out, Precedence() - 1, CYLeft(flags)); |
d35a3b07 | 214 | out << '?'; |
5999c315 | 215 | if (true_ != NULL) |
b09da87b | 216 | true_->Output(out, CYPA, CYNoFlags); |
d35a3b07 | 217 | out << ':'; |
b09da87b | 218 | false_->Output(out, CYPA, CYRight(flags)); |
5999c315 JF |
219 | } |
220 | ||
fb98ac0c JF |
221 | void CYContinue::Output(CYOutput &out, CYFlags flags) const { |
222 | if ((flags & CYNoLeader) != 0) | |
223 | out << ' '; | |
5999c315 JF |
224 | out << "continue"; |
225 | if (label_ != NULL) | |
226 | out << ' ' << *label_; | |
fb98ac0c JF |
227 | if ((flags & CYNoTerminator) == 0) |
228 | out << ';'; | |
229 | else if ((flags & CYNoTrailer) != 0) | |
230 | out << ' '; | |
5999c315 JF |
231 | } |
232 | ||
652ec1ba | 233 | void CYClause::Output(CYOutput &out) const { |
d35a3b07 JF |
234 | if (case_ != NULL) { |
235 | out << "case"; | |
cac61857 | 236 | case_->Output(out, CYNoLeader); |
d35a3b07 | 237 | } else |
5999c315 JF |
238 | out << "default"; |
239 | out << ':'; | |
240 | if (code_ != NULL) | |
fb98ac0c | 241 | code_->Multiple(out, next_ == NULL ? CYNoFlags : CYNoTrailer); |
cac61857 JF |
242 | if (next_ != NULL) |
243 | out << *next_; | |
244 | } | |
245 | ||
246 | const char *CYDeclaration::ForEachIn() const { | |
247 | return identifier_->Value(); | |
5999c315 JF |
248 | } |
249 | ||
652ec1ba | 250 | void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const { |
75b0a457 JF |
251 | if ((flags & CYNoLeader) != 0) |
252 | out << ' '; | |
fb98ac0c JF |
253 | out << "var"; |
254 | Output(out, CYRight(flags) | CYNoLeader); | |
75b0a457 JF |
255 | } |
256 | ||
652ec1ba | 257 | void CYDeclaration::ForEachIn(CYOutput &out) const { |
75b0a457 | 258 | out << *identifier_; |
5999c315 JF |
259 | } |
260 | ||
652ec1ba | 261 | void CYDeclaration::Output(CYOutput &out, CYFlags flags) const { |
fb98ac0c JF |
262 | if ((flags & CYNoLeader) != 0) |
263 | out << ' '; | |
5999c315 | 264 | out << *identifier_; |
d35a3b07 JF |
265 | if (initialiser_ != NULL) { |
266 | out << '='; | |
75b0a457 JF |
267 | initialiser_->Output(out, CYPA, CYRight(flags)); |
268 | } else if ((flags & CYNoTrailer) != 0) | |
269 | out << ' '; | |
5999c315 JF |
270 | } |
271 | ||
652ec1ba | 272 | void CYDeclarations::For(CYOutput &out) const { |
fb98ac0c JF |
273 | out << "var"; |
274 | Output(out, CYNoIn | CYNoLeader); | |
cac61857 | 275 | } |
d35a3b07 | 276 | |
652ec1ba | 277 | void CYDeclarations::Output(CYOutput &out, CYFlags flags) const { |
5999c315 | 278 | const CYDeclarations *declaration(this); |
fb98ac0c | 279 | bool first(true); |
d35a3b07 | 280 | output: |
75b0a457 | 281 | CYDeclarations *next(declaration->next_); |
fb98ac0c JF |
282 | CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags)); |
283 | first = false; | |
284 | declaration->declaration_->Output(out, jacks); | |
d35a3b07 | 285 | |
75b0a457 | 286 | if (next != NULL) { |
d35a3b07 | 287 | out << ','; |
75b0a457 | 288 | declaration = next; |
d35a3b07 JF |
289 | goto output; |
290 | } | |
5999c315 JF |
291 | } |
292 | ||
652ec1ba | 293 | void CYDirectMember::Output(CYOutput &out, CYFlags flags) const { |
9b5527f0 JF |
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 | ||
fb98ac0c JF |
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); | |
d35a3b07 | 309 | out << "while("; |
b09da87b JF |
310 | test_->Output(out, CYNoFlags); |
311 | out << ')'; | |
5999c315 JF |
312 | } |
313 | ||
652ec1ba | 314 | void CYElement::Output(CYOutput &out) const { |
5999c315 | 315 | if (value_ != NULL) |
b09da87b | 316 | value_->Output(out, CYPA, CYNoFlags); |
5befe15e | 317 | if (next_ != NULL || value_ == NULL) |
5999c315 | 318 | out << ','; |
5befe15e JF |
319 | if (next_ != NULL) |
320 | next_->Output(out); | |
5999c315 JF |
321 | } |
322 | ||
fb98ac0c | 323 | void CYEmpty::Output(CYOutput &out, CYFlags flags) const { |
5999c315 JF |
324 | out << ';'; |
325 | } | |
326 | ||
fb98ac0c JF |
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 << ';'; | |
5999c315 JF |
332 | } |
333 | ||
652ec1ba | 334 | void CYExpression::ClassName(CYOutput &out, bool object) const { |
e5bc40db JF |
335 | Output(out, CYPA, CYNoFlags); |
336 | } | |
337 | ||
cac61857 JF |
338 | const char *CYExpression::ForEachIn() const { |
339 | return NULL; | |
340 | } | |
341 | ||
652ec1ba | 342 | void CYExpression::For(CYOutput &out) const { |
cac61857 JF |
343 | Output(out, CYNoIn); |
344 | } | |
345 | ||
652ec1ba | 346 | void CYExpression::ForEachIn(CYOutput &out) const { |
fb98ac0c | 347 | Output(out, CYPA, CYNoRightHand); |
75b0a457 JF |
348 | } |
349 | ||
652ec1ba | 350 | void CYExpression::ForIn(CYOutput &out, CYFlags flags) const { |
fb98ac0c | 351 | Output(out, flags | CYNoRightHand); |
d35a3b07 JF |
352 | } |
353 | ||
652ec1ba | 354 | void CYExpression::Output(CYOutput &out, unsigned precedence, CYFlags flags) const { |
fb98ac0c | 355 | if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand()) { |
5999c315 | 356 | out << '('; |
b09da87b | 357 | Output(out, CYNoFlags); |
5999c315 | 358 | out << ')'; |
b09da87b JF |
359 | } else |
360 | Output(out, flags); | |
361 | } | |
362 | ||
652ec1ba | 363 | void CYField::Output(CYOutput &out) const { |
b09da87b | 364 | // XXX: implement! |
5999c315 JF |
365 | } |
366 | ||
b10bd496 JF |
367 | void CYFinally::Output(CYOutput &out) const { |
368 | out << "finally{"; | |
369 | if (code_ != NULL) | |
fb98ac0c | 370 | code_->Multiple(out); |
b10bd496 JF |
371 | out << "}"; |
372 | } | |
373 | ||
fb98ac0c JF |
374 | void CYFor::Output(CYOutput &out, CYFlags flags) const { |
375 | if ((flags & CYNoLeader) != 0) | |
376 | out << ' '; | |
5999c315 JF |
377 | out << "for("; |
378 | if (initialiser_ != NULL) | |
cac61857 | 379 | initialiser_->For(out); |
5999c315 JF |
380 | out << ';'; |
381 | if (test_ != NULL) | |
b09da87b | 382 | test_->Output(out, CYNoFlags); |
5999c315 JF |
383 | out << ';'; |
384 | if (increment_ != NULL) | |
b09da87b | 385 | increment_->Output(out, CYNoFlags); |
5999c315 | 386 | out << ')'; |
fb98ac0c | 387 | code_->Single(out, CYNoFlags); |
5999c315 JF |
388 | } |
389 | ||
fb98ac0c JF |
390 | void CYForEachIn::Output(CYOutput &out, CYFlags flags) const { |
391 | if ((flags & CYNoLeader) != 0) | |
392 | out << ' '; | |
393 | ||
6f926cee | 394 | out << "with({$cys:0,$cyt:0}){"; |
75b0a457 | 395 | |
75b0a457 JF |
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 | ||
fb98ac0c | 405 | code_->Multiple(out); |
75b0a457 | 406 | |
6f926cee | 407 | out << '}'; |
75b0a457 | 408 | |
6f926cee | 409 | out << '}'; |
75b0a457 JF |
410 | } |
411 | ||
652ec1ba | 412 | void CYForEachInComprehension::Begin_(CYOutput &out) const { |
75b0a457 JF |
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 | ||
652ec1ba | 422 | void CYForEachInComprehension::End_(CYOutput &out) const { |
75b0a457 JF |
423 | out << "}}());"; |
424 | } | |
425 | ||
fb98ac0c JF |
426 | void CYForIn::Output(CYOutput &out, CYFlags flags) const { |
427 | if ((flags & CYNoLeader) != 0) | |
428 | out << ' '; | |
5999c315 | 429 | out << "for("; |
cac61857 | 430 | initialiser_->ForIn(out, CYNoIn | CYNoTrailer); |
b09da87b JF |
431 | out << "in"; |
432 | set_->Output(out, CYNoLeader); | |
5999c315 | 433 | out << ')'; |
fb98ac0c | 434 | code_->Single(out, CYRight(flags)); |
5999c315 JF |
435 | } |
436 | ||
652ec1ba | 437 | void CYForInComprehension::Begin_(CYOutput &out) const { |
75b0a457 JF |
438 | out << "for(" << *name_ << " in"; |
439 | set_->Output(out, CYNoLeader); | |
440 | out << ')'; | |
441 | } | |
442 | ||
fb98ac0c JF |
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); | |
b09da87b JF |
469 | } |
470 | ||
652ec1ba | 471 | void CYFunctionParameter::Output(CYOutput &out) const { |
b09da87b JF |
472 | out << *name_; |
473 | if (next_ != NULL) { | |
474 | out << ','; | |
475 | out << *next_; | |
476 | } | |
5999c315 JF |
477 | } |
478 | ||
fb98ac0c JF |
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 << ' '; | |
d35a3b07 | 486 | out << "if("; |
b09da87b | 487 | test_->Output(out, CYNoFlags); |
d35a3b07 | 488 | out << ')'; |
fb98ac0c JF |
489 | CYFlags right(protect ? CYNoFlags : CYRight(flags)); |
490 | CYFlags jacks(CYNoDangle); | |
491 | jacks |= false_ == NULL ? right : CYNoTrailer; | |
492 | true_->Single(out, jacks); | |
5999c315 | 493 | if (false_ != NULL) { |
fb98ac0c JF |
494 | out << "else"; |
495 | if (protect) | |
496 | right |= CYNoTerminator; | |
497 | false_->Single(out, CYNoLeader | right); | |
5999c315 | 498 | } |
fb98ac0c JF |
499 | if (protect) |
500 | out << '}'; | |
5999c315 JF |
501 | } |
502 | ||
652ec1ba | 503 | void CYIfComprehension::Begin_(CYOutput &out) const { |
75b0a457 JF |
504 | out << "if("; |
505 | test_->Output(out, CYNoFlags); | |
506 | out << ')'; | |
507 | } | |
508 | ||
652ec1ba | 509 | void CYIndirect::Output(CYOutput &out, CYFlags flags) const { |
b09da87b | 510 | rhs_->Output(out, 1, CYLeft(flags)); |
9b5527f0 | 511 | out << ".$cyi"; |
fb98ac0c JF |
512 | if ((flags & CYNoTrailer) != 0) |
513 | out << ' '; | |
9b5527f0 JF |
514 | } |
515 | ||
652ec1ba | 516 | void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const { |
9b5527f0 JF |
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 | } | |
5999c315 JF |
526 | } |
527 | ||
652ec1ba | 528 | void CYInfix::Output(CYOutput &out, CYFlags flags) const { |
b09da87b JF |
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; | |
1ef7d061 JF |
542 | if (strcmp(name, "-") == 0) |
543 | right |= CYNoHyphen; | |
b09da87b JF |
544 | rhs_->Output(out, Precedence() - 1, right); |
545 | if (protect) | |
546 | out << ')'; | |
5999c315 JF |
547 | } |
548 | ||
fb98ac0c JF |
549 | void CYLet::Output(CYOutput &out, CYFlags flags) const { |
550 | if ((flags & CYNoLeader) != 0) | |
83b5afe2 | 551 | out << ' '; |
cac61857 JF |
552 | out << "let("; |
553 | declarations_->Output(out, CYNoFlags); | |
554 | out << "){"; | |
555 | if (statements_ != NULL) | |
fb98ac0c | 556 | statements_->Multiple(out); |
cac61857 JF |
557 | out << "}"; |
558 | } | |
559 | ||
652ec1ba | 560 | void CYMessage::Output(CYOutput &out, bool replace) const { |
4e8c99fb | 561 | if (next_ != NULL) |
e5bc40db | 562 | next_->Output(out, replace); |
b09da87b JF |
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) | |
5999c315 JF |
568 | out << ':'; |
569 | } | |
b09da87b | 570 | out << "\");"; |
e5bc40db JF |
571 | out << "$cyt=$cyn.type($cy" << (instance_ ? 's' : 'p') << ");"; |
572 | out << "class_" << (replace ? "replace" : "add") << "Method($cy" << (instance_ ? 'c' : 'm') << ",$cyn,"; | |
478d4ed0 | 573 | out << "new Functor(function(self,_cmd"; |
b09da87b | 574 | for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_) |
478d4ed0 JF |
575 | if (parameter->name_ != NULL) |
576 | out << ',' << *parameter->name_; | |
577 | out << "){return function(){"; | |
b09da87b | 578 | if (body_ != NULL) |
fb98ac0c | 579 | body_->Multiple(out); |
478d4ed0 | 580 | out << "}.call(self);},$cyt),$cyt);"; |
5999c315 JF |
581 | } |
582 | ||
652ec1ba | 583 | void CYNew::Output(CYOutput &out, CYFlags flags) const { |
bce8339b JF |
584 | if ((flags & CYNoLeader) != 0) |
585 | out << ' '; | |
d35a3b07 | 586 | out << "new"; |
fb98ac0c JF |
587 | constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader | CYNoCall); |
588 | if (arguments_ != NULL) { | |
589 | out << '('; | |
d35a3b07 | 590 | arguments_->Output(out); |
fb98ac0c JF |
591 | out << ')'; |
592 | } | |
5999c315 JF |
593 | } |
594 | ||
652ec1ba | 595 | void CYNull::Output(CYOutput &out, CYFlags flags) const { |
b09da87b JF |
596 | if ((flags & CYNoLeader) != 0) |
597 | out << ' '; | |
5999c315 | 598 | CYWord::Output(out); |
b09da87b JF |
599 | if ((flags & CYNoTrailer) != 0) |
600 | out << ' '; | |
5999c315 JF |
601 | } |
602 | ||
652ec1ba | 603 | void CYNumber::Output(CYOutput &out, CYFlags flags) const { |
1ef7d061 JF |
604 | double value(Value()); |
605 | if ((flags & CYNoLeader) != 0 || value < 0 && (flags & CYNoHyphen) != 0) | |
b09da87b | 606 | out << ' '; |
18401062 | 607 | // XXX: decide on correct precision |
652ec1ba | 608 | out.out_ << std::setprecision(9) << value; |
b09da87b JF |
609 | if ((flags & CYNoTrailer) != 0) |
610 | out << ' '; | |
5999c315 JF |
611 | } |
612 | ||
652ec1ba | 613 | void CYNumber::PropertyName(CYOutput &out) const { |
fb98ac0c | 614 | Output(out, CYNoFlags); |
e5bc40db JF |
615 | } |
616 | ||
652ec1ba | 617 | void CYObject::Output(CYOutput &out, CYFlags flags) const { |
b09da87b JF |
618 | bool protect((flags & CYNoBrace) != 0); |
619 | if (protect) | |
620 | out << '('; | |
693d501b JF |
621 | out << '{'; |
622 | if (property_ != NULL) | |
623 | property_->Output(out); | |
624 | out << '}'; | |
b09da87b JF |
625 | if (protect) |
626 | out << ')'; | |
693d501b JF |
627 | } |
628 | ||
652ec1ba | 629 | void CYPostfix::Output(CYOutput &out, CYFlags flags) const { |
b09da87b | 630 | lhs_->Output(out, Precedence(), CYLeft(flags)); |
d35a3b07 | 631 | out << Operator(); |
5999c315 JF |
632 | } |
633 | ||
652ec1ba | 634 | void CYPrefix::Output(CYOutput &out, CYFlags flags) const { |
1ef7d061 | 635 | const char *name(Operator()); |
b09da87b | 636 | bool alphabetic(Alphabetic()); |
1ef7d061 JF |
637 | if (alphabetic && (flags & CYNoLeader) != 0 || name[0] == '-' && (flags & CYNoHyphen) != 0) |
638 | out << ' '; | |
639 | out << name; | |
b09da87b JF |
640 | CYFlags right(CYRight(flags)); |
641 | if (alphabetic) | |
642 | right |= CYNoLeader; | |
643 | rhs_->Output(out, Precedence(), right); | |
5999c315 JF |
644 | } |
645 | ||
652ec1ba | 646 | void CYProperty::Output(CYOutput &out) const { |
e5bc40db | 647 | name_->PropertyName(out); |
579ed526 | 648 | out << ':'; |
b09da87b | 649 | value_->Output(out, CYPA, CYNoFlags); |
5999c315 JF |
650 | if (next_ != NULL) { |
651 | out << ','; | |
693d501b | 652 | next_->Output(out); |
5999c315 | 653 | } |
5999c315 JF |
654 | } |
655 | ||
63cd45c9 JF |
656 | void CYRegEx::Output(CYOutput &out, CYFlags flags) const { |
657 | out << Value(); | |
658 | if ((flags & CYNoTrailer) != 0) | |
659 | out << ' '; | |
660 | } | |
661 | ||
fb98ac0c JF |
662 | void CYReturn::Output(CYOutput &out, CYFlags flags) const { |
663 | bool terminator((flags & CYNoTerminator) == 0); | |
664 | if ((flags & CYNoLeader) != 0) | |
665 | out << ' '; | |
5999c315 | 666 | out << "return"; |
b09da87b | 667 | if (value_ != NULL) |
fb98ac0c JF |
668 | value_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader); |
669 | if (terminator) | |
670 | out << ';'; | |
5999c315 JF |
671 | } |
672 | ||
652ec1ba | 673 | void CYSelector::Output(CYOutput &out, CYFlags flags) const { |
bce8339b JF |
674 | if ((flags & CYNoLeader) != 0) |
675 | out << ' '; | |
b09da87b | 676 | out << "new Selector(\""; |
62014ea9 JF |
677 | if (name_ != NULL) |
678 | name_->Output(out); | |
dea834b0 | 679 | out << "\")"; |
e7ed5354 JF |
680 | } |
681 | ||
652ec1ba | 682 | void CYSelectorPart::Output(CYOutput &out) const { |
62014ea9 JF |
683 | if (name_ != NULL) |
684 | out << *name_; | |
685 | if (value_) | |
686 | out << ':'; | |
687 | if (next_ != NULL) | |
688 | next_->Output(out); | |
689 | } | |
690 | ||
652ec1ba | 691 | void CYSend::Output(CYOutput &out, CYFlags flags) const { |
c239b9f8 JF |
692 | if ((flags & CYNoLeader) != 0) |
693 | out << ' '; | |
b09da87b JF |
694 | out << "objc_msgSend("; |
695 | self_->Output(out, CYPA, CYNoFlags); | |
4afefdd9 JF |
696 | out << ","; |
697 | std::ostringstream name; | |
b09da87b JF |
698 | for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) |
699 | if (argument->name_ != NULL) { | |
4afefdd9 | 700 | name << *argument->name_; |
b09da87b | 701 | if (argument->value_ != NULL) |
4afefdd9 | 702 | name << ':'; |
b09da87b | 703 | } |
652ec1ba | 704 | out.out_ << reinterpret_cast<void *>(sel_registerName(name.str().c_str())); |
b09da87b JF |
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 | ||
fb98ac0c JF |
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 | } | |
5999c315 JF |
723 | } |
724 | ||
fb98ac0c JF |
725 | void CYStatement::Single(CYOutput &out, CYFlags flags) const { |
726 | if (next_ != NULL) { | |
5999c315 | 727 | out << '{'; |
fb98ac0c | 728 | Multiple(out); |
5999c315 | 729 | out << '}'; |
fb98ac0c JF |
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); | |
5999c315 JF |
739 | } |
740 | } | |
741 | ||
652ec1ba | 742 | void CYString::Output(CYOutput &out, CYFlags flags) const { |
b4aa79af JF |
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 ? '\'' : '"'); | |
5999c315 JF |
753 | for (const char *value(value_), *end(value_ + size_); value != end; ++value) |
754 | switch (*value) { | |
5999c315 JF |
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 | ||
b4aa79af JF |
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 | ||
5999c315 JF |
775 | default: |
776 | if (*value < 0x20 || *value >= 0x7f) | |
652ec1ba | 777 | out.out_ << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value); |
b4aa79af | 778 | else simple: |
5999c315 JF |
779 | out << *value; |
780 | } | |
b4aa79af | 781 | out << (single ? '\'' : '"'); |
5999c315 JF |
782 | } |
783 | ||
652ec1ba | 784 | void CYString::PropertyName(CYOutput &out) const { |
e5bc40db JF |
785 | if (const char *word = Word()) |
786 | out << word; | |
787 | else | |
fb98ac0c | 788 | Output(out, CYNoFlags); |
e5bc40db JF |
789 | } |
790 | ||
fb98ac0c JF |
791 | void CYSwitch::Output(CYOutput &out, CYFlags flags) const { |
792 | if ((flags & CYNoLeader) != 0) | |
793 | out << ' '; | |
d35a3b07 | 794 | out << "switch("; |
b09da87b | 795 | value_->Output(out, CYNoFlags); |
d35a3b07 | 796 | out << "){"; |
5999c315 JF |
797 | if (clauses_ != NULL) |
798 | out << *clauses_; | |
799 | out << '}'; | |
800 | } | |
801 | ||
652ec1ba | 802 | void CYThis::Output(CYOutput &out, CYFlags flags) const { |
b09da87b JF |
803 | if ((flags & CYNoLeader) != 0) |
804 | out << ' '; | |
5999c315 | 805 | CYWord::Output(out); |
b09da87b JF |
806 | if ((flags & CYNoTrailer) != 0) |
807 | out << ' '; | |
5999c315 JF |
808 | } |
809 | ||
fb98ac0c JF |
810 | void CYThrow::Output(CYOutput &out, CYFlags flags) const { |
811 | bool terminator((flags & CYNoTerminator) == 0); | |
812 | if ((flags & CYNoLeader) != 0) | |
813 | out << ' '; | |
d35a3b07 | 814 | out << "throw"; |
b09da87b | 815 | if (value_ != NULL) |
fb98ac0c JF |
816 | value_->Output(out, (terminator ? CYCenter(flags) : flags) | CYNoLeader); |
817 | if (terminator) | |
818 | out << ';'; | |
5999c315 JF |
819 | } |
820 | ||
fb98ac0c JF |
821 | void CYTry::Output(CYOutput &out, CYFlags flags) const { |
822 | if ((flags & CYNoLeader) != 0) | |
823 | out << ' '; | |
b10bd496 JF |
824 | out << "try{"; |
825 | if (code_ != NULL) | |
fb98ac0c | 826 | code_->Multiple(out); |
b10bd496 | 827 | out << "}"; |
5999c315 | 828 | if (catch_ != NULL) |
9b5527f0 | 829 | catch_->Output(out); |
b10bd496 JF |
830 | if (finally_ != NULL) |
831 | finally_->Output(out); | |
5999c315 JF |
832 | } |
833 | ||
fb98ac0c JF |
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 << ';'; | |
cac61857 JF |
842 | } |
843 | ||
652ec1ba | 844 | void CYVariable::Output(CYOutput &out, CYFlags flags) const { |
478d4ed0 JF |
845 | if ((flags & CYNoLeader) != 0) |
846 | out << ' '; | |
5999c315 | 847 | out << *name_; |
478d4ed0 JF |
848 | if ((flags & CYNoTrailer) != 0) |
849 | out << ' '; | |
5999c315 JF |
850 | } |
851 | ||
fb98ac0c JF |
852 | void CYWhile::Output(CYOutput &out, CYFlags flags) const { |
853 | if ((flags & CYNoLeader) != 0) | |
854 | out << ' '; | |
d35a3b07 | 855 | out << "while("; |
b09da87b | 856 | test_->Output(out, CYNoFlags); |
d35a3b07 | 857 | out << ')'; |
fb98ac0c | 858 | code_->Single(out, CYRight(flags)); |
5999c315 JF |
859 | } |
860 | ||
fb98ac0c JF |
861 | void CYWith::Output(CYOutput &out, CYFlags flags) const { |
862 | if ((flags & CYNoLeader) != 0) | |
863 | out << ' '; | |
d35a3b07 | 864 | out << "with("; |
b09da87b | 865 | scope_->Output(out, CYNoFlags); |
d35a3b07 | 866 | out << ')'; |
fb98ac0c | 867 | code_->Single(out, CYRight(flags)); |
5999c315 JF |
868 | } |
869 | ||
652ec1ba | 870 | void CYWord::ClassName(CYOutput &out, bool object) const { |
367eebb1 JF |
871 | if (object) |
872 | out << "objc_getClass("; | |
873 | out << '"' << Value() << '"'; | |
874 | if (object) | |
875 | out << ')'; | |
e5bc40db JF |
876 | } |
877 | ||
652ec1ba | 878 | void CYWord::Output(CYOutput &out) const { |
5999c315 JF |
879 | out << Value(); |
880 | } | |
e5bc40db | 881 | |
652ec1ba | 882 | void CYWord::PropertyName(CYOutput &out) const { |
e5bc40db JF |
883 | Output(out); |
884 | } |