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