]> git.saurik.com Git - cycript.git/blame - Output.cpp
The grammar and lexer should not share a filename.
[cycript.git] / Output.cpp
CommitLineData
b3378a02 1/* Cycript - Optimizing JavaScript Compiler/Runtime
c1d3e52e 2 * Copyright (C) 2009-2015 Jay Freeman (saurik)
4644480a
JF
3*/
4
f95d2598 5/* GNU Affero General Public License, Version 3 {{{ */
4644480a 6/*
f95d2598
JF
7 * This program is free software: you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation, either version 3 of the License, or
10 * (at your option) any later version.
11
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
c15969fd 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
f95d2598
JF
15 * GNU Affero General Public License for more details.
16
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
b3378a02 19**/
4644480a
JF
20/* }}} */
21
520c130f 22#include "cycript.hpp"
5999c315 23
4afefdd9
JF
24#include <sstream>
25
20052ff7
JF
26#include "Syntax.hpp"
27
1fdca2fa 28void CYOutput::Terminate() {
efd689d8 29 operator ()(';');
1fdca2fa
JF
30 mode_ = NoMode;
31}
32
96a7e5c2 33CYOutput &CYOutput::operator <<(char rhs) {
1fdca2fa
JF
34 if (rhs == ' ' || rhs == '\n')
35 if (pretty_)
efd689d8 36 operator ()(rhs);
1fdca2fa
JF
37 else goto done;
38 else if (rhs == '\t')
39 if (pretty_)
40 for (unsigned i(0); i != indent_; ++i)
efd689d8 41 operator ()(" ", 4);
1fdca2fa 42 else goto done;
320ce753
JF
43 else if (rhs == '\r') {
44 if (right_) {
efd689d8 45 operator ()('\n');
320ce753 46 right_ = false;
14ec9e00 47 } goto done;
320ce753 48 } else goto work;
1fdca2fa 49
320ce753 50 right_ = true;
1fdca2fa
JF
51 mode_ = NoMode;
52 goto done;
96a7e5c2 53
1fdca2fa 54 work:
320ce753
JF
55 if (mode_ == Terminated && rhs != '}') {
56 right_ = true;
efd689d8 57 operator ()(';');
320ce753 58 }
96a7e5c2
JF
59
60 if (rhs == ';') {
61 if (pretty_)
62 goto none;
63 else {
64 mode_ = Terminated;
65 goto done;
66 }
c0bc320e
JF
67 } else if (rhs == '+') {
68 if (mode_ == NoPlus)
efd689d8 69 operator ()(' ');
c0bc320e 70 mode_ = NoPlus;
96a7e5c2
JF
71 } else if (rhs == '-') {
72 if (mode_ == NoHyphen)
efd689d8 73 operator ()(' ');
96a7e5c2
JF
74 mode_ = NoHyphen;
75 } else if (WordEndRange_[rhs]) {
76 if (mode_ == NoLetter)
efd689d8 77 operator ()(' ');
96a7e5c2
JF
78 mode_ = NoLetter;
79 } else none:
80 mode_ = NoMode;
81
320ce753 82 right_ = true;
efd689d8 83 operator ()(rhs);
96a7e5c2
JF
84 done:
85 return *this;
86}
87
88CYOutput &CYOutput::operator <<(const char *rhs) {
89 size_t size(strlen(rhs));
90
91 if (size == 1)
92 return *this << *rhs;
93
94 if (mode_ == Terminated)
efd689d8 95 operator ()(';');
96a7e5c2 96 else if (
c0bc320e 97 mode_ == NoPlus && *rhs == '+' ||
96a7e5c2
JF
98 mode_ == NoHyphen && *rhs == '-' ||
99 mode_ == NoLetter && WordEndRange_[*rhs]
100 )
efd689d8 101 operator ()(' ');
96a7e5c2 102
0482072a
JF
103 char last(rhs[size - 1]);
104 if (WordEndRange_[last] || last == '/')
96a7e5c2
JF
105 mode_ = NoLetter;
106 else
107 mode_ = NoMode;
108
320ce753 109 right_ = true;
efd689d8 110 operator ()(rhs, size);
96a7e5c2
JF
111 return *this;
112}
113
652ec1ba 114void 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)
8351aa30 121 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
5999c315 122 if (next_ != NULL) {
068fc9b8 123 out << ',';
96a7e5c2 124 out << ' ' << *next_;
5999c315
JF
125 }
126}
127
652ec1ba 128void CYArray::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 129 out << '[' << elements_ << ']';
5befe15e
JF
130}
131
652ec1ba 132void CYArrayComprehension::Output(CYOutput &out, CYFlags flags) const {
4644480a 133 out << '[' << *expression_ << ' ' << *comprehensions_ << ']';
75b0a457
JF
134}
135
652ec1ba 136void CYAssignment::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 137 lhs_->Output(out, Precedence() - 1, CYLeft(flags) | CYNoRightHand);
96a7e5c2 138 out << ' ' << Operator() << ' ';
b09da87b 139 rhs_->Output(out, Precedence(), CYRight(flags));
d35a3b07
JF
140}
141
b0385401 142void CYBlock::Output(CYOutput &out, CYFlags flags) const {
3b52fd1a
JF
143 out << '{' << '\n';
144 ++out.indent_;
b0385401 145 out << code_;
3b52fd1a
JF
146 --out.indent_;
147 out << '\t' << '}';
148}
149
652ec1ba 150void CYBoolean::Output(CYOutput &out, CYFlags flags) const {
76284c74
JF
151 out << '!' << (Value() ? "0" : "1");
152 if ((flags & CYNoInteger) != 0)
153 out << '.';
5999c315
JF
154}
155
fb98ac0c 156void CYBreak::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
157 out << "break";
158 if (label_ != NULL)
159 out << ' ' << *label_;
96a7e5c2 160 out << ';';
5999c315
JF
161}
162
652ec1ba 163void CYCall::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c
JF
164 bool protect((flags & CYNoCall) != 0);
165 if (protect)
166 out << '(';
167 function_->Output(out, Precedence(), protect ? CYNoFlags : flags);
96a7e5c2 168 out << '(' << arguments_ << ')';
fb98ac0c
JF
169 if (protect)
170 out << ')';
5999c315
JF
171}
172
37954781
JF
173namespace cy {
174namespace Syntax {
175
176void Catch::Output(CYOutput &out) const {
b0385401
JF
177 out << ' ' << "catch" << ' ' << '(' << *name_ << ')' << ' ';
178 out << '{' << '\n';
179 ++out.indent_;
180 out << code_;
181 --out.indent_;
182 out << '\t' << '}';
5999c315
JF
183}
184
37954781
JF
185} }
186
652ec1ba 187void CYCompound::Output(CYOutput &out, CYFlags flags) const {
fd5cdf97
JF
188 if (next_ == NULL)
189 expression_->Output(out, flags);
190 else {
191 expression_->Output(out, CYLeft(flags));
192 out << ',' << ' ';
193 next_->Output(out, CYRight(flags));
194 }
e5bc40db
JF
195}
196
652ec1ba 197void CYCondition::Output(CYOutput &out, CYFlags flags) const {
b09da87b 198 test_->Output(out, Precedence() - 1, CYLeft(flags));
96a7e5c2 199 out << ' ' << '?' << ' ';
5999c315 200 if (true_ != NULL)
8351aa30 201 true_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 202 out << ' ' << ':' << ' ';
8351aa30 203 false_->Output(out, CYAssign::Precedence_, CYRight(flags));
5999c315
JF
204}
205
fb98ac0c 206void CYContinue::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
207 out << "continue";
208 if (label_ != NULL)
209 out << ' ' << *label_;
96a7e5c2 210 out << ';';
5999c315
JF
211}
212
652ec1ba 213void CYClause::Output(CYOutput &out) const {
efd689d8 214 out << '\t';
96a7e5c2
JF
215 if (case_ != NULL)
216 out << "case" << ' ' << *case_;
217 else
5999c315 218 out << "default";
1fdca2fa 219 out << ':' << '\n';
efd689d8 220 ++out.indent_;
b0385401 221 out << code_;
efd689d8 222 --out.indent_;
96a7e5c2 223 out << next_;
cac61857
JF
224}
225
c8a0500b
JF
226void CYDebugger::Output(CYOutput &out, CYFlags flags) const {
227 out << "debugger" << ';';
228}
229
652ec1ba 230void CYDeclaration::ForIn(CYOutput &out, CYFlags flags) const {
efd689d8 231 out << "var" << ' ';
96a7e5c2 232 Output(out, CYRight(flags));
75b0a457
JF
233}
234
652ec1ba 235void CYDeclaration::Output(CYOutput &out, CYFlags flags) const {
5999c315 236 out << *identifier_;
e013809d 237 //out.out_ << ':' << identifier_->usage_ << '#' << identifier_->offset_;
d35a3b07 238 if (initialiser_ != NULL) {
96a7e5c2 239 out << ' ' << '=' << ' ';
8351aa30 240 initialiser_->Output(out, CYAssign::Precedence_, CYRight(flags));
96a7e5c2 241 }
5999c315
JF
242}
243
15b88a33 244void CYForDeclarations::Output(CYOutput &out, CYFlags flags) const {
efd689d8 245 out << "var" << ' ';
bf1fd02c 246 declarations_->Output(out, CYRight(flags));
96a7e5c2
JF
247}
248
249void CYDeclarations::Output(CYOutput &out) const {
250 Output(out, CYNoFlags);
cac61857 251}
d35a3b07 252
652ec1ba 253void CYDeclarations::Output(CYOutput &out, CYFlags flags) const {
5999c315 254 const CYDeclarations *declaration(this);
fb98ac0c 255 bool first(true);
d35a3b07 256
c8a0500b
JF
257 for (;;) {
258 CYDeclarations *next(declaration->next_);
259
260 CYFlags jacks(first ? CYLeft(flags) : next == NULL ? CYRight(flags) : CYCenter(flags));
261 first = false;
262 declaration->declaration_->Output(out, jacks);
263
264 if (next == NULL)
265 break;
266
96a7e5c2 267 out << ',' << ' ';
75b0a457 268 declaration = next;
d35a3b07 269 }
5999c315
JF
270}
271
652ec1ba 272void CYDirectMember::Output(CYOutput &out, CYFlags flags) const {
b38adb44 273 object_->Output(out, Precedence(), CYLeft(flags) | CYNoInteger);
9b5527f0
JF
274 if (const char *word = property_->Word())
275 out << '.' << word;
96a7e5c2
JF
276 else
277 out << '[' << *property_ << ']';
9b5527f0
JF
278}
279
fb98ac0c 280void CYDoWhile::Output(CYOutput &out, CYFlags flags) const {
fb98ac0c 281 out << "do";
efd689d8
JF
282
283 unsigned line(out.position_.line);
284 unsigned indent(out.indent_);
285 code_->Single(out, CYCenter(flags), CYCompactLong);
286
287 if (out.position_.line != line && out.recent_ == indent)
288 out << ' ';
289 else
290 out << '\n' << '\t';
291
96a7e5c2 292 out << "while" << ' ' << '(' << *test_ << ')';
5999c315
JF
293}
294
fc8fc33d
JF
295void CYElementSpread::Output(CYOutput &out) const {
296 out << "..." << value_;
297}
298
299void CYElementValue::Output(CYOutput &out) const {
5999c315 300 if (value_ != NULL)
8351aa30 301 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
11c1cc16 302 if (next_ != NULL || value_ == NULL) {
5999c315 303 out << ',';
fc8fc33d 304 if (next_ != NULL && !next_->Elision())
11c1cc16
JF
305 out << ' ';
306 }
5befe15e
JF
307 if (next_ != NULL)
308 next_->Output(out);
5999c315
JF
309}
310
fb98ac0c 311void CYEmpty::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 312 out.Terminate();
5999c315
JF
313}
314
fb98ac0c 315void CYExpress::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2
JF
316 expression_->Output(out, flags | CYNoBF);
317 out << ';';
5999c315
JF
318}
319
652ec1ba 320void CYExpression::ClassName(CYOutput &out, bool object) const {
8351aa30 321 Output(out, CYAssign::Precedence_, CYNoFlags);
e5bc40db
JF
322}
323
652ec1ba 324void CYExpression::ForIn(CYOutput &out, CYFlags flags) const {
fb98ac0c 325 Output(out, flags | CYNoRightHand);
d35a3b07
JF
326}
327
96a7e5c2
JF
328void CYExpression::Output(CYOutput &out) const {
329 Output(out, CYNoFlags);
330}
331
9a39f705 332void CYExpression::Output(CYOutput &out, int precedence, CYFlags flags) const {
96a7e5c2
JF
333 if (precedence < Precedence() || (flags & CYNoRightHand) != 0 && RightHand())
334 out << '(' << *this << ')';
335 else
b09da87b
JF
336 Output(out, flags);
337}
338
c5587ed7
JF
339void CYExternal::Output(CYOutput &out, CYFlags flags) const {
340 out << "extern" << abi_ << typed_ << ';';
341}
342
a0be43fc 343void CYFatArrow::Output(CYOutput &out, CYFlags flags) const {
b0385401 344 out << '(' << parameters_ << ')' << ' ' << "=>" << ' ' << '{' << code_ << '}';
a0be43fc
JF
345}
346
b10bd496 347void CYFinally::Output(CYOutput &out) const {
b0385401
JF
348 out << ' ' << "finally" << ' ';
349 out << '{' << '\n';
350 ++out.indent_;
351 out << code_;
352 --out.indent_;
353 out << '\t' << '}';
b10bd496
JF
354}
355
fb98ac0c 356void CYFor::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 357 out << "for" << ' ' << '(';
5999c315 358 if (initialiser_ != NULL)
15b88a33 359 initialiser_->Output(out, CYNoIn);
1fdca2fa 360 out.Terminate();
e661185c
JF
361 if (test_ != NULL)
362 out << ' ';
96a7e5c2 363 out << test_;
1fdca2fa 364 out.Terminate();
e661185c
JF
365 if (increment_ != NULL)
366 out << ' ';
96a7e5c2 367 out << increment_;
5999c315 368 out << ')';
efd689d8 369 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315
JF
370}
371
d5618df7 372void CYForOf::Output(CYOutput &out, CYFlags flags) const {
4644480a
JF
373 out << "for" << ' ' << "each" << ' ' << '(';
374 initialiser_->ForIn(out, CYNoIn);
efd689d8
JF
375 out << ' ' << "in" << ' ' << *set_ << ')';
376 code_->Single(out, CYRight(flags), CYCompactShort);
75b0a457
JF
377}
378
d5618df7 379void CYForOfComprehension::Output(CYOutput &out) const {
4644480a 380 out << "for" << ' ' << "each" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')' << next_;
75b0a457
JF
381}
382
fb98ac0c 383void CYForIn::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 384 out << "for" << ' ' << '(';
029bc65b
JF
385 if (initialiser_ != NULL)
386 initialiser_->ForIn(out, CYNoIn);
efd689d8
JF
387 out << ' ' << "in" << ' ' << *set_ << ')';
388 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315
JF
389}
390
4644480a
JF
391void CYForInComprehension::Output(CYOutput &out) const {
392 out << "for" << ' ' << '(' << *name_ << ' ' << "in" << ' ' << *set_ << ')';
75b0a457
JF
393}
394
fb98ac0c 395void CYFunction::Output(CYOutput &out, CYFlags flags) const {
1fdca2fa 396 // XXX: one could imagine using + here to save a byte
fb98ac0c
JF
397 bool protect((flags & CYNoFunction) != 0);
398 if (protect)
399 out << '(';
fb98ac0c
JF
400 out << "function";
401 if (name_ != NULL)
402 out << ' ' << *name_;
b0385401
JF
403 out << '(' << parameters_ << ')' << ' ';
404 out << '{' << '\n';
405 ++out.indent_;
406 out << code_;
407 --out.indent_;
408 out << '\t' << '}';
fb98ac0c
JF
409 if (protect)
410 out << ')';
411}
412
413void CYFunctionExpression::Output(CYOutput &out, CYFlags flags) const {
414 CYFunction::Output(out, flags);
415}
416
417void CYFunctionStatement::Output(CYOutput &out, CYFlags flags) const {
418 CYFunction::Output(out, flags);
b09da87b
JF
419}
420
652ec1ba 421void CYFunctionParameter::Output(CYOutput &out) const {
c8a0500b 422 initialiser_->Output(out, CYNoFlags);
96a7e5c2
JF
423 if (next_ != NULL)
424 out << ',' << ' ' << *next_;
5999c315
JF
425}
426
029bc65b
JF
427const char *CYIdentifier::Word() const {
428 return replace_ == NULL || replace_ == this ? CYWord::Word() : replace_->Word();
429}
430
fb98ac0c
JF
431void CYIf::Output(CYOutput &out, CYFlags flags) const {
432 bool protect(false);
433 if (false_ == NULL && (flags & CYNoDangle) != 0) {
434 protect = true;
435 out << '{';
96a7e5c2 436 }
1fdca2fa
JF
437
438 out << "if" << ' ' << '(' << *test_ << ')';
439
fb98ac0c 440 CYFlags right(protect ? CYNoFlags : CYRight(flags));
d29365ce 441
fb98ac0c 442 CYFlags jacks(CYNoDangle);
96a7e5c2
JF
443 if (false_ == NULL)
444 jacks |= right;
d29365ce
JF
445 else
446 jacks |= protect ? CYNoFlags : CYCenter(flags);
1fdca2fa 447
efd689d8
JF
448 unsigned line(out.position_.line);
449 unsigned indent(out.indent_);
450 true_->Single(out, jacks, CYCompactShort);
1fdca2fa 451
5999c315 452 if (false_ != NULL) {
efd689d8
JF
453 if (out.position_.line != line && out.recent_ == indent)
454 out << ' ';
455 else
456 out << '\n' << '\t';
457
458 out << "else";
459 false_->Single(out, right, CYCompactLong);
5999c315 460 }
1fdca2fa 461
fb98ac0c
JF
462 if (protect)
463 out << '}';
5999c315
JF
464}
465
4644480a
JF
466void CYIfComprehension::Output(CYOutput &out) const {
467 out << "if" << ' ' << '(' << *test_ << ')' << next_;
75b0a457
JF
468}
469
7b750785
JF
470void CYImport::Output(CYOutput &out, CYFlags flags) const {
471 out << "@import";
472}
473
652ec1ba 474void CYIndirectMember::Output(CYOutput &out, CYFlags flags) const {
9b5527f0 475 object_->Output(out, Precedence(), CYLeft(flags));
9b5527f0 476 if (const char *word = property_->Word())
3b52fd1a 477 out << "->" << word;
96a7e5c2 478 else
3b52fd1a 479 out << "->" << '[' << *property_ << ']';
5999c315
JF
480}
481
652ec1ba 482void CYInfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 483 const char *name(Operator());
d09e527c 484 bool protect((flags & CYNoIn) != 0 && strcmp(name, "in") == 0);
b09da87b
JF
485 if (protect)
486 out << '(';
b09da87b 487 CYFlags left(protect ? CYNoFlags : CYLeft(flags));
b09da87b 488 lhs_->Output(out, Precedence(), left);
96a7e5c2 489 out << ' ' << name << ' ';
b09da87b 490 CYFlags right(protect ? CYNoFlags : CYRight(flags));
b09da87b
JF
491 rhs_->Output(out, Precedence() - 1, right);
492 if (protect)
493 out << ')';
5999c315
JF
494}
495
3b52fd1a 496void CYLabel::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
497 out << *name_ << ':';
498 statement_->Single(out, CYRight(flags), CYCompactShort);
3b52fd1a
JF
499}
500
b0385401
JF
501void CYParenthetical::Output(CYOutput &out, CYFlags flags) const {
502 out << '(';
503 expression_->Output(out, CYCompound::Precedence_, CYNoFlags);
504 out << ')';
505}
506
507void CYStatement::Output(CYOutput &out) const {
508 Multiple(out);
509}
510
b900e1a4
JF
511void CYTemplate::Output(CYOutput &out, CYFlags flags) const {
512 _assert(false);
513}
514
9a39f705
JF
515void CYTypeArrayOf::Output(CYOutput &out, CYIdentifier *identifier) const {
516 next_->Output(out, Precedence(), identifier);
517 out << '[';
518 out << size_;
519 out << ']';
520}
521
3fe16be7
JF
522void CYTypeBlockWith::Output(CYOutput &out, CYIdentifier *identifier) const {
523 out << '(' << '^';
524 next_->Output(out, Precedence(), identifier);
525 out << ')' << '(' << parameters_ << ')';
526}
527
9a39f705 528void CYTypeConstant::Output(CYOutput &out, CYIdentifier *identifier) const {
efd689d8 529 out << "const" << ' ';
9a39f705
JF
530 next_->Output(out, Precedence(), identifier);
531}
532
533void CYTypeFunctionWith::Output(CYOutput &out, CYIdentifier *identifier) const {
534 next_->Output(out, Precedence(), identifier);
535 out << '(' << parameters_ << ')';
536}
537
538void CYTypePointerTo::Output(CYOutput &out, CYIdentifier *identifier) const {
539 out << '*';
540 next_->Output(out, Precedence(), identifier);
541}
542
543void CYTypeVolatile::Output(CYOutput &out, CYIdentifier *identifier) const {
544 out << "volatile";
545 next_->Output(out, Precedence(), identifier);
546}
547
548void CYTypeModifier::Output(CYOutput &out, int precedence, CYIdentifier *identifier) const {
549 if (this == NULL) {
550 out << identifier;
551 return;
552 }
553
554 bool protect(precedence > Precedence());
555
556 if (protect)
557 out << '(';
558 Output(out, identifier);
559 if (protect)
560 out << ')';
561}
562
60097023 563void CYTypedIdentifier::Output(CYOutput &out) const {
3fe283c5 564 specifier_->Output(out);
9a39f705
JF
565 modifier_->Output(out, 0, identifier_);
566}
567
568void CYEncodedType::Output(CYOutput &out, CYFlags flags) const {
569 out << "@encode(" << typed_ << ")";
570}
571
572void CYTypedParameter::Output(CYOutput &out) const {
573 out << typed_;
574 if (next_ != NULL)
575 out << ',' << ' ' << next_;
60097023
JF
576}
577
690cf1a8
JF
578void CYLambda::Output(CYOutput &out, CYFlags flags) const {
579 // XXX: this is seriously wrong
580 out << "[](";
581 out << ")->";
582 out << "{";
583 out << "}";
584}
585
60097023 586void CYTypeDefinition::Output(CYOutput &out, CYFlags flags) const {
efd689d8 587 out << "typedef" << ' ' << *typed_;
60097023
JF
588}
589
c8a0500b 590void CYLetStatement::Output(CYOutput &out, CYFlags flags) const {
15b88a33 591 out << "let" << ' ' << '(' << *declarations_ << ')';
efd689d8 592 code_->Single(out, CYRight(flags), CYCompactShort);
cac61857
JF
593}
594
7b750785
JF
595void CYModule::Output(CYOutput &out) const {
596 out << part_;
597 if (next_ != NULL)
598 out << '.' << next_;
599}
600
2eb8215d
JF
601namespace cy {
602namespace Syntax {
603
604void New::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 605 out << "new" << ' ';
11c1cc16 606 CYFlags jacks(CYNoCall | CYCenter(flags));
11c1cc16 607 constructor_->Output(out, Precedence(), jacks);
96a7e5c2
JF
608 if (arguments_ != NULL)
609 out << '(' << *arguments_ << ')';
5999c315
JF
610}
611
2eb8215d
JF
612} }
613
652ec1ba 614void CYNull::Output(CYOutput &out, CYFlags flags) const {
8f56307d 615 out << "null";
5999c315
JF
616}
617
652ec1ba 618void CYNumber::Output(CYOutput &out, CYFlags flags) const {
856b8cd0
JF
619 std::ostringstream str;
620 CYNumerify(str, Value());
9561f209
JF
621 std::string value(str.str());
622 out << value.c_str();
623 // XXX: this should probably also handle hex conversions and exponents
624 if ((flags & CYNoInteger) != 0 && value.find('.') == std::string::npos)
625 out << '.';
5999c315
JF
626}
627
652ec1ba 628void CYNumber::PropertyName(CYOutput &out) const {
fb98ac0c 629 Output(out, CYNoFlags);
e5bc40db
JF
630}
631
652ec1ba 632void CYObject::Output(CYOutput &out, CYFlags flags) const {
b09da87b
JF
633 bool protect((flags & CYNoBrace) != 0);
634 if (protect)
635 out << '(';
c0bc320e
JF
636 out << '{' << '\n';
637 ++out.indent_;
3b52fd1a 638 out << properties_;
c0bc320e
JF
639 --out.indent_;
640 out << '\t' << '}';
b09da87b
JF
641 if (protect)
642 out << ')';
693d501b
JF
643}
644
652ec1ba 645void CYPostfix::Output(CYOutput &out, CYFlags flags) const {
b09da87b 646 lhs_->Output(out, Precedence(), CYLeft(flags));
d35a3b07 647 out << Operator();
5999c315
JF
648}
649
652ec1ba 650void CYPrefix::Output(CYOutput &out, CYFlags flags) const {
1ef7d061 651 const char *name(Operator());
1ef7d061 652 out << name;
96a7e5c2 653 if (Alphabetic())
11c1cc16 654 out << ' ';
96a7e5c2 655 rhs_->Output(out, Precedence(), CYRight(flags));
5999c315
JF
656}
657
a7d8b413 658void CYScript::Output(CYOutput &out) const {
b0385401 659 out << code_;
3b52fd1a
JF
660}
661
652ec1ba 662void CYProperty::Output(CYOutput &out) const {
c0bc320e 663 out << '\t';
e5bc40db 664 name_->PropertyName(out);
96a7e5c2 665 out << ':' << ' ';
8351aa30 666 value_->Output(out, CYAssign::Precedence_, CYNoFlags);
96a7e5c2 667 if (next_ != NULL)
c0bc320e
JF
668 out << ',' << '\n' << *next_;
669 else
670 out << '\n';
5999c315
JF
671}
672
63cd45c9
JF
673void CYRegEx::Output(CYOutput &out, CYFlags flags) const {
674 out << Value();
63cd45c9
JF
675}
676
fb98ac0c 677void CYReturn::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
678 out << "return";
679 if (value_ != NULL)
680 out << ' ' << *value_;
681 out << ';';
5999c315
JF
682}
683
6c093cce
JF
684void CYRubyBlock::Output(CYOutput &out, CYFlags flags) const {
685 call_->Output(out, CYLeft(flags));
686 out << ' ';
687 proc_->Output(out, CYRight(flags));
688}
689
690void CYRubyProc::Output(CYOutput &out, CYFlags flags) const {
0da459fc 691 out << '{' << ' ' << '|' << parameters_ << '|' << '\n';
b0385401 692 ++out.indent_;
6c093cce 693 out << code_;
b0385401
JF
694 --out.indent_;
695 out << '\t' << '}';
6c093cce
JF
696}
697
fb98ac0c
JF
698void CYStatement::Multiple(CYOutput &out, CYFlags flags) const {
699 bool first(true);
c2c9f509 700 CYForEach (next, this) {
fb98ac0c 701 bool last(next->next_ == NULL);
7bf4a0cd 702 CYFlags jacks(first ? last ? flags : CYLeft(flags) : last ? CYRight(flags) : CYCenter(flags));
fb98ac0c 703 first = false;
1fdca2fa 704 out << '\t';
fb98ac0c 705 next->Output(out, jacks);
1fdca2fa 706 out << '\n';
fb98ac0c 707 }
5999c315
JF
708}
709
efd689d8 710void CYStatement::Single(CYOutput &out, CYFlags flags, CYCompactType request) const {
0f37eca9
JF
711 if (this == NULL)
712 return out.Terminate();
713
3b52fd1a 714 _assert(next_ == NULL);
efd689d8
JF
715
716 CYCompactType compact(Compact());
717
718 if (compact >= request)
719 out << ' ';
720 else {
721 out << '\n';
722 ++out.indent_;
723 out << '\t';
724 }
725
3b52fd1a 726 Output(out, flags);
efd689d8
JF
727
728 if (compact < request)
729 --out.indent_;
5999c315
JF
730}
731
652ec1ba 732void CYString::Output(CYOutput &out, CYFlags flags) const {
96a7e5c2 733 std::ostringstream str;
520c130f 734 CYStringify(str, value_, size_);
96a7e5c2 735 out << str.str().c_str();
5999c315
JF
736}
737
652ec1ba 738void CYString::PropertyName(CYOutput &out) const {
e5bc40db
JF
739 if (const char *word = Word())
740 out << word;
741 else
96a7e5c2 742 out << *this;
e5bc40db
JF
743}
744
c0bc320e
JF
745static const char *Reserved_[] = {
746 "false", "null", "true",
747
748 "break", "case", "catch", "continue", "default",
749 "delete", "do", "else", "finally", "for", "function",
750 "if", "in", "instanceof", "new", "return", "switch",
751 "this", "throw", "try", "typeof", "var", "void",
752 "while", "with",
753
754 "debugger", "const",
755
756 "class", "enum", "export", "extends", "import", "super",
757
758 "abstract", "boolean", "byte", "char", "double", "final",
759 "float", "goto", "int", "long", "native", "short",
760 "synchronized", "throws", "transient", "volatile",
761
762 "let", "yield",
763
c0bc320e
JF
764 NULL
765};
766
11c1cc16
JF
767const char *CYString::Word() const {
768 if (size_ == 0 || !WordStartRange_[value_[0]])
769 return NULL;
770 for (size_t i(1); i != size_; ++i)
771 if (!WordEndRange_[value_[i]])
772 return NULL;
773 const char *value(Value());
c0bc320e 774 for (const char **reserved(Reserved_); *reserved != NULL; ++reserved)
11c1cc16
JF
775 if (strcmp(*reserved, value) == 0)
776 return NULL;
777 return value;
778}
779
fb98ac0c 780void CYSwitch::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
781 out << "switch" << ' ' << '(' << *value_ << ')' << ' ' << '{' << '\n';
782 ++out.indent_;
96a7e5c2 783 out << clauses_;
efd689d8
JF
784 --out.indent_;
785 out << '\t' << '}';
5999c315
JF
786}
787
652ec1ba 788void CYThis::Output(CYOutput &out, CYFlags flags) const {
8f56307d 789 out << "this";
5999c315
JF
790}
791
37954781
JF
792namespace cy {
793namespace Syntax {
794
795void Throw::Output(CYOutput &out, CYFlags flags) const {
c0bc320e
JF
796 out << "throw";
797 if (value_ != NULL)
798 out << ' ' << *value_;
799 out << ';';
5999c315
JF
800}
801
37954781 802void Try::Output(CYOutput &out, CYFlags flags) const {
b0385401
JF
803 out << "try" << ' ';
804 out << '{' << '\n';
805 ++out.indent_;
806 out << code_;
807 --out.indent_;
808 out << '\t' << '}';
809 out << catch_ << finally_;
5999c315
JF
810}
811
37954781
JF
812} }
813
03db6a67
JF
814void CYTypeError::Output(CYOutput &out) const {
815 out << "@error";
816}
817
3fe283c5
JF
818void CYTypeLong::Output(CYOutput &out) const {
819 out << "long" << specifier_;
820}
821
822void CYTypeShort::Output(CYOutput &out) const {
823 out << "short" << specifier_;
824}
825
826void CYTypeSigned::Output(CYOutput &out) const {
827 out << "signed" << specifier_;
828}
829
830void CYTypeUnsigned::Output(CYOutput &out) const {
831 out << "unsigned" << specifier_;
832}
833
834void CYTypeVariable::Output(CYOutput &out) const {
835 out << *name_;
836}
837
838void CYTypeVoid::Output(CYOutput &out) const {
839 out << "void";
840}
841
fb98ac0c 842void CYVar::Output(CYOutput &out, CYFlags flags) const {
efd689d8 843 out << "var" << ' ';
96a7e5c2
JF
844 declarations_->Output(out, flags);
845 out << ';';
cac61857
JF
846}
847
652ec1ba 848void CYVariable::Output(CYOutput &out, CYFlags flags) const {
5999c315
JF
849 out << *name_;
850}
851
fb98ac0c 852void CYWhile::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
853 out << "while" << ' ' << '(' << *test_ << ')';
854 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315
JF
855}
856
fb98ac0c 857void CYWith::Output(CYOutput &out, CYFlags flags) const {
efd689d8
JF
858 out << "with" << ' ' << '(' << *scope_ << ')';
859 code_->Single(out, CYRight(flags), CYCompactShort);
5999c315
JF
860}
861
652ec1ba 862void CYWord::ClassName(CYOutput &out, bool object) const {
367eebb1
JF
863 if (object)
864 out << "objc_getClass(";
029bc65b 865 out << '"' << Word() << '"';
367eebb1
JF
866 if (object)
867 out << ')';
e5bc40db
JF
868}
869
652ec1ba 870void CYWord::Output(CYOutput &out) const {
029bc65b 871 out << Word();
efd689d8
JF
872 if (out.options_.verbose_) {
873 out('@');
874 char number[32];
875 sprintf(number, "%p", this);
876 out(number);
877 }
5999c315 878}
e5bc40db 879
652ec1ba 880void CYWord::PropertyName(CYOutput &out) const {
e5bc40db
JF
881 Output(out);
882}
029bc65b
JF
883
884const char *CYWord::Word() const {
885 return word_;
886}