source: webkit/trunk/JavaScriptCore/kjs/nodes2string.cpp@ 29804

Last change on this file since 29804 was 29804, checked in by Darin Adler, 17 years ago

JavaScriptCore:

Reviewed by Oliver.

Test: fast/js/toString-for-var-decl.html

  • kjs/nodes.h: Added PlaceholderTrueNode so we can put nodes into for loops without injecting the word "true" into them (nice, but not the bug fix). Fixed ForNode constructor so expr1WasVarDecl is set only when there is an expression, since it's common for the actual variable declaration to be moved by the parser.
  • kjs/nodes2string.cpp: (KJS::PlaceholderTrueNode::streamTo): Added. Empty.

LayoutTests:

Reviewed by Oliver.

  • fast/js/resources/toString-for-var-decl.js: Streamlined the test a bit, with more of the execution within shouldBe so that exceptions are caught for us. Added a new test case reflecting the just-fixed bug.
  • fast/js/toString-for-var-decl-expected.txt: Updated.
  • Property svn:eol-style set to native
File size: 22.2 KB
Line 
1/*
2 * Copyright (C) 2002 Harri Porten ([email protected])
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Eric Seidel <[email protected]>
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Library General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Library General Public License for more details.
15 *
16 * You should have received a copy of the GNU Library General Public License
17 * along with this library; see the file COPYING.LIB. If not, write to
18 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
19 * Boston, MA 02110-1301, USA.
20 *
21 */
22
23#include "config.h"
24#include "nodes.h"
25
26#include <wtf/MathExtras.h>
27#include <wtf/StringExtras.h>
28#include <wtf/unicode/Unicode.h>
29
30using namespace WTF;
31using namespace Unicode;
32
33namespace KJS {
34
35// A simple text streaming class that helps with code indentation.
36
37enum EndlType { Endl };
38enum IndentType { Indent };
39enum UnindentType { Unindent };
40enum DotExprType { DotExpr };
41
42class SourceStream {
43public:
44 SourceStream() : m_numberNeedsParens(false), m_atStartOfStatement(true), m_precedence(PrecExpression) { }
45 UString toString() const { return m_string; }
46 SourceStream& operator<<(const Identifier&);
47 SourceStream& operator<<(const UString&);
48 SourceStream& operator<<(const char*);
49 SourceStream& operator<<(double);
50 SourceStream& operator<<(char);
51 SourceStream& operator<<(EndlType);
52 SourceStream& operator<<(IndentType);
53 SourceStream& operator<<(UnindentType);
54 SourceStream& operator<<(DotExprType);
55 SourceStream& operator<<(Precedence);
56 SourceStream& operator<<(const Node*);
57 template <typename T> SourceStream& operator<<(const RefPtr<T>& n) { return *this << n.get(); }
58
59private:
60 UString m_string;
61 UString m_spacesForIndentation;
62 bool m_numberNeedsParens;
63 bool m_atStartOfStatement;
64 Precedence m_precedence;
65};
66
67// --------
68
69static UString escapeStringForPrettyPrinting(const UString& s)
70{
71 UString escapedString;
72
73 for (int i = 0; i < s.size(); i++) {
74 unsigned short c = s.data()[i].unicode();
75 switch (c) {
76 case '\"':
77 escapedString += "\\\"";
78 break;
79 case '\n':
80 escapedString += "\\n";
81 break;
82 case '\r':
83 escapedString += "\\r";
84 break;
85 case '\t':
86 escapedString += "\\t";
87 break;
88 case '\\':
89 escapedString += "\\\\";
90 break;
91 default:
92 if (c < 128 && isPrintableChar(c))
93 escapedString.append(c);
94 else {
95 char hexValue[7];
96 snprintf(hexValue, 7, "\\u%04x", c);
97 escapedString += hexValue;
98 }
99 }
100 }
101
102 return escapedString;
103}
104
105static const char* operatorString(Operator oper)
106{
107 switch (oper) {
108 case OpEqual:
109 return "=";
110 case OpMultEq:
111 return "*=";
112 case OpDivEq:
113 return "/=";
114 case OpPlusEq:
115 return "+=";
116 case OpMinusEq:
117 return "-=";
118 case OpLShift:
119 return "<<=";
120 case OpRShift:
121 return ">>=";
122 case OpURShift:
123 return ">>>=";
124 case OpAndEq:
125 return "&=";
126 case OpXOrEq:
127 return "^=";
128 case OpOrEq:
129 return "|=";
130 case OpModEq:
131 return "%=";
132 case OpPlusPlus:
133 return "++";
134 case OpMinusMinus:
135 return "--";
136 }
137 ASSERT_NOT_REACHED();
138 return "???";
139}
140
141static bool isParserRoundTripNumber(const UString& string)
142{
143 double number = string.toDouble(false, false);
144 if (isnan(number) || isinf(number))
145 return false;
146 return string == UString::from(number);
147}
148
149// --------
150
151SourceStream& SourceStream::operator<<(char c)
152{
153 m_numberNeedsParens = false;
154 m_atStartOfStatement = false;
155 UChar ch(c);
156 m_string.append(ch);
157 return *this;
158}
159
160SourceStream& SourceStream::operator<<(const char* s)
161{
162 m_numberNeedsParens = false;
163 m_atStartOfStatement = false;
164 m_string += s;
165 return *this;
166}
167
168SourceStream& SourceStream::operator<<(double value)
169{
170 bool needParens = m_numberNeedsParens;
171 m_numberNeedsParens = false;
172 m_atStartOfStatement = false;
173
174 if (needParens)
175 m_string.append('(');
176 m_string += UString::from(value);
177 if (needParens)
178 m_string.append(')');
179
180 return *this;
181}
182
183SourceStream& SourceStream::operator<<(const UString& s)
184{
185 m_numberNeedsParens = false;
186 m_atStartOfStatement = false;
187 m_string += s;
188 return *this;
189}
190
191SourceStream& SourceStream::operator<<(const Identifier& s)
192{
193 m_numberNeedsParens = false;
194 m_atStartOfStatement = false;
195 m_string += s.ustring();
196 return *this;
197}
198
199SourceStream& SourceStream::operator<<(const Node* n)
200{
201 bool needParens = (m_precedence != PrecExpression && n->precedence() > m_precedence) || (m_atStartOfStatement && n->needsParensIfLeftmost());
202 m_precedence = PrecExpression;
203 if (n) {
204 if (needParens)
205 m_string.append('(');
206 n->streamTo(*this);
207 if (needParens)
208 m_string.append(')');
209 }
210 return *this;
211}
212
213SourceStream& SourceStream::operator<<(EndlType)
214{
215 m_numberNeedsParens = false;
216 m_atStartOfStatement = true;
217 m_string.append('\n');
218 m_string.append(m_spacesForIndentation);
219 return *this;
220}
221
222SourceStream& SourceStream::operator<<(IndentType)
223{
224 m_numberNeedsParens = false;
225 m_atStartOfStatement = false;
226 m_spacesForIndentation += " ";
227 return *this;
228}
229
230SourceStream& SourceStream::operator<<(UnindentType)
231{
232 m_numberNeedsParens = false;
233 m_atStartOfStatement = false;
234 m_spacesForIndentation = m_spacesForIndentation.substr(0, m_spacesForIndentation.size() - 2);
235 return *this;
236}
237
238inline SourceStream& SourceStream::operator<<(DotExprType)
239{
240 m_numberNeedsParens = true;
241 return *this;
242}
243
244inline SourceStream& SourceStream::operator<<(Precedence precedence)
245{
246 m_precedence = precedence;
247 return *this;
248}
249
250static void streamLeftAssociativeBinaryOperator(SourceStream& s, Precedence precedence,
251 const char* operatorString, const Node* left, const Node* right)
252{
253 s << precedence << left
254 << ' ' << operatorString << ' '
255 << static_cast<Precedence>(precedence - 1) << right;
256}
257
258template <typename T> static inline void streamLeftAssociativeBinaryOperator(SourceStream& s,
259 Precedence p, const char* o, const RefPtr<T>& l, const RefPtr<T>& r)
260{
261 streamLeftAssociativeBinaryOperator(s, p, o, l.get(), r.get());
262}
263
264// --------
265
266UString Node::toString() const
267{
268 SourceStream stream;
269 streamTo(stream);
270 return stream.toString();
271}
272
273// --------
274
275void NullNode::streamTo(SourceStream& s) const
276{
277 s << "null";
278}
279
280void FalseNode::streamTo(SourceStream& s) const
281{
282 s << "false";
283}
284
285void TrueNode::streamTo(SourceStream& s) const
286{
287 s << "true";
288}
289
290void PlaceholderTrueNode::streamTo(SourceStream&) const
291{
292}
293
294void NumberNode::streamTo(SourceStream& s) const
295{
296 s << value();
297}
298
299void StringNode::streamTo(SourceStream& s) const
300{
301 s << '"' << escapeStringForPrettyPrinting(m_value) << '"';
302}
303
304void RegExpNode::streamTo(SourceStream& s) const
305{
306 s << '/' << m_regExp->pattern() << '/' << m_regExp->flags();
307}
308
309void ThisNode::streamTo(SourceStream& s) const
310{
311 s << "this";
312}
313
314void ResolveNode::streamTo(SourceStream& s) const
315{
316 s << ident;
317}
318
319void ElementNode::streamTo(SourceStream& s) const
320{
321 for (const ElementNode* n = this; n; n = n->next.get()) {
322 for (int i = 0; i < n->elision; i++)
323 s << ',';
324 s << PrecAssignment << n->node;
325 if (n->next)
326 s << ',';
327 }
328}
329
330void ArrayNode::streamTo(SourceStream& s) const
331{
332 s << '[' << element;
333 for (int i = 0; i < elision; i++)
334 s << ',';
335 // Parser consumes one elision comma if there's array elements
336 // present in the expression.
337 if (opt && element)
338 s << ',';
339 s << ']';
340}
341
342void ObjectLiteralNode::streamTo(SourceStream& s) const
343{
344 if (list)
345 s << "{ " << list << " }";
346 else
347 s << "{ }";
348}
349
350void PropertyListNode::streamTo(SourceStream& s) const
351{
352 s << node;
353 for (const PropertyListNode* n = next.get(); n; n = n->next.get())
354 s << ", " << n->node;
355}
356
357void PropertyNode::streamTo(SourceStream& s) const
358{
359 switch (type) {
360 case Constant: {
361 UString propertyName = name().ustring();
362 if (isParserRoundTripNumber(propertyName))
363 s << propertyName;
364 else
365 s << '"' << escapeStringForPrettyPrinting(propertyName) << '"';
366 s << ": " << PrecAssignment << assign;
367 break;
368 }
369 case Getter:
370 case Setter: {
371 const FuncExprNode* func = static_cast<const FuncExprNode*>(assign.get());
372 if (type == Getter)
373 s << "get \"";
374 else
375 s << "set \"";
376 s << escapeStringForPrettyPrinting(name().ustring())
377 << "\"(" << func->param << ')' << func->body;
378 break;
379 }
380 }
381}
382
383void BracketAccessorNode::streamTo(SourceStream& s) const
384{
385 s << PrecCall << expr1 << "[" << expr2 << "]";
386}
387
388void DotAccessorNode::streamTo(SourceStream& s) const
389{
390 s << DotExpr << PrecCall << expr << "." << ident;
391}
392
393void ArgumentListNode::streamTo(SourceStream& s) const
394{
395 s << PrecAssignment << expr;
396 for (ArgumentListNode* n = next.get(); n; n = n->next.get())
397 s << ", " << PrecAssignment << n->expr;
398}
399
400void ArgumentsNode::streamTo(SourceStream& s) const
401{
402 s << '(' << listNode << ')';
403}
404
405void NewExprNode::streamTo(SourceStream& s) const
406{
407 s << "new " << PrecMember << expr << args;
408}
409
410void FunctionCallValueNode::streamTo(SourceStream& s) const
411{
412 s << PrecCall << expr << args;
413}
414
415void FunctionCallResolveNode::streamTo(SourceStream& s) const
416{
417 s << ident << args;
418}
419
420void FunctionCallBracketNode::streamTo(SourceStream& s) const
421{
422 s << PrecCall << base << "[" << subscript << "]" << args;
423}
424
425void FunctionCallDotNode::streamTo(SourceStream& s) const
426{
427 s << DotExpr << PrecCall << base << "." << ident << args;
428}
429
430void PostIncResolveNode::streamTo(SourceStream& s) const
431{
432 s << m_ident << "++";
433}
434
435void PostDecResolveNode::streamTo(SourceStream& s) const
436{
437 s << m_ident << "--";
438}
439
440void PostfixBracketNode::streamTo(SourceStream& s) const
441{
442 s << PrecCall << m_base << "[" << m_subscript << "]";
443 if (isIncrement())
444 s << "++";
445 else
446 s << "--";
447}
448
449void PostfixDotNode::streamTo(SourceStream& s) const
450{
451 s << DotExpr << PrecCall << m_base << "." << m_ident;
452 if (isIncrement())
453 s << "++";
454 else
455 s << "--";
456}
457
458void PostfixErrorNode::streamTo(SourceStream& s) const
459{
460 s << PrecLeftHandSide << m_expr;
461 if (m_oper == OpPlusPlus)
462 s << "++";
463 else
464 s << "--";
465}
466
467void DeleteResolveNode::streamTo(SourceStream& s) const
468{
469 s << "delete " << m_ident;
470}
471
472void DeleteBracketNode::streamTo(SourceStream& s) const
473{
474 s << "delete " << PrecCall << m_base << "[" << m_subscript << "]";
475}
476
477void DeleteDotNode::streamTo(SourceStream& s) const
478{
479 s << "delete " << DotExpr << PrecCall << m_base << "." << m_ident;
480}
481
482void DeleteValueNode::streamTo(SourceStream& s) const
483{
484 s << "delete " << PrecUnary << m_expr;
485}
486
487void VoidNode::streamTo(SourceStream& s) const
488{
489 s << "void " << PrecUnary << expr;
490}
491
492void TypeOfValueNode::streamTo(SourceStream& s) const
493{
494 s << "typeof " << PrecUnary << m_expr;
495}
496
497void TypeOfResolveNode::streamTo(SourceStream& s) const
498{
499 s << "typeof " << m_ident;
500}
501
502void PreIncResolveNode::streamTo(SourceStream& s) const
503{
504 s << "++" << m_ident;
505}
506
507void PreDecResolveNode::streamTo(SourceStream& s) const
508{
509 s << "--" << m_ident;
510}
511
512void PrefixBracketNode::streamTo(SourceStream& s) const
513{
514 if (isIncrement())
515 s << "++";
516 else
517 s << "--";
518 s << PrecCall << m_base << "[" << m_subscript << "]";
519}
520
521void PrefixDotNode::streamTo(SourceStream& s) const
522{
523 if (isIncrement())
524 s << "++";
525 else
526 s << "--";
527 s << DotExpr << PrecCall << m_base << "." << m_ident;
528}
529
530void PrefixErrorNode::streamTo(SourceStream& s) const
531{
532 if (m_oper == OpPlusPlus)
533 s << "++" << PrecUnary << m_expr;
534 else
535 s << "--" << PrecUnary << m_expr;
536}
537
538void UnaryPlusNode::streamTo(SourceStream& s) const
539{
540 s << "+ " << PrecUnary << m_expr;
541}
542
543void NegateNode::streamTo(SourceStream& s) const
544{
545 s << "- " << PrecUnary << expr;
546}
547
548void BitwiseNotNode::streamTo(SourceStream& s) const
549{
550 s << "~" << PrecUnary << expr;
551}
552
553void LogicalNotNode::streamTo(SourceStream& s) const
554{
555 s << "!" << PrecUnary << expr;
556}
557
558void MultNode::streamTo(SourceStream& s) const
559{
560 streamLeftAssociativeBinaryOperator(s, precedence(), "*", term1, term2);
561}
562
563void DivNode::streamTo(SourceStream& s) const
564{
565 streamLeftAssociativeBinaryOperator(s, precedence(), "/", term1, term2);
566}
567
568void ModNode::streamTo(SourceStream& s) const
569{
570 streamLeftAssociativeBinaryOperator(s, precedence(), "%", term1, term2);
571}
572
573void AddNode::streamTo(SourceStream& s) const
574{
575 streamLeftAssociativeBinaryOperator(s, precedence(), "+", term1, term2);
576}
577
578void SubNode::streamTo(SourceStream& s) const
579{
580 streamLeftAssociativeBinaryOperator(s, precedence(), "-", term1, term2);
581}
582
583void LeftShiftNode::streamTo(SourceStream& s) const
584{
585 streamLeftAssociativeBinaryOperator(s, precedence(), "<<", term1, term2);
586}
587
588void RightShiftNode::streamTo(SourceStream& s) const
589{
590 streamLeftAssociativeBinaryOperator(s, precedence(), ">>", term1, term2);
591}
592
593void UnsignedRightShiftNode::streamTo(SourceStream& s) const
594{
595 streamLeftAssociativeBinaryOperator(s, precedence(), ">>>", term1, term2);
596}
597
598void LessNode::streamTo(SourceStream& s) const
599{
600 streamLeftAssociativeBinaryOperator(s, precedence(), "<", expr1, expr2);
601}
602
603void GreaterNode::streamTo(SourceStream& s) const
604{
605 streamLeftAssociativeBinaryOperator(s, precedence(), ">", expr1, expr2);
606}
607
608void LessEqNode::streamTo(SourceStream& s) const
609{
610 streamLeftAssociativeBinaryOperator(s, precedence(), "<=", expr1, expr2);
611}
612
613void GreaterEqNode::streamTo(SourceStream& s) const
614{
615 streamLeftAssociativeBinaryOperator(s, precedence(), ">=", expr1, expr2);
616}
617
618void InstanceOfNode::streamTo(SourceStream& s) const
619{
620 streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", expr1, expr2);
621}
622
623void InNode::streamTo(SourceStream& s) const
624{
625 streamLeftAssociativeBinaryOperator(s, precedence(), "in", expr1, expr2);
626}
627
628void EqualNode::streamTo(SourceStream& s) const
629{
630 streamLeftAssociativeBinaryOperator(s, precedence(), "==", expr1, expr2);
631}
632
633void NotEqualNode::streamTo(SourceStream& s) const
634{
635 streamLeftAssociativeBinaryOperator(s, precedence(), "!=", expr1, expr2);
636}
637
638void StrictEqualNode::streamTo(SourceStream& s) const
639{
640 streamLeftAssociativeBinaryOperator(s, precedence(), "===", expr1, expr2);
641}
642
643void NotStrictEqualNode::streamTo(SourceStream& s) const
644{
645 streamLeftAssociativeBinaryOperator(s, precedence(), "!==", expr1, expr2);
646}
647
648void BitAndNode::streamTo(SourceStream& s) const
649{
650 streamLeftAssociativeBinaryOperator(s, precedence(), "&", expr1, expr2);
651}
652
653void BitXOrNode::streamTo(SourceStream& s) const
654{
655 streamLeftAssociativeBinaryOperator(s, precedence(), "^", expr1, expr2);
656}
657
658void BitOrNode::streamTo(SourceStream& s) const
659{
660 streamLeftAssociativeBinaryOperator(s, precedence(), "|", expr1, expr2);
661}
662
663void LogicalAndNode::streamTo(SourceStream& s) const
664{
665 streamLeftAssociativeBinaryOperator(s, precedence(), "&&", expr1, expr2);
666}
667
668void LogicalOrNode::streamTo(SourceStream& s) const
669{
670 streamLeftAssociativeBinaryOperator(s, precedence(), "||", expr1, expr2);
671}
672
673void ConditionalNode::streamTo(SourceStream& s) const
674{
675 s << PrecLogicalOr << logical
676 << " ? " << PrecAssignment << expr1
677 << " : " << PrecAssignment << expr2;
678}
679
680void ReadModifyResolveNode::streamTo(SourceStream& s) const
681{
682 s << m_ident << ' ' << operatorString(m_oper) << ' ' << PrecAssignment << m_right;
683}
684
685void AssignResolveNode::streamTo(SourceStream& s) const
686{
687 s << m_ident << " = " << PrecAssignment << m_right;
688}
689
690void ReadModifyBracketNode::streamTo(SourceStream& s) const
691{
692 s << PrecCall << m_base << '[' << m_subscript << "] "
693 << operatorString(m_oper) << ' ' << PrecAssignment << m_right;
694}
695
696void AssignBracketNode::streamTo(SourceStream& s) const
697{
698 s << PrecCall << m_base << '[' << m_subscript << "] = " << PrecAssignment << m_right;
699}
700
701void ReadModifyDotNode::streamTo(SourceStream& s) const
702{
703 s << DotExpr << PrecCall << m_base << "." << m_ident << ' '
704 << operatorString(m_oper) << ' ' << PrecAssignment << m_right;
705}
706
707void AssignDotNode::streamTo(SourceStream& s) const
708{
709 s << DotExpr << PrecCall << m_base << "." << m_ident << " = " << PrecAssignment << m_right;
710}
711
712void AssignErrorNode::streamTo(SourceStream& s) const
713{
714 s << PrecLeftHandSide << m_left << ' '
715 << operatorString(m_oper) << ' ' << PrecAssignment << m_right;
716}
717
718void CommaNode::streamTo(SourceStream& s) const
719{
720 s << PrecAssignment << expr1 << ", " << PrecAssignment << expr2;
721}
722
723void ConstDeclNode::streamTo(SourceStream& s) const
724{
725 s << ident;
726 if (init)
727 s << " = " << init;
728 for (ConstDeclNode* n = next.get(); n; n = n->next.get()) {
729 s << ", " << ident;
730 if (init)
731 s << " = " << init;
732 }
733}
734
735void ConstStatementNode::streamTo(SourceStream& s) const
736{
737 s << Endl << "const " << next << ';';
738}
739
740static inline void statementListStreamTo(const Vector<RefPtr<StatementNode> >& nodes, SourceStream& s)
741{
742 for (Vector<RefPtr<StatementNode> >::const_iterator ptr = nodes.begin(); ptr != nodes.end(); ptr++)
743 s << *ptr;
744}
745
746void BlockNode::streamTo(SourceStream& s) const
747{
748 s << Endl << "{" << Indent;
749 statementListStreamTo(m_children, s);
750 s << Unindent << Endl << "}";
751}
752
753void ScopeNode::streamTo(SourceStream& s) const
754{
755 s << Endl << "{" << Indent;
756
757 bool printedVar = false;
758 for (size_t i = 0; i < m_varStack.size(); ++i) {
759 if (m_varStack[i].second == 0) {
760 if (!printedVar) {
761 s << Endl << "var ";
762 printedVar = true;
763 } else
764 s << ", ";
765 s << m_varStack[i].first;
766 }
767 }
768 if (printedVar)
769 s << ';';
770
771 statementListStreamTo(m_children, s);
772 s << Unindent << Endl << "}";
773}
774
775void EmptyStatementNode::streamTo(SourceStream& s) const
776{
777 s << Endl << ';';
778}
779
780void ExprStatementNode::streamTo(SourceStream& s) const
781{
782 s << Endl << expr << ';';
783}
784
785void VarStatementNode::streamTo(SourceStream& s) const
786{
787 s << Endl << "var " << expr << ';';
788}
789
790void IfNode::streamTo(SourceStream& s) const
791{
792 s << Endl << "if (" << m_condition << ')' << Indent << m_ifBlock << Unindent;
793}
794
795void IfElseNode::streamTo(SourceStream& s) const
796{
797 IfNode::streamTo(s);
798 s << Endl << "else" << Indent << m_elseBlock << Unindent;
799}
800
801void DoWhileNode::streamTo(SourceStream& s) const
802{
803 s << Endl << "do " << Indent << statement << Unindent << Endl
804 << "while (" << expr << ");";
805}
806
807void WhileNode::streamTo(SourceStream& s) const
808{
809 s << Endl << "while (" << expr << ')' << Indent << statement << Unindent;
810}
811
812void ForNode::streamTo(SourceStream& s) const
813{
814 s << Endl << "for ("
815 << (expr1WasVarDecl ? "var " : "")
816 << expr1
817 << "; " << expr2
818 << "; " << expr3
819 << ')' << Indent << statement << Unindent;
820}
821
822void ForInNode::streamTo(SourceStream& s) const
823{
824 s << Endl << "for (";
825 if (identIsVarDecl) {
826 s << "var ";
827 if (init)
828 s << init;
829 else
830 s << PrecLeftHandSide << lexpr;
831 } else
832 s << PrecLeftHandSide << lexpr;
833
834 s << " in " << expr << ')' << Indent << statement << Unindent;
835}
836
837void ContinueNode::streamTo(SourceStream& s) const
838{
839 s << Endl << "continue";
840 if (!ident.isNull())
841 s << ' ' << ident;
842 s << ';';
843}
844
845void BreakNode::streamTo(SourceStream& s) const
846{
847 s << Endl << "break";
848 if (!ident.isNull())
849 s << ' ' << ident;
850 s << ';';
851}
852
853void ReturnNode::streamTo(SourceStream& s) const
854{
855 s << Endl << "return";
856 if (value)
857 s << ' ' << value;
858 s << ';';
859}
860
861void WithNode::streamTo(SourceStream& s) const
862{
863 s << Endl << "with (" << expr << ") " << statement;
864}
865
866void CaseClauseNode::streamTo(SourceStream& s) const
867{
868 s << Endl;
869 if (expr)
870 s << "case " << expr;
871 else
872 s << "default";
873 s << ":" << Indent;
874 statementListStreamTo(m_children, s);
875 s << Unindent;
876}
877
878void ClauseListNode::streamTo(SourceStream& s) const
879{
880 for (const ClauseListNode* n = this; n; n = n->getNext())
881 s << n->getClause();
882}
883
884void CaseBlockNode::streamTo(SourceStream& s) const
885{
886 for (const ClauseListNode* n = list1.get(); n; n = n->getNext())
887 s << n->getClause();
888 s << def;
889 for (const ClauseListNode* n = list2.get(); n; n = n->getNext())
890 s << n->getClause();
891}
892
893void SwitchNode::streamTo(SourceStream& s) const
894{
895 s << Endl << "switch (" << expr << ") {"
896 << Indent << block << Unindent
897 << Endl << "}";
898}
899
900void LabelNode::streamTo(SourceStream& s) const
901{
902 s << Endl << label << ":" << Indent << statement << Unindent;
903}
904
905void ThrowNode::streamTo(SourceStream& s) const
906{
907 s << Endl << "throw " << expr << ';';
908}
909
910void TryNode::streamTo(SourceStream& s) const
911{
912 s << Endl << "try " << tryBlock;
913 if (catchBlock)
914 s << Endl << "catch (" << exceptionIdent << ')' << catchBlock;
915 if (finallyBlock)
916 s << Endl << "finally " << finallyBlock;
917}
918
919void ParameterNode::streamTo(SourceStream& s) const
920{
921 s << id;
922 for (ParameterNode* n = next.get(); n; n = n->next.get())
923 s << ", " << n->id;
924}
925
926void FuncDeclNode::streamTo(SourceStream& s) const
927{
928 s << Endl << "function " << ident << '(' << param << ')' << body;
929}
930
931void FuncExprNode::streamTo(SourceStream& s) const
932{
933 s << "function " << ident << '(' << param << ')' << body;
934}
935
936}
Note: See TracBrowser for help on using the repository browser.