2 * Copyright (C) 2002 Harri Porten (porten@kde.org)
3 * Copyright (C) 2003, 2004, 2005, 2006, 2007 Apple Inc. All rights reserved.
4 * Copyright (C) 2007 Eric Seidel <eric@webkit.org>
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.
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.
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.
26 #include <wtf/MathExtras.h>
27 #include <wtf/StringExtras.h>
28 #include <wtf/unicode/Unicode.h>
31 using namespace Unicode;
35 // A simple text streaming class that helps with code indentation.
37 enum EndlType { Endl };
38 enum IndentType { Indent };
39 enum UnindentType { Unindent };
40 enum DotExprType { DotExpr };
44 SourceStream() : m_numberNeedsParens(false), 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(); }
61 UString m_spacesForIndentation;
62 bool m_numberNeedsParens;
63 Precedence m_precedence;
68 static UString escapeStringForPrettyPrinting(const UString& s)
70 UString escapedString;
72 for (int i = 0; i < s.size(); i++) {
73 unsigned short c = s.data()[i].unicode();
76 escapedString += "\\\"";
79 escapedString += "\\n";
82 escapedString += "\\r";
85 escapedString += "\\t";
88 escapedString += "\\\\";
91 if (c < 128 && isPrintableChar(c))
92 escapedString.append(c);
95 snprintf(hexValue, 7, "\\u%04x", c);
96 escapedString += hexValue;
101 return escapedString;
104 static const char* operatorString(Operator oper)
136 ASSERT_NOT_REACHED();
140 static bool isParserRoundTripNumber(const UString& string)
142 double number = string.toDouble(false, false);
143 if (isnan(number) || isinf(number))
145 return string == UString::from(number);
150 SourceStream& SourceStream::operator<<(char c)
152 m_numberNeedsParens = false;
158 SourceStream& SourceStream::operator<<(const char* s)
160 m_numberNeedsParens = false;
165 SourceStream& SourceStream::operator<<(double value)
167 bool needParens = m_numberNeedsParens;
168 m_numberNeedsParens = false;
171 m_string.append('(');
172 m_string += UString::from(value);
174 m_string.append(')');
179 SourceStream& SourceStream::operator<<(const UString& s)
181 m_numberNeedsParens = false;
186 SourceStream& SourceStream::operator<<(const Identifier& s)
188 m_numberNeedsParens = false;
189 m_string += s.ustring();
193 SourceStream& SourceStream::operator<<(const Node* n)
195 bool needParens = m_precedence != PrecExpression && n->precedence() > m_precedence;
196 m_precedence = PrecExpression;
199 m_string.append('(');
202 m_string.append(')');
207 SourceStream& SourceStream::operator<<(EndlType)
209 m_numberNeedsParens = false;
210 m_string.append('\n');
211 m_string.append(m_spacesForIndentation);
215 SourceStream& SourceStream::operator<<(IndentType)
217 m_numberNeedsParens = false;
218 m_spacesForIndentation += " ";
222 SourceStream& SourceStream::operator<<(UnindentType)
224 m_numberNeedsParens = false;
225 m_spacesForIndentation = m_spacesForIndentation.substr(0, m_spacesForIndentation.size() - 2);
229 inline SourceStream& SourceStream::operator<<(DotExprType)
231 m_numberNeedsParens = true;
235 inline SourceStream& SourceStream::operator<<(Precedence precedence)
237 m_precedence = precedence;
241 static void streamLeftAssociativeBinaryOperator(SourceStream& s, Precedence precedence,
242 const char* operatorString, const Node* left, const Node* right)
244 s << precedence << left
245 << ' ' << operatorString << ' '
246 << static_cast<Precedence>(precedence - 1) << right;
249 template <typename T> static inline void streamLeftAssociativeBinaryOperator(SourceStream& s,
250 Precedence p, const char* o, const RefPtr<T>& l, const RefPtr<T>& r)
252 streamLeftAssociativeBinaryOperator(s, p, o, l.get(), r.get());
257 UString Node::toString() const
261 return stream.toString();
266 void NullNode::streamTo(SourceStream& s) const
271 void BooleanNode::streamTo(SourceStream& s) const
273 s << (value ? "true" : "false");
276 void NumberNode::streamTo(SourceStream& s) const
281 void StringNode::streamTo(SourceStream& s) const
283 s << '"' << escapeStringForPrettyPrinting(value) << '"';
286 void RegExpNode::streamTo(SourceStream& s) const
288 s << '/' << pattern << '/' << flags;
291 void ThisNode::streamTo(SourceStream& s) const
296 void ResolveNode::streamTo(SourceStream& s) const
301 void ElementNode::streamTo(SourceStream& s) const
303 for (const ElementNode* n = this; n; n = n->next.get()) {
304 for (int i = 0; i < n->elision; i++)
306 s << PrecAssignment << n->node;
312 void ArrayNode::streamTo(SourceStream& s) const
315 for (int i = 0; i < elision; i++)
317 // Parser consumes one elision comma if there's array elements
318 // present in the expression.
324 void ObjectLiteralNode::streamTo(SourceStream& s) const
327 s << "{ " << list << " }";
332 void PropertyListNode::streamTo(SourceStream& s) const
335 for (const PropertyListNode* n = next.get(); n; n = n->next.get())
336 s << ", " << n->node;
339 void PropertyNode::streamTo(SourceStream& s) const
343 UString propertyName = name().ustring();
344 if (isParserRoundTripNumber(propertyName))
347 s << '"' << escapeStringForPrettyPrinting(propertyName) << '"';
348 s << ": " << PrecAssignment << assign;
353 const FuncExprNode* func = static_cast<const FuncExprNode*>(assign.get());
358 s << escapeStringForPrettyPrinting(name().ustring())
359 << "\"(" << func->param << ')' << func->body;
365 void BracketAccessorNode::streamTo(SourceStream& s) const
367 s << PrecCall << expr1 << "[" << expr2 << "]";
370 void DotAccessorNode::streamTo(SourceStream& s) const
372 s << DotExpr << PrecCall << expr << "." << ident;
375 void ArgumentListNode::streamTo(SourceStream& s) const
377 s << PrecAssignment << expr;
378 for (ArgumentListNode* n = next.get(); n; n = n->next.get())
379 s << ", " << PrecAssignment << n->expr;
382 void ArgumentsNode::streamTo(SourceStream& s) const
384 s << '(' << listNode << ')';
387 void NewExprNode::streamTo(SourceStream& s) const
389 s << "new " << PrecMember << expr << args;
392 void FunctionCallValueNode::streamTo(SourceStream& s) const
394 s << PrecCall << expr << args;
397 void FunctionCallResolveNode::streamTo(SourceStream& s) const
402 void FunctionCallBracketNode::streamTo(SourceStream& s) const
404 s << PrecCall << base << "[" << subscript << "]" << args;
407 void FunctionCallDotNode::streamTo(SourceStream& s) const
409 s << DotExpr << PrecCall << base << "." << ident << args;
412 void PostIncResolveNode::streamTo(SourceStream& s) const
414 s << m_ident << "++";
417 void PostDecResolveNode::streamTo(SourceStream& s) const
419 s << m_ident << "--";
422 void PostfixBracketNode::streamTo(SourceStream& s) const
424 s << PrecCall << m_base << "[" << m_subscript << "]";
431 void PostfixDotNode::streamTo(SourceStream& s) const
433 s << DotExpr << PrecCall << m_base << "." << m_ident;
440 void PostfixErrorNode::streamTo(SourceStream& s) const
442 s << PrecLeftHandSide << m_expr;
443 if (m_oper == OpPlusPlus)
449 void DeleteResolveNode::streamTo(SourceStream& s) const
451 s << "delete " << m_ident;
454 void DeleteBracketNode::streamTo(SourceStream& s) const
456 s << "delete " << PrecCall << m_base << "[" << m_subscript << "]";
459 void DeleteDotNode::streamTo(SourceStream& s) const
461 s << "delete " << DotExpr << PrecCall << m_base << "." << m_ident;
464 void DeleteValueNode::streamTo(SourceStream& s) const
466 s << "delete " << PrecUnary << m_expr;
469 void VoidNode::streamTo(SourceStream& s) const
471 s << "void " << PrecUnary << expr;
474 void TypeOfValueNode::streamTo(SourceStream& s) const
476 s << "typeof " << PrecUnary << m_expr;
479 void TypeOfResolveNode::streamTo(SourceStream& s) const
481 s << "typeof " << m_ident;
484 void PreIncResolveNode::streamTo(SourceStream& s) const
486 s << "++" << m_ident;
489 void PreDecResolveNode::streamTo(SourceStream& s) const
491 s << "--" << m_ident;
494 void PrefixBracketNode::streamTo(SourceStream& s) const
500 s << PrecCall << m_base << "[" << m_subscript << "]";
503 void PrefixDotNode::streamTo(SourceStream& s) const
509 s << DotExpr << PrecCall << m_base << "." << m_ident;
512 void PrefixErrorNode::streamTo(SourceStream& s) const
514 if (m_oper == OpPlusPlus)
515 s << "++" << PrecUnary << m_expr;
517 s << "--" << PrecUnary << m_expr;
520 void UnaryPlusNode::streamTo(SourceStream& s) const
522 s << "+ " << PrecUnary << expr;
525 void NegateNode::streamTo(SourceStream& s) const
527 s << "- " << PrecUnary << expr;
530 void BitwiseNotNode::streamTo(SourceStream& s) const
532 s << "~" << PrecUnary << expr;
535 void LogicalNotNode::streamTo(SourceStream& s) const
537 s << "!" << PrecUnary << expr;
540 void MultNode::streamTo(SourceStream& s) const
542 streamLeftAssociativeBinaryOperator(s, precedence(), "*", term1, term2);
545 void DivNode::streamTo(SourceStream& s) const
547 streamLeftAssociativeBinaryOperator(s, precedence(), "/", term1, term2);
550 void ModNode::streamTo(SourceStream& s) const
552 streamLeftAssociativeBinaryOperator(s, precedence(), "%", term1, term2);
555 void AddNode::streamTo(SourceStream& s) const
557 streamLeftAssociativeBinaryOperator(s, precedence(), "+", term1, term2);
560 void SubNode::streamTo(SourceStream& s) const
562 streamLeftAssociativeBinaryOperator(s, precedence(), "-", term1, term2);
565 void LeftShiftNode::streamTo(SourceStream& s) const
567 streamLeftAssociativeBinaryOperator(s, precedence(), "<<", term1, term2);
570 void RightShiftNode::streamTo(SourceStream& s) const
572 streamLeftAssociativeBinaryOperator(s, precedence(), ">>", term1, term2);
575 void UnsignedRightShiftNode::streamTo(SourceStream& s) const
577 streamLeftAssociativeBinaryOperator(s, precedence(), ">>>", term1, term2);
580 void LessNode::streamTo(SourceStream& s) const
582 streamLeftAssociativeBinaryOperator(s, precedence(), "<", expr1, expr2);
585 void GreaterNode::streamTo(SourceStream& s) const
587 streamLeftAssociativeBinaryOperator(s, precedence(), ">", expr1, expr2);
590 void LessEqNode::streamTo(SourceStream& s) const
592 streamLeftAssociativeBinaryOperator(s, precedence(), "<=", expr1, expr2);
595 void GreaterEqNode::streamTo(SourceStream& s) const
597 streamLeftAssociativeBinaryOperator(s, precedence(), ">=", expr1, expr2);
600 void InstanceOfNode::streamTo(SourceStream& s) const
602 streamLeftAssociativeBinaryOperator(s, precedence(), "instanceof", expr1, expr2);
605 void InNode::streamTo(SourceStream& s) const
607 streamLeftAssociativeBinaryOperator(s, precedence(), "in", expr1, expr2);
610 void EqualNode::streamTo(SourceStream& s) const
612 streamLeftAssociativeBinaryOperator(s, precedence(), "==", expr1, expr2);
615 void NotEqualNode::streamTo(SourceStream& s) const
617 streamLeftAssociativeBinaryOperator(s, precedence(), "!=", expr1, expr2);
620 void StrictEqualNode::streamTo(SourceStream& s) const
622 streamLeftAssociativeBinaryOperator(s, precedence(), "===", expr1, expr2);
625 void NotStrictEqualNode::streamTo(SourceStream& s) const
627 streamLeftAssociativeBinaryOperator(s, precedence(), "!==", expr1, expr2);
630 void BitAndNode::streamTo(SourceStream& s) const
632 streamLeftAssociativeBinaryOperator(s, precedence(), "&", expr1, expr2);
635 void BitXOrNode::streamTo(SourceStream& s) const
637 streamLeftAssociativeBinaryOperator(s, precedence(), "^", expr1, expr2);
640 void BitOrNode::streamTo(SourceStream& s) const
642 streamLeftAssociativeBinaryOperator(s, precedence(), "|", expr1, expr2);
645 void LogicalAndNode::streamTo(SourceStream& s) const
647 streamLeftAssociativeBinaryOperator(s, precedence(), "&&", expr1, expr2);
650 void LogicalOrNode::streamTo(SourceStream& s) const
652 streamLeftAssociativeBinaryOperator(s, precedence(), "||", expr1, expr2);
655 void ConditionalNode::streamTo(SourceStream& s) const
657 s << PrecLogicalOr << logical
658 << " ? " << PrecAssignment << expr1
659 << " : " << PrecAssignment << expr2;
662 void ReadModifyResolveNode::streamTo(SourceStream& s) const
664 s << m_ident << ' ' << operatorString(m_oper) << ' ' << PrecAssignment << m_right;
667 void AssignResolveNode::streamTo(SourceStream& s) const
669 s << m_ident << " = " << PrecAssignment << m_right;
672 void ReadModifyBracketNode::streamTo(SourceStream& s) const
674 s << PrecCall << m_base << '[' << m_subscript << "] "
675 << operatorString(m_oper) << ' ' << PrecAssignment << m_right;
678 void AssignBracketNode::streamTo(SourceStream& s) const
680 s << PrecCall << m_base << '[' << m_subscript << "] = " << PrecAssignment << m_right;
683 void ReadModifyDotNode::streamTo(SourceStream& s) const
685 s << DotExpr << PrecCall << m_base << "." << m_ident << ' '
686 << operatorString(m_oper) << ' ' << PrecAssignment << m_right;
689 void AssignDotNode::streamTo(SourceStream& s) const
691 s << DotExpr << PrecCall << m_base << "." << m_ident << " = " << PrecAssignment << m_right;
694 void AssignErrorNode::streamTo(SourceStream& s) const
696 s << PrecLeftHandSide << m_left << ' '
697 << operatorString(m_oper) << ' ' << PrecAssignment << m_right;
700 void CommaNode::streamTo(SourceStream& s) const
702 s << PrecAssignment << expr1 << ", " << PrecAssignment << expr2;
705 void AssignExprNode::streamTo(SourceStream& s) const
707 s << " = " << PrecAssignment << expr;
710 void VarDeclNode::streamTo(SourceStream& s) const
712 s << "var " << ident << init;
713 for (VarDeclNode* n = next.get(); n; n = n->next.get())
714 s << ", " << ident << init;
717 void VarStatementNode::streamTo(SourceStream& s) const
719 s << Endl << next << ';';
722 static inline void statementListStreamTo(Vector<RefPtr<StatementNode> >* nodes, SourceStream& s)
727 for (Vector<RefPtr<StatementNode> >::iterator ptr = nodes->begin(); ptr != nodes->end(); ptr++)
731 void BlockNode::streamTo(SourceStream& s) const
733 s << Endl << "{" << Indent;
734 statementListStreamTo(m_children.get(), s);
735 s << Unindent << Endl << "}";
738 void EmptyStatementNode::streamTo(SourceStream& s) const
743 void ExprStatementNode::streamTo(SourceStream& s) const
745 s << Endl << expr << ';';
748 void IfNode::streamTo(SourceStream& s) const
750 s << Endl << "if (" << expr << ')' << Indent << statement1 << Unindent;
752 s << Endl << "else" << Indent << statement2 << Unindent;
755 void DoWhileNode::streamTo(SourceStream& s) const
757 s << Endl << "do " << Indent << statement << Unindent << Endl
758 << "while (" << expr << ");";
761 void WhileNode::streamTo(SourceStream& s) const
763 s << Endl << "while (" << expr << ')' << Indent << statement << Unindent;
766 void ForNode::streamTo(SourceStream& s) const
772 << ')' << Indent << statement << Unindent;
775 void ForInNode::streamTo(SourceStream& s) const
777 s << Endl << "for (";
781 s << PrecLeftHandSide << lexpr;
783 s << " in " << expr << ')' << Indent << statement << Unindent;
786 void ContinueNode::streamTo(SourceStream& s) const
788 s << Endl << "continue";
794 void BreakNode::streamTo(SourceStream& s) const
796 s << Endl << "break";
802 void ReturnNode::streamTo(SourceStream& s) const
804 s << Endl << "return";
810 void WithNode::streamTo(SourceStream& s) const
812 s << Endl << "with (" << expr << ") " << statement;
815 void CaseClauseNode::streamTo(SourceStream& s) const
819 s << "case " << expr;
823 statementListStreamTo(m_children.get(), s);
827 void ClauseListNode::streamTo(SourceStream& s) const
829 for (const ClauseListNode* n = this; n; n = n->getNext())
833 void CaseBlockNode::streamTo(SourceStream& s) const
835 for (const ClauseListNode* n = list1.get(); n; n = n->getNext())
838 for (const ClauseListNode* n = list2.get(); n; n = n->getNext())
842 void SwitchNode::streamTo(SourceStream& s) const
844 s << Endl << "switch (" << expr << ") {"
845 << Indent << block << Unindent
849 void LabelNode::streamTo(SourceStream& s) const
851 s << Endl << label << ":" << Indent << statement << Unindent;
854 void ThrowNode::streamTo(SourceStream& s) const
856 s << Endl << "throw " << expr << ';';
859 void TryNode::streamTo(SourceStream& s) const
861 s << Endl << "try " << tryBlock;
863 s << Endl << "catch (" << exceptionIdent << ')' << catchBlock;
865 s << Endl << "finally " << finallyBlock;
868 void ParameterNode::streamTo(SourceStream& s) const
871 for (ParameterNode* n = next.get(); n; n = n->next.get())
875 void FuncDeclNode::streamTo(SourceStream& s) const
877 s << Endl << "function " << ident << '(' << param << ')' << body;
880 void FuncExprNode::streamTo(SourceStream& s) const
882 s << "function " << ident << '(' << param << ')' << body;