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