]>
Commit | Line | Data |
---|---|---|
1 | #include "Parser.hpp" | |
2 | ||
3 | #include <iostream> | |
4 | #include <iomanip> | |
5 | ||
6 | #include <objc/runtime.h> | |
7 | #include <sstream> | |
8 | ||
9 | _finline CYFlags operator ~(CYFlags rhs) { | |
10 | return static_cast<CYFlags>(~static_cast<unsigned>(rhs)); | |
11 | } | |
12 | ||
13 | _finline CYFlags operator &(CYFlags lhs, CYFlags rhs) { | |
14 | return static_cast<CYFlags>(static_cast<unsigned>(lhs) & static_cast<unsigned>(rhs)); | |
15 | } | |
16 | ||
17 | _finline CYFlags operator |(CYFlags lhs, CYFlags rhs) { | |
18 | return static_cast<CYFlags>(static_cast<unsigned>(lhs) | static_cast<unsigned>(rhs)); | |
19 | } | |
20 | ||
21 | _finline CYFlags &operator |=(CYFlags &lhs, CYFlags rhs) { | |
22 | return lhs = lhs | rhs; | |
23 | } | |
24 | ||
25 | _finline CYFlags CYLeft(CYFlags flags) { | |
26 | return flags & ~CYNoTrailer; | |
27 | } | |
28 | ||
29 | _finline CYFlags CYCenter(CYFlags flags) { | |
30 | return flags & CYNoIn; | |
31 | } | |
32 | ||
33 | _finline CYFlags CYRight(CYFlags flags) { | |
34 | return flags & (CYNoIn | CYNoTrailer); | |
35 | } | |
36 | ||
37 | bool CYFalse::Value() const { | |
38 | return false; | |
39 | } | |
40 | ||
41 | bool CYTrue::Value() const { | |
42 | return true; | |
43 | } | |
44 | ||
45 | #define CYPA 16 | |
46 | ||
47 | void CYAddressOf::Output(std::ostream &out, CYFlags flags) const { | |
48 | rhs_->Output(out, 1, CYLeft(flags)); | |
49 | out << ".addressOf()"; | |
50 | } | |
51 | ||
52 | void CYArgument::Output(std::ostream &out) const { | |
53 | if (name_ != NULL) { | |
54 | out << *name_; | |
55 | if (value_ != NULL) | |
56 | out << ":"; | |
57 | } | |
58 | if (value_ != NULL) | |
59 | value_->Output(out, CYPA, CYNoFlags); | |
60 | if (next_ != NULL) { | |
61 | if (next_->name_ == NULL) | |
62 | out << ','; | |
63 | else | |
64 | out << ' '; | |
65 | next_->Output(out); | |
66 | } | |
67 | } | |
68 | ||
69 | void CYArray::Output(std::ostream &out, CYFlags flags) const { | |
70 | out << '['; | |
71 | if (elements_ != NULL) | |
72 | elements_->Output(out); | |
73 | out << ']'; | |
74 | } | |
75 | ||
76 | void CYAssignment::Output(std::ostream &out, CYFlags flags) const { | |
77 | lhs_->Output(out, Precedence() - 1, CYLeft(flags)); | |
78 | out << Operator(); | |
79 | rhs_->Output(out, Precedence(), CYRight(flags)); | |
80 | } | |
81 | ||
82 | void CYBoolean::Output(std::ostream &out, CYFlags flags) const { | |
83 | if ((flags & CYNoLeader) != 0) | |
84 | out << ' '; | |
85 | out << (Value() ? "true" : "false"); | |
86 | if ((flags & CYNoTrailer) != 0) | |
87 | out << ' '; | |
88 | } | |
89 | ||
90 | void CYBreak::Output(std::ostream &out) const { | |
91 | out << "break"; | |
92 | if (label_ != NULL) | |
93 | out << ' ' << *label_; | |
94 | out << ';'; | |
95 | } | |
96 | ||
97 | void CYCall::Output(std::ostream &out, CYFlags flags) const { | |
98 | function_->Output(out, Precedence(), CYLeft(flags)); | |
99 | out << '('; | |
100 | if (arguments_ != NULL) | |
101 | arguments_->Output(out); | |
102 | out << ')'; | |
103 | } | |
104 | ||
105 | void CYCatch::Output(std::ostream &out) const { | |
106 | out << "catch(" << *name_ << ')'; | |
107 | code_->Output(out, true); | |
108 | } | |
109 | ||
110 | void CYClass::Output(std::ostream &out) const { | |
111 | out << "(function($cys,$cyc,$cym,$cyn,$cyt){"; | |
112 | out << "$cyc=objc_allocateClassPair($cys,\"" << *name_ << "\",0);"; | |
113 | out << "$cym=object_getClass($cyc);"; | |
114 | if (fields_ != NULL) | |
115 | fields_->Output(out); | |
116 | if (messages_ != NULL) | |
117 | messages_->Output(out); | |
118 | out << "objc_registerClassPair($cyc);"; | |
119 | out << "})("; | |
120 | if (super_ != NULL) | |
121 | super_->Output(out, CYPA, CYNoFlags); | |
122 | else | |
123 | out << "null"; | |
124 | out << ");"; | |
125 | } | |
126 | ||
127 | void CYCondition::Output(std::ostream &out, CYFlags flags) const { | |
128 | test_->Output(out, Precedence() - 1, CYLeft(flags)); | |
129 | out << '?'; | |
130 | if (true_ != NULL) | |
131 | true_->Output(out, CYPA, CYNoFlags); | |
132 | out << ':'; | |
133 | false_->Output(out, CYPA, CYRight(flags)); | |
134 | } | |
135 | ||
136 | void CYContinue::Output(std::ostream &out) const { | |
137 | out << "continue"; | |
138 | if (label_ != NULL) | |
139 | out << ' ' << *label_; | |
140 | out << ';'; | |
141 | } | |
142 | ||
143 | void CYClause::Output(std::ostream &out) const { | |
144 | if (case_ != NULL) { | |
145 | out << "case"; | |
146 | case_->Output(out, CYNoFlags); | |
147 | } else | |
148 | out << "default"; | |
149 | out << ':'; | |
150 | if (code_ != NULL) | |
151 | code_->Output(out, false); | |
152 | out << *next_; | |
153 | } | |
154 | ||
155 | // XXX: deal with NoIn | |
156 | void CYDeclaration::Part(std::ostream &out) const { | |
157 | out << "var "; | |
158 | Output(out); | |
159 | } | |
160 | ||
161 | void CYDeclaration::Output(std::ostream &out) const { | |
162 | out << *identifier_; | |
163 | if (initialiser_ != NULL) { | |
164 | out << '='; | |
165 | initialiser_->Output(out, CYPA, CYNoFlags); | |
166 | } | |
167 | } | |
168 | ||
169 | // XXX: deal with NoIn | |
170 | void CYDeclarations::Part(std::ostream &out) const { | |
171 | out << "var "; | |
172 | ||
173 | const CYDeclarations *declaration(this); | |
174 | output: | |
175 | out << *declaration->declaration_; | |
176 | declaration = declaration->next_; | |
177 | ||
178 | if (declaration != NULL) { | |
179 | out << ','; | |
180 | goto output; | |
181 | } | |
182 | } | |
183 | ||
184 | void CYDeclarations::Output(std::ostream &out) const { | |
185 | Part(out); | |
186 | out << ';'; | |
187 | } | |
188 | ||
189 | void CYDoWhile::Output(std::ostream &out) const { | |
190 | // XXX: extra space character! | |
191 | out << "do "; | |
192 | code_->Output(out, false); | |
193 | out << "while("; | |
194 | test_->Output(out, CYNoFlags); | |
195 | out << ')'; | |
196 | } | |
197 | ||
198 | void CYElement::Output(std::ostream &out) const { | |
199 | if (value_ != NULL) | |
200 | value_->Output(out, CYPA, CYNoFlags); | |
201 | if (next_ != NULL || value_ == NULL) | |
202 | out << ','; | |
203 | if (next_ != NULL) | |
204 | next_->Output(out); | |
205 | } | |
206 | ||
207 | void CYEmpty::Output(std::ostream &out) const { | |
208 | out << ';'; | |
209 | } | |
210 | ||
211 | void CYEmpty::Output(std::ostream &out, bool block) const { | |
212 | if (next_ != NULL) | |
213 | CYSource::Output(out, block); | |
214 | else | |
215 | out << "{}"; | |
216 | } | |
217 | ||
218 | void CYExpress::Output(std::ostream &out) const { | |
219 | expression_->Output(out, CYNoFunction | CYNoBrace); | |
220 | out << ';'; | |
221 | } | |
222 | ||
223 | void CYExpression::Part(std::ostream &out) const { | |
224 | // XXX: this should handle LeftHandSideExpression | |
225 | Output(out, CYNoIn); | |
226 | } | |
227 | ||
228 | void CYCompound::Output(std::ostream &out, CYFlags flags) const { | |
229 | if (CYExpression *expression = expressions_) | |
230 | if (CYExpression *next = expression->next_) { | |
231 | expression->Output(out, CYLeft(flags)); | |
232 | CYFlags center(CYCenter(flags)); | |
233 | while (next != NULL) { | |
234 | expression = next; | |
235 | out << ','; | |
236 | next = expression->next_; | |
237 | CYFlags right(next != NULL ? center : CYRight(flags)); | |
238 | expression->Output(out, right); | |
239 | } | |
240 | } else | |
241 | expression->Output(out, flags); | |
242 | } | |
243 | ||
244 | void CYExpression::Output(std::ostream &out, unsigned precedence, CYFlags flags) const { | |
245 | if (precedence < Precedence()) { | |
246 | out << '('; | |
247 | Output(out, CYNoFlags); | |
248 | out << ')'; | |
249 | } else | |
250 | Output(out, flags); | |
251 | } | |
252 | ||
253 | void CYField::Output(std::ostream &out) const { | |
254 | // XXX: implement! | |
255 | } | |
256 | ||
257 | void CYFor::Output(std::ostream &out) const { | |
258 | out << "for("; | |
259 | if (initialiser_ != NULL) | |
260 | initialiser_->Part(out); | |
261 | out << ';'; | |
262 | if (test_ != NULL) | |
263 | test_->Output(out, CYNoFlags); | |
264 | out << ';'; | |
265 | if (increment_ != NULL) | |
266 | increment_->Output(out, CYNoFlags); | |
267 | out << ')'; | |
268 | code_->Output(out, false); | |
269 | } | |
270 | ||
271 | void CYForIn::Output(std::ostream &out) const { | |
272 | out << "for("; | |
273 | initialiser_->Part(out); | |
274 | // XXX: deal with this space character! | |
275 | out << ' '; | |
276 | out << "in"; | |
277 | set_->Output(out, CYNoLeader); | |
278 | out << ')'; | |
279 | code_->Output(out, false); | |
280 | } | |
281 | ||
282 | void CYFunction::Output(std::ostream &out) const { | |
283 | CYLambda::Output(out, CYNoFlags); | |
284 | } | |
285 | ||
286 | void CYFunctionParameter::Output(std::ostream &out) const { | |
287 | out << *name_; | |
288 | if (next_ != NULL) { | |
289 | out << ','; | |
290 | out << *next_; | |
291 | } | |
292 | } | |
293 | ||
294 | void CYIf::Output(std::ostream &out) const { | |
295 | out << "if("; | |
296 | test_->Output(out, CYNoFlags); | |
297 | out << ')'; | |
298 | true_->Output(out, true); | |
299 | if (false_ != NULL) { | |
300 | out << "else "; | |
301 | false_->Output(out, false); | |
302 | } | |
303 | } | |
304 | ||
305 | void CYIndirect::Output(std::ostream &out, CYFlags flags) const { | |
306 | rhs_->Output(out, 1, CYLeft(flags)); | |
307 | out << "[0]"; | |
308 | } | |
309 | ||
310 | void CYInfix::Output(std::ostream &out, CYFlags flags) const { | |
311 | const char *name(Operator()); | |
312 | bool protect((flags & CYNoIn) != 0 && strcmp(name, "in")); | |
313 | if (protect) | |
314 | out << '('; | |
315 | bool alphabetic(Alphabetic()); | |
316 | CYFlags left(protect ? CYNoFlags : CYLeft(flags)); | |
317 | if (alphabetic) | |
318 | left |= CYNoTrailer; | |
319 | lhs_->Output(out, Precedence(), left); | |
320 | out << name; | |
321 | CYFlags right(protect ? CYNoFlags : CYRight(flags)); | |
322 | if (alphabetic) | |
323 | right |= CYNoLeader; | |
324 | rhs_->Output(out, Precedence() - 1, right); | |
325 | if (protect) | |
326 | out << ')'; | |
327 | } | |
328 | ||
329 | void CYLambda::Output(std::ostream &out, CYFlags flags) const { | |
330 | bool protect((flags & CYNoFunction) != 0); | |
331 | if (protect) | |
332 | out << '('; | |
333 | out << "function"; | |
334 | if (name_ != NULL) | |
335 | out << ' ' << *name_; | |
336 | out << '('; | |
337 | if (parameters_ != NULL) | |
338 | out << *parameters_; | |
339 | out << "){"; | |
340 | if (body_ != NULL) | |
341 | body_->Show(out); | |
342 | out << '}'; | |
343 | if (protect) | |
344 | out << ')'; | |
345 | } | |
346 | ||
347 | void CYMember::Output(std::ostream &out, CYFlags flags) const { | |
348 | object_->Output(out, Precedence(), CYLeft(flags)); | |
349 | if (const char *word = property_->Word()) | |
350 | out << '.' << word; | |
351 | else { | |
352 | out << '['; | |
353 | property_->Output(out, CYNoFlags); | |
354 | out << ']'; | |
355 | } | |
356 | } | |
357 | ||
358 | void CYMessage::Output(std::ostream &out) const { | |
359 | if (next_ != NULL) | |
360 | next_->Output(out); | |
361 | out << "$cyn=new Selector(\""; | |
362 | for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_) | |
363 | if (parameter->tag_ != NULL) { | |
364 | out << *parameter->tag_; | |
365 | if (parameter->name_ != NULL) | |
366 | out << ':'; | |
367 | } | |
368 | out << "\");"; | |
369 | out << "$cyt=$cyn.type($cys," << (instance_ ? "true" : "false") << ");"; | |
370 | out << "class_addMethod($cy" << (instance_ ? 'c' : 'm') << ",$cyn,"; | |
371 | out << "new Functor(function(self,_cmd"; | |
372 | for (CYMessageParameter *parameter(parameter_); parameter != NULL; parameter = parameter->next_) | |
373 | if (parameter->name_ != NULL) | |
374 | out << ',' << *parameter->name_; | |
375 | out << "){return function(){"; | |
376 | if (body_ != NULL) | |
377 | body_->Show(out); | |
378 | out << "}.call(self);},$cyt),$cyt);"; | |
379 | } | |
380 | ||
381 | void CYNew::Output(std::ostream &out, CYFlags flags) const { | |
382 | out << "new"; | |
383 | constructor_->Output(out, Precedence(), CYCenter(flags) | CYNoLeader); | |
384 | out << '('; | |
385 | if (arguments_ != NULL) | |
386 | arguments_->Output(out); | |
387 | out << ')'; | |
388 | } | |
389 | ||
390 | void CYNull::Output(std::ostream &out, CYFlags flags) const { | |
391 | if ((flags & CYNoLeader) != 0) | |
392 | out << ' '; | |
393 | CYWord::Output(out); | |
394 | if ((flags & CYNoTrailer) != 0) | |
395 | out << ' '; | |
396 | } | |
397 | ||
398 | void CYNumber::Output(std::ostream &out, CYFlags flags) const { | |
399 | if ((flags & CYNoLeader) != 0) | |
400 | out << ' '; | |
401 | // XXX: this is not a useful formatting | |
402 | out << Value(); | |
403 | if ((flags & CYNoTrailer) != 0) | |
404 | out << ' '; | |
405 | } | |
406 | ||
407 | void CYObject::Output(std::ostream &out, CYFlags flags) const { | |
408 | bool protect((flags & CYNoBrace) != 0); | |
409 | if (protect) | |
410 | out << '('; | |
411 | out << '{'; | |
412 | if (property_ != NULL) | |
413 | property_->Output(out); | |
414 | out << '}'; | |
415 | if (protect) | |
416 | out << ')'; | |
417 | } | |
418 | ||
419 | void CYPostfix::Output(std::ostream &out, CYFlags flags) const { | |
420 | lhs_->Output(out, Precedence(), CYLeft(flags)); | |
421 | out << Operator(); | |
422 | } | |
423 | ||
424 | void CYPrefix::Output(std::ostream &out, CYFlags flags) const { | |
425 | bool alphabetic(Alphabetic()); | |
426 | out << Operator(); | |
427 | CYFlags right(CYRight(flags)); | |
428 | if (alphabetic) | |
429 | right |= CYNoLeader; | |
430 | rhs_->Output(out, Precedence(), right); | |
431 | } | |
432 | ||
433 | void CYProperty::Output(std::ostream &out) const { | |
434 | out << *name_; | |
435 | out << ':'; | |
436 | value_->Output(out, CYPA, CYNoFlags); | |
437 | if (next_ != NULL) { | |
438 | out << ','; | |
439 | next_->Output(out); | |
440 | } | |
441 | } | |
442 | ||
443 | void CYReturn::Output(std::ostream &out) const { | |
444 | out << "return"; | |
445 | if (value_ != NULL) | |
446 | value_->Output(out, CYNoLeader); | |
447 | out << ';'; | |
448 | } | |
449 | ||
450 | void CYSelector::Output(std::ostream &out, CYFlags flags) const { | |
451 | out << "new Selector(\""; | |
452 | if (name_ != NULL) | |
453 | name_->Output(out); | |
454 | out << "\")"; | |
455 | } | |
456 | ||
457 | void CYSelectorPart::Output(std::ostream &out) const { | |
458 | if (name_ != NULL) | |
459 | out << *name_; | |
460 | if (value_) | |
461 | out << ':'; | |
462 | if (next_ != NULL) | |
463 | next_->Output(out); | |
464 | } | |
465 | ||
466 | void CYSend::Output(std::ostream &out, CYFlags flags) const { | |
467 | out << "objc_msgSend("; | |
468 | self_->Output(out, CYPA, CYNoFlags); | |
469 | out << ","; | |
470 | std::ostringstream name; | |
471 | for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) | |
472 | if (argument->name_ != NULL) { | |
473 | name << *argument->name_; | |
474 | if (argument->value_ != NULL) | |
475 | name << ':'; | |
476 | } | |
477 | out << reinterpret_cast<void *>(sel_registerName(name.str().c_str())); | |
478 | for (CYArgument *argument(arguments_); argument != NULL; argument = argument->next_) | |
479 | if (argument->value_ != NULL) { | |
480 | out << ","; | |
481 | argument->value_->Output(out, CYPA, CYNoFlags); | |
482 | } | |
483 | out << ')'; | |
484 | } | |
485 | ||
486 | void CYSource::Show(std::ostream &out) const { | |
487 | for (const CYSource *next(this); next != NULL; next = next->next_) | |
488 | next->Output(out); | |
489 | } | |
490 | ||
491 | void CYSource::Output(std::ostream &out, bool block) const { | |
492 | if (!block && next_ == NULL) | |
493 | Output(out); | |
494 | else { | |
495 | out << '{'; | |
496 | Show(out); | |
497 | out << '}'; | |
498 | } | |
499 | } | |
500 | ||
501 | void CYString::Output(std::ostream &out, CYFlags flags) const { | |
502 | unsigned quot(0), apos(0); | |
503 | for (const char *value(value_), *end(value_ + size_); value != end; ++value) | |
504 | if (*value == '"') | |
505 | ++quot; | |
506 | else if (*value == '\'') | |
507 | ++apos; | |
508 | ||
509 | bool single(quot > apos); | |
510 | ||
511 | out << (single ? '\'' : '"'); | |
512 | for (const char *value(value_), *end(value_ + size_); value != end; ++value) | |
513 | switch (*value) { | |
514 | case '\\': out << "\\\\"; break; | |
515 | case '\b': out << "\\b"; break; | |
516 | case '\f': out << "\\f"; break; | |
517 | case '\n': out << "\\n"; break; | |
518 | case '\r': out << "\\r"; break; | |
519 | case '\t': out << "\\t"; break; | |
520 | case '\v': out << "\\v"; break; | |
521 | ||
522 | case '"': | |
523 | if (!single) | |
524 | out << "\\\""; | |
525 | else goto simple; | |
526 | break; | |
527 | ||
528 | case '\'': | |
529 | if (single) | |
530 | out << "\\'"; | |
531 | else goto simple; | |
532 | break; | |
533 | ||
534 | default: | |
535 | if (*value < 0x20 || *value >= 0x7f) | |
536 | out << "\\x" << std::setbase(16) << std::setw(2) << std::setfill('0') << unsigned(*value); | |
537 | else simple: | |
538 | out << *value; | |
539 | } | |
540 | out << (single ? '\'' : '"'); | |
541 | } | |
542 | ||
543 | void CYSwitch::Output(std::ostream &out) const { | |
544 | out << "switch("; | |
545 | value_->Output(out, CYNoFlags); | |
546 | out << "){"; | |
547 | if (clauses_ != NULL) | |
548 | out << *clauses_; | |
549 | out << '}'; | |
550 | } | |
551 | ||
552 | void CYThis::Output(std::ostream &out, CYFlags flags) const { | |
553 | if ((flags & CYNoLeader) != 0) | |
554 | out << ' '; | |
555 | CYWord::Output(out); | |
556 | if ((flags & CYNoTrailer) != 0) | |
557 | out << ' '; | |
558 | } | |
559 | ||
560 | void CYThrow::Output(std::ostream &out) const { | |
561 | out << "throw"; | |
562 | if (value_ != NULL) | |
563 | value_->Output(out, CYNoLeader); | |
564 | out << ';'; | |
565 | } | |
566 | ||
567 | void CYTry::Output(std::ostream &out) const { | |
568 | out << "try"; | |
569 | try_->Output(out, true); | |
570 | if (catch_ != NULL) | |
571 | out << catch_; | |
572 | if (finally_ != NULL) { | |
573 | out << "finally"; | |
574 | finally_->Output(out, true); | |
575 | } | |
576 | } | |
577 | ||
578 | void CYVariable::Output(std::ostream &out, CYFlags flags) const { | |
579 | if ((flags & CYNoLeader) != 0) | |
580 | out << ' '; | |
581 | out << *name_; | |
582 | if ((flags & CYNoTrailer) != 0) | |
583 | out << ' '; | |
584 | } | |
585 | ||
586 | void CYWhile::Output(std::ostream &out) const { | |
587 | out << "while("; | |
588 | test_->Output(out, CYNoFlags); | |
589 | out << ')'; | |
590 | code_->Output(out, false); | |
591 | } | |
592 | ||
593 | void CYWith::Output(std::ostream &out) const { | |
594 | out << "with("; | |
595 | scope_->Output(out, CYNoFlags); | |
596 | out << ')'; | |
597 | code_->Output(out, false); | |
598 | } | |
599 | ||
600 | void CYWord::Output(std::ostream &out) const { | |
601 | out << Value(); | |
602 | } |