source: trunk/src/script/qscriptprettypretty.cpp@ 76

Last change on this file since 76 was 2, checked in by Dmitry A. Kuminov, 16 years ago

Initially imported qt-all-opensource-src-4.5.1 from Trolltech.

File size: 27.7 KB
Line 
1/****************************************************************************
2**
3** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies).
4** Contact: Qt Software Information ([email protected])
5**
6** This file is part of the QtScript module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial Usage
10** Licensees holding valid Qt Commercial licenses may use this file in
11** accordance with the Qt Commercial License Agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and Nokia.
14**
15** GNU Lesser General Public License Usage
16** Alternatively, this file may be used under the terms of the GNU Lesser
17** General Public License version 2.1 as published by the Free Software
18** Foundation and appearing in the file LICENSE.LGPL included in the
19** packaging of this file. Please review the following information to
20** ensure the GNU Lesser General Public License version 2.1 requirements
21** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
22**
23** In addition, as a special exception, Nokia gives you certain
24** additional rights. These rights are described in the Nokia Qt LGPL
25** Exception version 1.0, included in the file LGPL_EXCEPTION.txt in this
26** package.
27**
28** GNU General Public License Usage
29** Alternatively, this file may be used under the terms of the GNU
30** General Public License version 3.0 as published by the Free Software
31** Foundation and appearing in the file LICENSE.GPL included in the
32** packaging of this file. Please review the following information to
33** ensure the GNU General Public License version 3.0 requirements will be
34** met: http://www.gnu.org/copyleft/gpl.html.
35**
36** If you are unsure which license is appropriate for your use, please
37** contact the sales department at [email protected].
38** $QT_END_LICENSE$
39**
40****************************************************************************/
41
42#include "qscriptprettypretty_p.h"
43
44#ifndef QT_NO_SCRIPT
45
46#include "qscriptengine_p.h"
47#include "qscriptvalueimpl_p.h"
48#include "qscriptcontext_p.h"
49#include "qscriptmember_p.h"
50#include "qscriptobject_p.h"
51#include "qscriptast_p.h"
52
53#include <QtCore/QString>
54#include <QtCore/QTextStream>
55#include <QtCore/QtDebug>
56
57QT_BEGIN_NAMESPACE
58
59namespace QScript {
60QString numberToString(qsreal value);
61}
62
63using namespace QScript;
64
65PrettyPretty::PrettyPretty(QTextStream &o):
66 out(o), m_indentLevel(0)
67{
68}
69
70PrettyPretty::~PrettyPretty()
71{
72}
73
74void PrettyPretty::acceptAsBlock(AST::Node *node)
75{
76 out << "{";
77 pushIndentLevel();
78 newlineAndIndent();
79 accept(node);
80 popIndentLevel();
81 newlineAndIndent();
82 out << "}";
83}
84
85int PrettyPretty::operatorPrecedenceLevel(int op)
86{
87 switch (op) {
88 case QSOperator::Div:
89 case QSOperator::Mod:
90 case QSOperator::Mul:
91 return 5;
92 case QSOperator::Add:
93 case QSOperator::Sub:
94 return 6;
95 case QSOperator::LShift:
96 case QSOperator::RShift:
97 case QSOperator::URShift:
98 return 7;
99 case QSOperator::Ge:
100 case QSOperator::Gt:
101 case QSOperator::In:
102 case QSOperator::InstanceOf:
103 case QSOperator::Le:
104 case QSOperator::Lt:
105 return 8;
106 case QSOperator::Equal:
107 case QSOperator::NotEqual:
108 case QSOperator::StrictEqual:
109 case QSOperator::StrictNotEqual:
110 return 9;
111 case QSOperator::BitAnd:
112 return 10;
113 case QSOperator::BitXor:
114 return 11;
115 case QSOperator::BitOr:
116 return 12;
117 case QSOperator::And:
118 return 13;
119 case QSOperator::Or:
120 return 14;
121 case QSOperator::InplaceAnd:
122 case QSOperator::InplaceSub:
123 case QSOperator::InplaceDiv:
124 case QSOperator::InplaceAdd:
125 case QSOperator::InplaceLeftShift:
126 case QSOperator::InplaceMod:
127 case QSOperator::InplaceMul:
128 case QSOperator::InplaceOr:
129 case QSOperator::InplaceRightShift:
130 case QSOperator::InplaceURightShift:
131 case QSOperator::InplaceXor:
132 case QSOperator::Assign:
133 return 16;
134 default:
135 Q_ASSERT_X(false, "PrettyPretty::operatorPrecedenceLevel()", "bad operator");
136 }
137 return 0;
138}
139
140int PrettyPretty::compareOperatorPrecedence(int op1, int op2)
141{
142 int prec1 = operatorPrecedenceLevel(op1);
143 int prec2 = operatorPrecedenceLevel(op2);
144 if (prec1 == prec2)
145 return 0;
146 if (prec1 > prec2)
147 return -1;
148 return 1;
149}
150
151QTextStream &PrettyPretty::operator () (AST::Node *node, int level)
152{
153 int was = indentLevel(level);
154 accept(node);
155 indentLevel(was);
156 return out;
157}
158
159QTextStream &PrettyPretty::newlineAndIndent()
160{
161 enum { IND = 4 };
162 out << endl << QString().fill(QLatin1Char(' '), m_indentLevel * IND);
163 return out;
164}
165
166void PrettyPretty::accept(AST::Node *node)
167{
168 AST::Node::acceptChild(node, this);
169}
170
171bool PrettyPretty::visit(AST::ThisExpression *node)
172{
173 Q_UNUSED(node);
174 out << "this";
175 return true;
176}
177
178void PrettyPretty::endVisit(AST::ThisExpression *node)
179{
180 Q_UNUSED(node);
181}
182
183bool PrettyPretty::visit(AST::IdentifierExpression *node)
184{
185 out << QScriptEnginePrivate::toString(node->name);
186 return true;
187}
188
189void PrettyPretty::endVisit(AST::IdentifierExpression *node)
190{
191 Q_UNUSED(node);
192}
193
194bool PrettyPretty::visit(AST::NullExpression *node)
195{
196 Q_UNUSED(node);
197 out << "null";
198 return false;
199}
200
201void PrettyPretty::endVisit(AST::NullExpression *node)
202{
203 Q_UNUSED(node);
204}
205
206bool PrettyPretty::visit(AST::TrueLiteral *node)
207{
208 Q_UNUSED(node);
209 out << "true";
210 return false;
211}
212
213void PrettyPretty::endVisit(AST::TrueLiteral *node)
214{
215 Q_UNUSED(node);
216}
217
218bool PrettyPretty::visit(AST::FalseLiteral *node)
219{
220 Q_UNUSED(node);
221 out << "false";
222 return false;
223}
224
225void PrettyPretty::endVisit(AST::FalseLiteral *node)
226{
227 Q_UNUSED(node);
228}
229
230bool PrettyPretty::visit(AST::StringLiteral *node)
231{
232 QString lit = QScriptEnginePrivate::toString(node->value);
233 lit.replace(QLatin1String("\\"), QLatin1String("\\\\"));
234 out << "\"" << lit << "\"";
235 return false;
236}
237
238void PrettyPretty::endVisit(AST::StringLiteral *node)
239{
240 Q_UNUSED(node);
241}
242
243bool PrettyPretty::visit(AST::NumericLiteral *node)
244{
245 out << QScript::numberToString(node->value);
246 return true;
247}
248
249void PrettyPretty::endVisit(AST::NumericLiteral *node)
250{
251 Q_UNUSED(node);
252}
253
254bool PrettyPretty::visit(AST::RegExpLiteral *node)
255{
256 out << "/" << QScriptEnginePrivate::toString(node->pattern) << "/";
257 if (node->flags)
258 out << QScript::Ecma::RegExp::flagsToString(node->flags);
259
260 return true;
261}
262
263void PrettyPretty::endVisit(AST::RegExpLiteral *node)
264{
265 Q_UNUSED(node);
266}
267
268bool PrettyPretty::visit(AST::ArrayLiteral *node)
269{
270 out << "[";
271 accept(node->elements);
272 accept(node->elision);
273 out << "]";
274 return false;
275}
276
277void PrettyPretty::endVisit(AST::ArrayLiteral *node)
278{
279 Q_UNUSED(node);
280}
281
282bool PrettyPretty::visit(AST::ObjectLiteral *node)
283{
284 out << "{";
285 if (node->properties) {
286 pushIndentLevel();
287 AST::PropertyNameAndValueList *prop;
288 for (prop = node->properties; prop != 0; prop = prop->next) {
289 newlineAndIndent();
290 accept(prop);
291 if (prop->next)
292 out << ",";
293 }
294 popIndentLevel();
295 newlineAndIndent();
296 }
297 out << "}";
298 return false;
299}
300
301void PrettyPretty::endVisit(AST::ObjectLiteral *node)
302{
303 Q_UNUSED(node);
304}
305
306bool PrettyPretty::visit(AST::ElementList *node)
307{
308 accept(node->elision);
309 accept(node->expression);
310 for (node = node->next; node != 0; node = node->next) {
311 out << ", ";
312 accept(node->elision);
313 accept(node->expression);
314 }
315 return false;
316}
317
318void PrettyPretty::endVisit(AST::ElementList *node)
319{
320 Q_UNUSED(node);
321}
322
323bool PrettyPretty::visit(AST::Elision *node)
324{
325 out << ", ";
326 for (AST::Elision *eit = node->next; eit != 0; eit = eit->next)
327 out << ", ";
328 return false;
329}
330
331void PrettyPretty::endVisit(AST::Elision *node)
332{
333 Q_UNUSED(node);
334}
335
336bool PrettyPretty::visit(AST::PropertyNameAndValueList *node)
337{
338 accept(node->name);
339 out << ": ";
340 accept(node->value);
341 return false;
342}
343
344void PrettyPretty::endVisit(AST::PropertyNameAndValueList *node)
345{
346 Q_UNUSED(node);
347}
348
349bool PrettyPretty::visit(AST::IdentifierPropertyName *node)
350{
351 out << QScriptEnginePrivate::toString(node->id);
352 return false;
353}
354
355void PrettyPretty::endVisit(AST::IdentifierPropertyName *node)
356{
357 Q_UNUSED(node);
358}
359
360bool PrettyPretty::visit(AST::StringLiteralPropertyName *node)
361{
362 QString lit = QScriptEnginePrivate::toString(node->id);
363 lit.replace(QLatin1String("\\"), QLatin1String("\\\\"));
364 out << lit;
365 return false;
366}
367
368void PrettyPretty::endVisit(AST::StringLiteralPropertyName *node)
369{
370 Q_UNUSED(node);
371}
372
373bool PrettyPretty::visit(AST::NumericLiteralPropertyName *node)
374{
375 out << node->id;
376 return false;
377}
378
379void PrettyPretty::endVisit(AST::NumericLiteralPropertyName *node)
380{
381 Q_UNUSED(node);
382}
383
384bool PrettyPretty::visit(AST::ArrayMemberExpression *node)
385{
386 accept(node->base);
387 out << "[";
388 accept(node->expression);
389 out << "]";
390 return false;
391}
392
393void PrettyPretty::endVisit(AST::ArrayMemberExpression *node)
394{
395 Q_UNUSED(node);
396}
397
398bool PrettyPretty::visit(AST::FieldMemberExpression *node)
399{
400 accept(node->base);
401 out << "." << QScriptEnginePrivate::toString(node->name);
402 return false;
403}
404
405void PrettyPretty::endVisit(AST::FieldMemberExpression *node)
406{
407 Q_UNUSED(node);
408}
409
410bool PrettyPretty::visit(AST::NewMemberExpression *node)
411{
412 out << "new ";
413 accept(node->base);
414 out << "(";
415 accept(node->arguments);
416 out << ")";
417 return false;
418}
419
420void PrettyPretty::endVisit(AST::NewMemberExpression *node)
421{
422 Q_UNUSED(node);
423}
424
425bool PrettyPretty::visit(AST::NewExpression *node)
426{
427 Q_UNUSED(node);
428 out << "new ";
429 return true;
430}
431
432void PrettyPretty::endVisit(AST::NewExpression *node)
433{
434 Q_UNUSED(node);
435}
436
437bool PrettyPretty::visit(AST::CallExpression *node)
438{
439 accept(node->base);
440 out << "(";
441 accept(node->arguments);
442 out << ")";
443 return false;
444}
445
446void PrettyPretty::endVisit(AST::CallExpression *node)
447{
448 Q_UNUSED(node);
449}
450
451bool PrettyPretty::visit(AST::ArgumentList *node)
452{
453 accept(node->expression);
454 for (node = node->next; node != 0; node = node->next) {
455 out << ", ";
456 accept(node->expression);
457 }
458 return false;
459}
460
461void PrettyPretty::endVisit(AST::ArgumentList *node)
462{
463 Q_UNUSED(node);
464}
465
466bool PrettyPretty::visit(AST::PostIncrementExpression *node)
467{
468 Q_UNUSED(node);
469 return true;
470}
471
472void PrettyPretty::endVisit(AST::PostIncrementExpression *node)
473{
474 Q_UNUSED(node);
475 out << "++";
476}
477
478bool PrettyPretty::visit(AST::PostDecrementExpression *node)
479{
480 Q_UNUSED(node);
481 return true;
482}
483
484void PrettyPretty::endVisit(AST::PostDecrementExpression *node)
485{
486 Q_UNUSED(node);
487 out << "--";
488}
489
490bool PrettyPretty::visit(AST::DeleteExpression *node)
491{
492 Q_UNUSED(node);
493 out << "delete ";
494 return true;
495}
496
497void PrettyPretty::endVisit(AST::DeleteExpression *node)
498{
499 Q_UNUSED(node);
500}
501
502bool PrettyPretty::visit(AST::VoidExpression *node)
503{
504 Q_UNUSED(node);
505 out << "void ";
506 return true;
507}
508
509void PrettyPretty::endVisit(AST::VoidExpression *node)
510{
511 Q_UNUSED(node);
512}
513
514bool PrettyPretty::visit(AST::TypeOfExpression *node)
515{
516 Q_UNUSED(node);
517 out << "typeof ";
518 return true;
519}
520
521void PrettyPretty::endVisit(AST::TypeOfExpression *node)
522{
523 Q_UNUSED(node);
524}
525
526bool PrettyPretty::visit(AST::PreIncrementExpression *node)
527{
528 Q_UNUSED(node);
529 out << "++";
530 return true;
531}
532
533void PrettyPretty::endVisit(AST::PreIncrementExpression *node)
534{
535 Q_UNUSED(node);
536}
537
538bool PrettyPretty::visit(AST::PreDecrementExpression *node)
539{
540 Q_UNUSED(node);
541 out << "--";
542 return true;
543}
544
545void PrettyPretty::endVisit(AST::PreDecrementExpression *node)
546{
547 Q_UNUSED(node);
548}
549
550bool PrettyPretty::visit(AST::UnaryPlusExpression *node)
551{
552 out << "+";
553 bool needParens = (node->expression->binaryExpressionCast() != 0);
554 if (needParens)
555 out << "(";
556 accept(node->expression);
557 if (needParens)
558 out << ")";
559 return false;
560}
561
562void PrettyPretty::endVisit(AST::UnaryPlusExpression *node)
563{
564 Q_UNUSED(node);
565}
566
567bool PrettyPretty::visit(AST::UnaryMinusExpression *node)
568{
569 out << "-";
570 bool needParens = (node->expression->binaryExpressionCast() != 0);
571 if (needParens)
572 out << "(";
573 accept(node->expression);
574 if (needParens)
575 out << ")";
576 return false;
577}
578
579void PrettyPretty::endVisit(AST::UnaryMinusExpression *node)
580{
581 Q_UNUSED(node);
582}
583
584bool PrettyPretty::visit(AST::TildeExpression *node)
585{
586 out << "~";
587 bool needParens = (node->expression->binaryExpressionCast() != 0);
588 if (needParens)
589 out << "(";
590 accept(node->expression);
591 if (needParens)
592 out << ")";
593 return false;
594}
595
596void PrettyPretty::endVisit(AST::TildeExpression *node)
597{
598 Q_UNUSED(node);
599}
600
601bool PrettyPretty::visit(AST::NotExpression *node)
602{
603 out << "!";
604 bool needParens = (node->expression->binaryExpressionCast() != 0);
605 if (needParens)
606 out << "(";
607 accept(node->expression);
608 if (needParens)
609 out << ")";
610 return false;
611}
612
613void PrettyPretty::endVisit(AST::NotExpression *node)
614{
615 Q_UNUSED(node);
616}
617
618bool PrettyPretty::visit(AST::BinaryExpression *node)
619{
620 bool needParens = node->left->binaryExpressionCast()
621 && (compareOperatorPrecedence(node->left->binaryExpressionCast()->op, node->op) < 0);
622 if (needParens)
623 out << "(";
624 accept(node->left);
625 if (needParens)
626 out << ")";
627 QString s;
628 switch (node->op) {
629 case QSOperator::Add:
630 s = QLatin1String("+"); break;
631 case QSOperator::And:
632 s = QLatin1String("&&"); break;
633 case QSOperator::InplaceAnd:
634 s = QLatin1String("&="); break;
635 case QSOperator::Assign:
636 s = QLatin1String("="); break;
637 case QSOperator::BitAnd:
638 s = QLatin1String("&"); break;
639 case QSOperator::BitOr:
640 s = QLatin1String("|"); break;
641 case QSOperator::BitXor:
642 s = QLatin1String("^"); break;
643 case QSOperator::InplaceSub:
644 s = QLatin1String("-="); break;
645 case QSOperator::Div:
646 s = QLatin1String("/"); break;
647 case QSOperator::InplaceDiv:
648 s = QLatin1String("/="); break;
649 case QSOperator::Equal:
650 s = QLatin1String("=="); break;
651 case QSOperator::Ge:
652 s = QLatin1String(">="); break;
653 case QSOperator::Gt:
654 s = QLatin1String(">"); break;
655 case QSOperator::In:
656 s = QLatin1String("in"); break;
657 case QSOperator::InplaceAdd:
658 s = QLatin1String("+="); break;
659 case QSOperator::InstanceOf:
660 s = QLatin1String("instanceof"); break;
661 case QSOperator::Le:
662 s = QLatin1String("<="); break;
663 case QSOperator::LShift:
664 s = QLatin1String("<<"); break;
665 case QSOperator::InplaceLeftShift:
666 s = QLatin1String("<<="); break;
667 case QSOperator::Lt:
668 s = QLatin1String("<"); break;
669 case QSOperator::Mod:
670 s = QLatin1String("%"); break;
671 case QSOperator::InplaceMod:
672 s = QLatin1String("%="); break;
673 case QSOperator::Mul:
674 s = QLatin1String("*"); break;
675 case QSOperator::InplaceMul:
676 s = QLatin1String("*="); break;
677 case QSOperator::NotEqual:
678 s = QLatin1String("!="); break;
679 case QSOperator::Or:
680 s = QLatin1String("||"); break;
681 case QSOperator::InplaceOr:
682 s = QLatin1String("|="); break;
683 case QSOperator::RShift:
684 s = QLatin1String(">>"); break;
685 case QSOperator::InplaceRightShift:
686 s = QLatin1String(">>="); break;
687 case QSOperator::StrictEqual:
688 s = QLatin1String("==="); break;
689 case QSOperator::StrictNotEqual:
690 s = QLatin1String("!=="); break;
691 case QSOperator::Sub:
692 s = QLatin1String("-"); break;
693 case QSOperator::URShift:
694 s = QLatin1String(">>>"); break;
695 case QSOperator::InplaceURightShift:
696 s = QLatin1String(">>>="); break;
697 case QSOperator::InplaceXor:
698 s = QLatin1String("^="); break;
699 default:
700 Q_ASSERT (0);
701 }
702 out << " " << s << " ";
703 needParens = node->right->binaryExpressionCast()
704 && (compareOperatorPrecedence(node->right->binaryExpressionCast()->op, node->op) <= 0);
705 if (needParens)
706 out << "(";
707 accept(node->right);
708 if (needParens)
709 out << ")";
710 return false;
711}
712
713void PrettyPretty::endVisit(AST::BinaryExpression *node)
714{
715 Q_UNUSED(node);
716}
717
718bool PrettyPretty::visit(AST::ConditionalExpression *node)
719{
720 accept(node->expression);
721 out << " ? ";
722 accept(node->ok);
723 out << " : ";
724 accept(node->ko);
725 return false;
726}
727
728void PrettyPretty::endVisit(AST::ConditionalExpression *node)
729{
730 Q_UNUSED(node);
731}