1 /**************************************************************************
3 ** This file is part of Qt Creator
5 ** Copyright (c) 2011 Nokia Corporation and/or its subsidiary(-ies).
7 ** Contact: Nokia Corporation (info@qt.nokia.com)
10 ** GNU Lesser General Public License Usage
12 ** This file may be used under the terms of the GNU Lesser General Public
13 ** License version 2.1 as published by the Free Software Foundation and
14 ** appearing in the file LICENSE.LGPL included in the packaging of this file.
15 ** Please review the following information to ensure the GNU Lesser General
16 ** Public License version 2.1 requirements will be met:
17 ** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
19 ** In addition, as a special exception, Nokia gives you certain additional
20 ** rights. These rights are described in the Nokia Qt LGPL Exception
21 ** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
25 ** Alternatively, this file may be used in accordance with the terms and
26 ** conditions contained in a signed written agreement between you and Nokia.
28 ** If you have questions regarding the use of this file, please contact
29 ** Nokia at qt-info@nokia.com.
31 **************************************************************************/
33 #include <qmljs/parser/qmljsast_p.h>
34 #include <qmljs/parser/qmljsastvisitor_p.h>
35 #include <qmljs/qmljsdocument.h>
39 #include <QCoreApplication>
40 #include <QStringList>
53 using namespace QmlJS;
54 using namespace QmlJS::AST;
57 class ASTDump: protected Visitor
60 void operator()(const QString &fileName, const QByteArray &src, Node *ast) {
62 QString basename = fileName;
63 int dotIdx = basename.lastIndexOf('.');
65 basename.truncate(dotIdx);
66 basename.append(QLatin1String(".ast.dot"));
67 out.open(basename.toUtf8().constData());
69 out << "digraph AST { ordering=out;" << endl;
70 // cout << "rankdir = \"LR\";" << endl;
71 Node::accept(ast, this);
73 typedef QPair<QByteArray, QByteArray> Pair;
75 foreach (const Pair &conn, _connections)
76 out << conn.first.constData() << " -> " << conn.second.constData() << endl;
82 cout << qPrintable(basename) << endl;
86 void alignTerminals() {
87 out<<"{ rank=same;" << endl;
88 foreach (const QByteArray &terminalShape, _terminalShapes) {
89 out << " " << string(terminalShape) << ";" << endl;
94 static QByteArray name(Node *ast) {
96 QByteArray name = abi::__cxa_demangle(typeid(*ast).name(), 0, 0, 0) + 12;
98 QByteArray name = typeid(*ast).name();
103 QString spell(const SourceLocation &token) {
104 return _src.mid(token.offset, token.length).replace('\'', "\\\\").replace('"', "\\\"");
107 void terminal(const SourceLocation &token) {
108 if (!token.isValid())
111 static int count = 1;
112 QByteArray id = 't' + QByteArray::number(count++);
113 Node *node = _stack.last();
114 _connections.append(qMakePair(_id[node], id));
118 t.append(" [label = \"");
119 t.append(spell(token).toUtf8());
120 t.append("\" shape=rect]");
121 _terminalShapes.append(t);
124 virtual void nonterminal(Node *ast) {
125 Node::accept(ast, this);
128 virtual void node(Node *ast) {
129 out << _id[ast].constData() << " [label=\"" << name(ast).constData() << "\"];" << endl;
132 virtual bool preVisit(Node *ast) {
133 static int count = 1;
134 const QByteArray id = 'n' + QByteArray::number(count++);
138 if (! _stack.isEmpty())
139 _connections.append(qMakePair(_id[_stack.last()], id));
148 virtual void postVisit(Node *) {
152 protected: // visiting methods:
153 virtual bool visit(UiImport *ast) {
154 terminal(ast->importToken);
157 nonterminal(ast->importUri);
159 terminal(ast->fileNameToken);
161 terminal(ast->versionToken);
162 terminal(ast->asToken);
163 terminal(ast->importIdToken);
164 terminal(ast->semicolonToken);
168 virtual bool visit(UiObjectBinding *ast) {
169 if (ast->hasOnToken) {
170 nonterminal(ast->qualifiedTypeNameId);
171 terminal(ast->colonToken);
172 nonterminal(ast->qualifiedId);
174 nonterminal(ast->qualifiedId);
175 terminal(ast->colonToken);
176 nonterminal(ast->qualifiedTypeNameId);
178 nonterminal(ast->initializer);
182 virtual bool visit(UiObjectDefinition *ast) {
183 nonterminal(ast->qualifiedTypeNameId);
184 nonterminal(ast->initializer);
188 virtual bool visit(UiObjectInitializer *ast) {
189 terminal(ast->lbraceToken);
190 nonterminal(ast->members);
191 terminal(ast->rbraceToken);
195 virtual bool visit(UiScriptBinding *ast) {
196 nonterminal(ast->qualifiedId);
197 terminal(ast->colonToken);
198 nonterminal(ast->statement);
202 virtual bool visit(UiArrayBinding *ast) {
203 nonterminal(ast->qualifiedId);
204 terminal(ast->colonToken);
205 terminal(ast->lbracketToken);
206 nonterminal(ast->members);
207 terminal(ast->rbracketToken);
211 virtual bool visit(UiArrayMemberList *ast) {
212 terminal(ast->commaToken);
213 nonterminal(ast->member);
214 nonterminal(ast->next);
218 virtual bool visit(UiQualifiedId *ast) {
219 terminal(ast->identifierToken);
220 nonterminal(ast->next);
224 virtual bool visit(UiPublicMember *ast) {
225 // TODO: place the parameters...
226 // UiParameterList *parameters;
228 terminal(ast->defaultToken);
229 terminal(ast->readonlyToken);
230 terminal(ast->propertyToken);
231 terminal(ast->typeModifierToken);
232 terminal(ast->typeToken);
233 terminal(ast->identifierToken);
234 terminal(ast->colonToken);
235 nonterminal(ast->expression);
236 nonterminal(ast->binding);
237 terminal(ast->semicolonToken);
241 virtual bool visit(UiFormal *ast) { terminal(ast->identifierToken); terminal(ast->asToken); terminal(ast->aliasToken); return false; }
242 virtual bool visit(UiSignature *ast) { terminal(ast->lparenToken); nonterminal(ast->formals); terminal(ast->rparenToken); return false; }
244 virtual bool visit(StringLiteral *ast) { terminal(ast->literalToken); return false; }
245 virtual bool visit(NumericLiteral *ast) { terminal(ast->literalToken); return false; }
246 virtual bool visit(TrueLiteral *ast) { terminal(ast->trueToken); return false; }
247 virtual bool visit(FalseLiteral *ast) { terminal(ast->falseToken); return false; }
248 virtual bool visit(IdentifierExpression *ast) { terminal(ast->identifierToken); return false; }
249 virtual bool visit(FieldMemberExpression *ast) { nonterminal(ast->base); terminal(ast->dotToken); terminal(ast->identifierToken); return false; }
250 virtual bool visit(BinaryExpression *ast) { nonterminal(ast->left); terminal(ast->operatorToken); nonterminal(ast->right); return false; }
251 virtual bool visit(UnaryPlusExpression *ast) { terminal(ast->plusToken); nonterminal(ast->expression); return false; }
252 virtual bool visit(UnaryMinusExpression *ast) { terminal(ast->minusToken); nonterminal(ast->expression); return false; }
253 virtual bool visit(NestedExpression *ast) { terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); return false; }
254 virtual bool visit(ThisExpression *ast) { terminal(ast->thisToken); return false; }
255 virtual bool visit(NullExpression *ast) { terminal(ast->nullToken); return false; }
256 virtual bool visit(RegExpLiteral *ast) { terminal(ast->literalToken); return false; }
257 virtual bool visit(ArrayLiteral *ast) { terminal(ast->lbracketToken); nonterminal(ast->elements); terminal(ast->commaToken); nonterminal(ast->elision); terminal(ast->rbracketToken); return false; }
258 virtual bool visit(ObjectLiteral *ast) { terminal(ast->lbraceToken); nonterminal(ast->properties); terminal(ast->rbraceToken); return false; }
259 virtual bool visit(ElementList *ast) { nonterminal(ast->next); terminal(ast->commaToken); nonterminal(ast->elision); nonterminal(ast->expression); return false; }
260 virtual bool visit(Elision *ast) { nonterminal(ast->next); terminal(ast->commaToken); return false; }
261 virtual bool visit(PropertyNameAndValueList *ast) { nonterminal(ast->name); terminal(ast->colonToken); nonterminal(ast->value); terminal(ast->commaToken); nonterminal(ast->next); return false; }
262 virtual bool visit(IdentifierPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
263 virtual bool visit(StringLiteralPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
264 virtual bool visit(NumericLiteralPropertyName *ast) { terminal(ast->propertyNameToken); return false; }
265 virtual bool visit(ArrayMemberExpression *ast) { nonterminal(ast->base); terminal(ast->lbracketToken); nonterminal(ast->expression); terminal(ast->rbracketToken); return false; }
266 virtual bool visit(NewMemberExpression *ast) { terminal(ast->newToken); nonterminal(ast->base); terminal(ast->lparenToken); nonterminal(ast->arguments); terminal(ast->rparenToken); return false; }
267 virtual bool visit(NewExpression *ast) { terminal(ast->newToken); nonterminal(ast->expression); return false; }
268 virtual bool visit(CallExpression *ast) { nonterminal(ast->base); terminal(ast->lparenToken); nonterminal(ast->arguments); terminal(ast->rparenToken); return false; }
269 virtual bool visit(ArgumentList *ast) { nonterminal(ast->expression); terminal(ast->commaToken); nonterminal(ast->next); return false; }
270 virtual bool visit(PostIncrementExpression *ast) { nonterminal(ast->base); terminal(ast->incrementToken); return false; }
271 virtual bool visit(PostDecrementExpression *ast) { nonterminal(ast->base); terminal(ast->decrementToken); return false; }
272 virtual bool visit(DeleteExpression *ast) { terminal(ast->deleteToken); nonterminal(ast->expression); return false; }
273 virtual bool visit(VoidExpression *ast) { terminal(ast->voidToken); nonterminal(ast->expression); return false; }
274 virtual bool visit(TypeOfExpression *ast) { terminal(ast->typeofToken); nonterminal(ast->expression); return false; }
275 virtual bool visit(PreIncrementExpression *ast) { terminal(ast->incrementToken); nonterminal(ast->expression); return false; }
276 virtual bool visit(PreDecrementExpression *ast) { terminal(ast->decrementToken); nonterminal(ast->expression); return false; }
277 virtual bool visit(TildeExpression *ast) { terminal(ast->tildeToken); nonterminal(ast->expression); return false; }
278 virtual bool visit(NotExpression *ast) { terminal(ast->notToken); nonterminal(ast->expression); return false; }
279 virtual bool visit(ConditionalExpression *ast) { nonterminal(ast->expression); terminal(ast->questionToken); nonterminal(ast->ok); terminal(ast->colonToken); nonterminal(ast->ko); return false; }
280 virtual bool visit(Expression *ast) { nonterminal(ast->left); terminal(ast->commaToken); nonterminal(ast->right); return false; }
281 virtual bool visit(Block *ast) { terminal(ast->lbraceToken); nonterminal(ast->statements); terminal(ast->rbraceToken); return false; }
282 virtual bool visit(VariableStatement *ast) { terminal(ast->declarationKindToken); nonterminal(ast->declarations); terminal(ast->semicolonToken); return false; }
283 virtual bool visit(VariableDeclaration *ast) { terminal(ast->identifierToken); nonterminal(ast->expression); return false; }
284 virtual bool visit(VariableDeclarationList *ast) { nonterminal(ast->declaration); terminal(ast->commaToken); nonterminal(ast->next); return false; }
285 virtual bool visit(EmptyStatement* ast) { terminal(ast->semicolonToken); return false; }
286 virtual bool visit(ExpressionStatement *ast) { nonterminal(ast->expression); terminal(ast->semicolonToken); return false; }
287 virtual bool visit(IfStatement *ast) { terminal(ast->ifToken); terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); nonterminal(ast->ok); terminal(ast->elseToken); nonterminal(ast->ko); return false; }
288 virtual bool visit(DoWhileStatement *ast) { terminal(ast->doToken); nonterminal(ast->statement); terminal(ast->whileToken); terminal(ast->lparenToken); nonterminal(ast->expression); terminal(ast->rparenToken); terminal(ast->semicolonToken); return false; }
290 // TODO: visitors for:
295 // LocalForEachStatement
309 // FunctionExpression
310 // FunctionDeclaration
315 QHash<Node *, QByteArray> _id;
316 QList<QPair<QByteArray, QByteArray> > _connections;
317 QList<Node *> _stack;
318 QList<QByteArray> _terminalShapes;
323 int main(int argc, char *argv[])
325 QCoreApplication app(argc, argv);
327 QStringList files = app.arguments();
330 foreach (const QString &fileName, files) {
331 QFile file(fileName);
332 if (! file.open(QFile::ReadOnly)) {
333 cerr << "Cannot open \"" << qPrintable(fileName)
334 << "\", skipping it." << endl;
338 const QByteArray source = file.readAll();
341 Document::Ptr doc = Document::create(fileName);
342 doc->setSource(source);
345 foreach (const DiagnosticMessage &m, doc->diagnosticMessages()) {
356 *os << m.loc.startLine << ':' << m.loc.startColumn << ':';
358 *os << qPrintable(m.message) << endl;
362 dump(fileName, source, doc->qmlProgram());