diff options
author | Kai Koehne <kai.koehne@nokia.com> | 2010-01-07 12:14:35 +0100 |
---|---|---|
committer | Kai Koehne <kai.koehne@nokia.com> | 2010-01-07 12:14:35 +0100 |
commit | 818a7b226bb79fe6e7e82d25ad329419c931287c (patch) | |
tree | aa6e11b64a22bdbda9c74b1c31fe7f39dd5e6eab /src/plugins/qmldesigner/core/filemanager | |
parent | ae535daa20eecc9feb07941caf65f2966fb8f9b5 (diff) | |
download | qt-creator-818a7b226bb79fe6e7e82d25ad329419c931287c.tar.gz |
New QmlDesigner plugin & Design mode
This adds a new "Design" mode that can be used to manipulate qml files
in a visual way. It will only get build if you have the declarativeui
module in Qt.
This is a squashed import from the Bauhaus project. Share & enjoy :)
Diffstat (limited to 'src/plugins/qmldesigner/core/filemanager')
61 files changed, 17023 insertions, 0 deletions
diff --git a/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.cpp b/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.cpp new file mode 100644 index 0000000000..026591f85f --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.cpp @@ -0,0 +1,118 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +#include "addarraymembervisitor.h" + +using namespace QmlEditor; +using namespace QmlEditor::Internal; +using namespace QmlJS; +using namespace QmlJS::AST; + +AddArrayMemberVisitor::AddArrayMemberVisitor(QmlDesigner::TextModifier &modifier, + quint32 parentLocation, + const QString &propertyName, + const QString &content): + QMLRewriter(modifier), + m_parentLocation(parentLocation), + m_propertyName(propertyName), + m_content(content), + m_convertObjectBindingIntoArrayBinding(false) +{ +} + +void AddArrayMemberVisitor::findArrayBindingAndInsert(const QString &m_propertyName, UiObjectMemberList *ast) +{ + for (UiObjectMemberList *iter = ast; iter; iter = iter->next) { + if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(iter->member)) { + if (flatten(arrayBinding->qualifiedId) == m_propertyName) + insertInto(arrayBinding); + } else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(iter->member)) { + if (flatten(objectBinding->qualifiedId) == m_propertyName && willConvertObjectBindingIntoArrayBinding()) + convertAndAdd(objectBinding); + } + } +} + +bool AddArrayMemberVisitor::visit(QmlJS::AST::UiObjectBinding *ast) +{ + if (didRewriting()) + return false; + + if (ast->firstSourceLocation().offset == m_parentLocation) + findArrayBindingAndInsert(m_propertyName, ast->initializer->members); + + return !didRewriting(); +} + +bool AddArrayMemberVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) +{ + if (didRewriting()) + return false; + + if (ast->firstSourceLocation().offset == m_parentLocation) + findArrayBindingAndInsert(m_propertyName, ast->initializer->members); + + return !didRewriting(); +} + +void AddArrayMemberVisitor::insertInto(QmlJS::AST::UiArrayBinding *arrayBinding) +{ + UiObjectMember *lastMember = 0; + for (UiArrayMemberList *iter = arrayBinding->members; iter; iter = iter->next) + if (iter->member) + lastMember = iter->member; + + if (!lastMember) + return; // an array binding cannot be empty, so there will (or should) always be a last member. + + const int insertionPoint = lastMember->lastSourceLocation().end(); + const int indentDepth = calculateIndentDepth(lastMember->firstSourceLocation()); + + replace(insertionPoint, 0, QLatin1String(",\n") + addIndentation(m_content, indentDepth)); + + setDidRewriting(true); +} + +void AddArrayMemberVisitor::convertAndAdd(QmlJS::AST::UiObjectBinding *objectBinding) +{ + const int indentDepth = calculateIndentDepth(objectBinding->firstSourceLocation()); + const QString arrayPrefix = QLatin1String("[\n") + addIndentation(QLatin1String(""), indentDepth); + replace(objectBinding->qualifiedTypeNameId->identifierToken.offset, 0, arrayPrefix); + const int insertionPoint = objectBinding->lastSourceLocation().end(); + replace(insertionPoint, 0, + QLatin1String(",\n") + + addIndentation(m_content, indentDepth) + QLatin1Char('\n') + + addIndentation(QLatin1String("]"), indentDepth) + ); + + setDidRewriting(true); +} diff --git a/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.h b/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.h new file mode 100644 index 0000000000..2b59521574 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/addarraymembervisitor.h @@ -0,0 +1,72 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef ADDARRAYMEMBERVISITOR_H +#define ADDARRAYMEMBERVISITOR_H + +#include "qmlrewriter.h" + +namespace QmlEditor { +namespace Internal { + +class AddArrayMemberVisitor: public QMLRewriter +{ +public: + AddArrayMemberVisitor(QmlDesigner::TextModifier &modifier, + quint32 parentLocation, + const QString &propertyName, + const QString &content); + + bool willConvertObjectBindingIntoArrayBinding() const + { return m_convertObjectBindingIntoArrayBinding; } + + void setConvertObjectBindingIntoArrayBinding(bool convertObjectBindingIntoArrayBinding) + { m_convertObjectBindingIntoArrayBinding = convertObjectBindingIntoArrayBinding; } + +protected: + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + +private: + void findArrayBindingAndInsert(const QString &m_propertyName, QmlJS::AST::UiObjectMemberList *ast); + + void insertInto(QmlJS::AST::UiArrayBinding *arrayBinding); + void convertAndAdd(QmlJS::AST::UiObjectBinding *objectBinding); + +private: + quint32 m_parentLocation; + QString m_propertyName; + QString m_content; + bool m_convertObjectBindingIntoArrayBinding; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // ADDARRAYMEMBERVISITOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.cpp new file mode 100644 index 0000000000..a9b5c9ad32 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.cpp @@ -0,0 +1,93 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +#include "addobjectvisitor.h" + +using namespace QmlEditor; +using namespace QmlEditor::Internal; +using namespace QmlJS; +using namespace QmlJS::AST; + +AddObjectVisitor::AddObjectVisitor(QmlDesigner::TextModifier &modifier, + quint32 parentLocation, + const QString &content, + const QStringList &propertyOrder): + QMLRewriter(modifier), + m_parentLocation(parentLocation), + m_content(content), + m_propertyOrder(propertyOrder) +{ +} + +bool AddObjectVisitor::visit(QmlJS::AST::UiObjectBinding *ast) +{ + if (didRewriting()) + return false; + + if (ast->qualifiedTypeNameId->identifierToken.offset == m_parentLocation) + insertInto(ast->initializer); + + return !didRewriting(); +} + +bool AddObjectVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) +{ + if (didRewriting()) + return false; + + if (ast->firstSourceLocation().offset == m_parentLocation) + insertInto(ast->initializer); + + return !didRewriting(); +} + +void AddObjectVisitor::insertInto(QmlJS::AST::UiObjectInitializer *ast) +{ + UiObjectMemberList *insertAfter = searchMemberToInsertAfter(ast->members, QString::null, m_propertyOrder); + + int insertionPoint; + int indentDepth; + QString textToInsert; + if (insertAfter && insertAfter->member) { + insertionPoint = insertAfter->member->lastSourceLocation().end(); + indentDepth = calculateIndentDepth(insertAfter->member->lastSourceLocation()); + textToInsert += QLatin1String("\n"); + } else { + insertionPoint = ast->lbraceToken.end(); + indentDepth = calculateIndentDepth(ast->lbraceToken) + 4; + } + + textToInsert += addIndentation(m_content, indentDepth); + replace(insertionPoint, 0, QLatin1String("\n") + textToInsert); + + setDidRewriting(true); +} diff --git a/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.h b/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.h new file mode 100644 index 0000000000..4a3097ffa5 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/addobjectvisitor.h @@ -0,0 +1,62 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef ADDOBJECTVISITOR_H +#define ADDOBJECTVISITOR_H + +#include "qmlrewriter.h" + +namespace QmlEditor { +namespace Internal { + +class AddObjectVisitor: public QMLRewriter +{ +public: + AddObjectVisitor(QmlDesigner::TextModifier &modifier, + quint32 parentLocation, + const QString &content, + const QStringList &propertyOrder); + +protected: + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + +private: + void insertInto(QmlJS::AST::UiObjectInitializer *ast); + +private: + quint32 m_parentLocation; + QString m_content; + QStringList m_propertyOrder; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // ADDOBJECTVISITOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.cpp new file mode 100644 index 0000000000..b93792e563 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.cpp @@ -0,0 +1,136 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +#include "addpropertyvisitor.h" + +using namespace QmlEditor; +using namespace QmlEditor::Internal; +using namespace QmlJS; +using namespace QmlJS::AST; + +AddPropertyVisitor::AddPropertyVisitor(QmlDesigner::TextModifier &modifier, + quint32 parentLocation, + const QString &name, + const QString &value, + QmlRefactoring::PropertyType propertyType, + const QStringList &propertyOrder): + QMLRewriter(modifier), + m_parentLocation(parentLocation), + m_name(name), + m_value(value), + m_propertyType(propertyType), + m_propertyOrder(propertyOrder) +{ +} + +bool AddPropertyVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) +{ + if (didRewriting()) + return false; + + if (ast->firstSourceLocation().offset == m_parentLocation) { + addInMembers(ast->initializer); + return false; + } + + return !didRewriting(); +} + +bool AddPropertyVisitor::visit(QmlJS::AST::UiObjectBinding *ast) +{ + if (didRewriting()) + return false; + + if (ast->qualifiedTypeNameId->identifierToken.offset == m_parentLocation) { + addInMembers(ast->initializer); + return false; + } + + return !didRewriting(); +} + +void AddPropertyVisitor::addInMembers(QmlJS::AST::UiObjectInitializer *initializer) +{ + UiObjectMemberList *insertAfter = searchMemberToInsertAfter(initializer->members, m_name, m_propertyOrder); + SourceLocation endOfPreviousMember; + SourceLocation startOfNextMember; + unsigned indentDepth; + + if (insertAfter == 0 || insertAfter->member == 0) { + // insert as first member + endOfPreviousMember = initializer->lbraceToken; + + if (initializer->members && initializer->members->member) + startOfNextMember = initializer->members->member->firstSourceLocation(); + else + startOfNextMember = initializer->rbraceToken; + + indentDepth = calculateIndentDepth(endOfPreviousMember) + 4; + } else { + endOfPreviousMember = insertAfter->member->lastSourceLocation(); + + if (insertAfter->next && insertAfter->next->member) + startOfNextMember = insertAfter->next->member->firstSourceLocation(); + else + startOfNextMember = initializer->rbraceToken; + + indentDepth = calculateIndentDepth(endOfPreviousMember); + } + + QString newPropertyTemplate; + switch (m_propertyType) { + case QmlRefactoring::ArrayBinding: + newPropertyTemplate = QLatin1String("%1: [\n%2\n]"); + m_value = addIndentation(m_value, 4); + break; + + case QmlRefactoring::ObjectBinding: + newPropertyTemplate = QLatin1String("%1: %2"); + break; + + case QmlRefactoring::ScriptBinding: + newPropertyTemplate = QLatin1String("%1: %2"); + break; + + default: + Q_ASSERT(!"unknown property type"); + } + + const bool isOneLiner = endOfPreviousMember.startLine == startOfNextMember.startLine; + if (isOneLiner) + newPropertyTemplate += QLatin1Char('\n'); + + const QString newPropertyText = addIndentation(newPropertyTemplate.arg(m_name, m_value), indentDepth); + replace(endOfPreviousMember.end(), 0, QLatin1Char('\n') + newPropertyText); + + setDidRewriting(true); +} diff --git a/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.h b/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.h new file mode 100644 index 0000000000..a375698a08 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/addpropertyvisitor.h @@ -0,0 +1,68 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef ADDPROPERTYVISITOR_H +#define ADDPROPERTYVISITOR_H + +#include "qmlrefactoring.h" +#include "qmlrewriter.h" + +namespace QmlEditor { +namespace Internal { + +class AddPropertyVisitor: public QMLRewriter +{ +public: +public: + AddPropertyVisitor(QmlDesigner::TextModifier &modifier, + quint32 parentLocation, + const QString &name, + const QString &value, + QmlEditor::QmlRefactoring::PropertyType propertyType, + const QStringList &propertyOrder); + +protected: + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + +private: + void addInMembers(QmlJS::AST::UiObjectInitializer *initializer); + +private: + quint32 m_parentLocation; + QString m_name; + QString m_value; + QmlEditor::QmlRefactoring::PropertyType m_propertyType; + QStringList m_propertyOrder; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // ADDPROPERTYVISITOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.cpp b/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.cpp new file mode 100644 index 0000000000..e7b7590418 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.cpp @@ -0,0 +1,75 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "astobjecttextextractor.h" +#include "qmljsast_p.h" + +using namespace QmlEditor; +using namespace QmlJS::AST; + +ASTObjectTextExtractor::ASTObjectTextExtractor(const QString &text): + m_document(QmlDocument::create("<ASTObjectTextExtractor>")) +{ + m_document->setSource(text); + m_document->parse(); +} + +QString ASTObjectTextExtractor::operator ()(int location) +{ + Q_ASSERT(location >= 0); + + m_location = location; + m_text.clear(); + + Node::accept(m_document->program(), this); + + return m_text; +} + +bool ASTObjectTextExtractor::visit(QmlJS::AST::UiObjectBinding *ast) +{ + if (!m_text.isEmpty()) + return false; + + if (ast->qualifiedTypeNameId->identifierToken.offset == m_location) + m_text = m_document->source().mid(m_location, ast->lastSourceLocation().end() - m_location); + + return m_text.isEmpty(); +} + +bool ASTObjectTextExtractor::visit(QmlJS::AST::UiObjectDefinition *ast) +{ + if (!m_text.isEmpty()) + return false; + + if (ast->firstSourceLocation().offset == m_location) + m_text = m_document->source().mid(m_location, ast->lastSourceLocation().end() - m_location); + + return m_text.isEmpty(); +} diff --git a/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.h b/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.h new file mode 100644 index 0000000000..029106f440 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/astobjecttextextractor.h @@ -0,0 +1,59 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef ASTOBJECTTEXTEXTRACTOR_H +#define ASTOBJECTTEXTEXTRACTOR_H + +#include <QtCore/QString> + +#include "qmldocument.h" +#include "qmljsastvisitor_p.h" + +namespace QmlEditor { + +class ASTObjectTextExtractor: public QmlJS::AST::Visitor +{ +public: + ASTObjectTextExtractor(const QString &text); + + QString operator()(int location); + +protected: + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + +private: + QmlDocument::Ptr m_document; + quint32 m_location; + QString m_text; +}; + +} // namespace QmlEditor + +#endif // ASTOBJECTTEXTEXTRACTOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp new file mode 100644 index 0000000000..5ecac14e1a --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.cpp @@ -0,0 +1,80 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +#include "changeimportsvisitor.h" + +using namespace QmlJS; +using namespace QmlJS::AST; + +using namespace QmlDesigner; +using namespace QmlDesigner::Internal; +using namespace QmlEditor::Internal; + +ChangeImportsVisitor::ChangeImportsVisitor(TextModifier &textModifier, const QSet<Import> &addedImports, const QSet<Import> &removedImports, const QString &source): + QMLRewriter(textModifier), + CopyPasteUtil(source), + m_addedImports(addedImports), + m_removedImports(removedImports) +{ +} + +bool ChangeImportsVisitor::visit(QmlJS::AST::UiProgram *ast) +{ + if (ast->imports) + accept(ast->imports); + + return false; +} + +bool ChangeImportsVisitor::visit(QmlJS::AST::UiImportList *ast) +{ + if (!ast) + return false; + + quint32 prevEnd = 0; + for (UiImportList *it = ast; it; it = it->next) { + UiImport *imp = it->import; + if (!imp) + continue; + + if (m_removedImports.remove(createImport(imp))) + replace(prevEnd, imp->lastSourceLocation().end() - prevEnd, ""); + + prevEnd = imp->lastSourceLocation().end(); + } + + foreach (const Import &i, m_addedImports) { + replace(prevEnd, 0, i.toString(false) + "\n"); + } + + return false; +} diff --git a/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h new file mode 100644 index 0000000000..9237799415 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/changeimportsvisitor.h @@ -0,0 +1,61 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CHANGEIMPORTSVISITOR_H +#define CHANGEIMPORTSVISITOR_H + +#include <QtCore/QSet> + +#include <model/copypasteutil.h> +#include "import.h" +#include "qmlrewriter.h" + +namespace QmlEditor { +namespace Internal { + +class ChangeImportsVisitor: public QMLRewriter, protected QmlDesigner::Internal::CopyPasteUtil +{ +public: + ChangeImportsVisitor(QmlDesigner::TextModifier &textModifier, + const QSet<QmlDesigner::Import> &addedImports, + const QSet<QmlDesigner::Import> &removedImports, const QString &source); + +protected: + virtual bool visit(QmlJS::AST::UiProgram *ast); + virtual bool visit(QmlJS::AST::UiImportList *ast); + +private: + QSet<QmlDesigner::Import> m_addedImports; + QSet<QmlDesigner::Import> m_removedImports; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // CHANGEIMPORTSVISITOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.cpp b/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.cpp new file mode 100644 index 0000000000..d0624f6ab8 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.cpp @@ -0,0 +1,81 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "changeobjecttypevisitor.h" +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +using namespace QmlJS; +using namespace QmlJS::AST; +using namespace QmlEditor::Internal; + +ChangeObjectTypeVisitor::ChangeObjectTypeVisitor(QmlDesigner::TextModifier &modifier, + quint32 nodeLocation, + const QString &newType): + QMLRewriter(modifier), + m_nodeLocation(nodeLocation), + m_newType(newType) +{ +} + +bool ChangeObjectTypeVisitor::visit(UiObjectDefinition *ast) +{ + if (ast->firstSourceLocation().offset == m_nodeLocation) { + replaceType(ast->qualifiedTypeNameId); + return false; + } + + return !didRewriting(); +} + +bool ChangeObjectTypeVisitor::visit(UiObjectBinding *ast) +{ + const quint32 start = ast->qualifiedTypeNameId->identifierToken.offset; + + if (start == m_nodeLocation) { + replaceType(ast->qualifiedTypeNameId); + return false; + } + + return !didRewriting(); +} + +void ChangeObjectTypeVisitor::replaceType(UiQualifiedId *typeId) +{ + Q_ASSERT(typeId); + + const int startOffset = typeId->identifierToken.offset; + int endOffset = typeId->identifierToken.end(); + for (UiQualifiedId *iter = typeId->next; iter; iter = iter->next) + if (!iter->next) + endOffset = iter->identifierToken.end(); + + replace(startOffset, endOffset - startOffset, m_newType); + setDidRewriting(true); +} diff --git a/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.h b/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.h new file mode 100644 index 0000000000..01c2e360a7 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/changeobjecttypevisitor.h @@ -0,0 +1,60 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CHANGEOBJECTTYPEVISITOR_H +#define CHANGEOBJECTTYPEVISITOR_H + +#include "qmlrewriter.h" + +namespace QmlEditor { +namespace Internal { + +class ChangeObjectTypeVisitor: public QMLRewriter +{ +public: + ChangeObjectTypeVisitor(QmlDesigner::TextModifier &modifier, + quint32 nodeLocation, + const QString &newType); + +protected: + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + +private: + void replaceType(QmlJS::AST::UiQualifiedId *typeId); + +private: + quint32 m_nodeLocation; + QString m_newType; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // CHANGEOBJECTTYPEVISITOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp new file mode 100644 index 0000000000..885671d183 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.cpp @@ -0,0 +1,191 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +#include "changepropertyvisitor.h" + +using namespace QmlJS; +using namespace QmlJS::AST; +using namespace QmlEditor; +using namespace QmlEditor::Internal; + +ChangePropertyVisitor::ChangePropertyVisitor(QmlDesigner::TextModifier &modifier, + quint32 parentLocation, + const QString &name, + const QString &value, + QmlRefactoring::PropertyType propertyType): + QMLRewriter(modifier), + m_parentLocation(parentLocation), + m_name(name), + m_value(value), + m_propertyType(propertyType) +{ +} + +bool ChangePropertyVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) +{ + if (didRewriting()) + return false; + + const quint32 objectStart = ast->firstSourceLocation().offset; + + if (objectStart == m_parentLocation) { + replaceInMembers(ast->initializer); + return false; + } + + return !didRewriting(); +} + +bool ChangePropertyVisitor::visit(QmlJS::AST::UiObjectBinding *ast) +{ + if (didRewriting()) + return false; + + const quint32 objectStart = ast->qualifiedTypeNameId->identifierToken.offset; + + if (objectStart == m_parentLocation) { + replaceInMembers(ast->initializer); + return false; + } + + return !didRewriting(); +} + +void ChangePropertyVisitor::replaceInMembers(UiObjectInitializer *initializer) +{ + for (UiObjectMemberList *members = initializer->members; members; members = members->next) { + UiObjectMember *propertyMember = members->member; + + if (isMatchingPropertyMember(propertyMember)) { + switch (m_propertyType) { + case QmlRefactoring::ArrayBinding: + insertIntoArray(cast<UiArrayBinding*>(propertyMember)); + break; + + case QmlRefactoring::ObjectBinding: + replaceMemberValue(propertyMember, false); + break; + + case QmlRefactoring::ScriptBinding: + replaceMemberValue(propertyMember, nextMemberOnSameLine(members)); + break; + + default: + Q_ASSERT(!"Unhandled QmlRefactoring::PropertyType"); + } + + break; + } + } +} + +void ChangePropertyVisitor::replaceMemberValue(UiObjectMember *propertyMember, bool needsSemicolon) +{ + QString replacement = m_value; + int startOffset = -1; + int endOffset = -1; + if (UiObjectBinding *objectBinding = AST::cast<UiObjectBinding *>(propertyMember)) { + startOffset = objectBinding->qualifiedTypeNameId->identifierToken.offset; + endOffset = objectBinding->initializer->rbraceToken.end(); + } else if (UiScriptBinding *scriptBinding = AST::cast<UiScriptBinding *>(propertyMember)) { + startOffset = scriptBinding->statement->firstSourceLocation().offset; + endOffset = scriptBinding->statement->lastSourceLocation().end(); + } else if (UiArrayBinding *arrayBinding = AST::cast<UiArrayBinding *>(propertyMember)) { + startOffset = arrayBinding->lbracketToken.offset; + endOffset = arrayBinding->rbracketToken.end(); + } else if (UiPublicMember *publicMember = AST::cast<UiPublicMember*>(propertyMember)) { + if (publicMember->expression) { + startOffset = publicMember->expression->firstSourceLocation().offset; + if (publicMember->semicolonToken.isValid()) + endOffset = publicMember->semicolonToken.end(); + else + endOffset = publicMember->expression->lastSourceLocation().offset; + } else { + startOffset = publicMember->lastSourceLocation().end(); + endOffset = startOffset; + if (publicMember->semicolonToken.isValid()) + startOffset = publicMember->semicolonToken.offset; + replacement.prepend(QLatin1String(": ")); + } + } else { + return; + } + + if (needsSemicolon) + replacement += ';'; + + replace(startOffset, endOffset - startOffset, replacement); + setDidRewriting(true); +} + +bool ChangePropertyVisitor::isMatchingPropertyMember(QmlJS::AST::UiObjectMember *member) const +{ + if (UiObjectBinding *objectBinding = AST::cast<UiObjectBinding *>(member)) { + return m_name == flatten(objectBinding->qualifiedId); + } else if (UiScriptBinding *scriptBinding = AST::cast<UiScriptBinding *>(member)) { + return m_name == flatten(scriptBinding->qualifiedId); + } else if (UiArrayBinding *arrayBinding = AST::cast<UiArrayBinding *>(member)) { + return m_name == flatten(arrayBinding->qualifiedId); + } else if (UiPublicMember *publicMember = AST::cast<UiPublicMember *>(member)) { + return m_name == publicMember->name->asString(); + } else { + return false; + } +} + +bool ChangePropertyVisitor::nextMemberOnSameLine(UiObjectMemberList *members) +{ + if (members && members->next && members->next->member) { + return members->next->member->firstSourceLocation().startLine == members->member->lastSourceLocation().startLine; + } else { + return false; + } +} + +void ChangePropertyVisitor::insertIntoArray(QmlJS::AST::UiArrayBinding *ast) +{ + if (!ast) + return; + + UiObjectMember *lastMember = 0; + for (UiArrayMemberList *iter = ast->members; iter; iter = iter->next) { + } + + if (!lastMember) + return; + + const int insertionPoint = lastMember->lastSourceLocation().end(); + const int indentDepth = calculateIndentDepth(lastMember->firstSourceLocation()); + const QString indentedArrayMember = addIndentation(m_value, indentDepth); + replace(insertionPoint, 0, QLatin1String(",\n") + indentedArrayMember); + setDidRewriting(true); +} diff --git a/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h new file mode 100644 index 0000000000..6cc41d8f91 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/changepropertyvisitor.h @@ -0,0 +1,70 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef CHANGEPROPERTYVISITOR_H +#define CHANGEPROPERTYVISITOR_H + +#include "qmlrefactoring.h" +#include "qmlrewriter.h" + +namespace QmlEditor { +namespace Internal { + +class ChangePropertyVisitor: public QMLRewriter +{ +public: + ChangePropertyVisitor(QmlDesigner::TextModifier &modifier, + quint32 parentLocation, + const QString &name, + const QString &value, + QmlRefactoring::PropertyType propertyType); + +protected: + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + +private: + void replaceInMembers(QmlJS::AST::UiObjectInitializer *initializer); + void replaceMemberValue(QmlJS::AST::UiObjectMember *propertyMember, bool needsSemicolon); + bool isMatchingPropertyMember(QmlJS::AST::UiObjectMember *member) const; + static bool nextMemberOnSameLine(QmlJS::AST::UiObjectMemberList *members); + + void insertIntoArray(QmlJS::AST::UiArrayBinding* ast); + +private: + quint32 m_parentLocation; + QString m_name; + QString m_value; + QmlRefactoring::PropertyType m_propertyType; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // CHANGEPROPERTYVISITOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/changeset.cpp b/src/plugins/qmldesigner/core/filemanager/changeset.cpp new file mode 100644 index 0000000000..b006106a16 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/changeset.cpp @@ -0,0 +1,359 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "changeset.h" + +namespace Utils { + +ChangeSet::ChangeSet() + : m_string(0), m_cursor(0), m_error(false) +{ +} + +static bool overlaps(int posA, int lengthA, int posB, int lengthB) { + if (lengthB > 0) { + return + // right edge of B contained in A + (posA < posB + lengthB && posA + lengthA >= posB + lengthB) + // left edge of B contained in A + || (posA <= posB && posA + lengthA > posB) + // A contained in B + || (posB < posA && posB + lengthB > posA + lengthA); + } else { + return (posB > posA && posB < posA + lengthA); + } +} + +bool ChangeSet::hasOverlap(int pos, int length) +{ + QListIterator<EditOp> i(m_operationList); + while (i.hasNext()) { + const EditOp &cmd = i.next(); + + switch (cmd.type) { + case EditOp::Replace: + if (overlaps(pos, length, cmd.pos1, cmd.length1)) + return true; + break; + + case EditOp::Move: + if (overlaps(pos, length, cmd.pos1, cmd.length1)) + return true; + if (cmd.pos2 > pos && cmd.pos2 < pos + length) + return true; + break; + + case EditOp::Insert: + if (cmd.pos1 > pos && cmd.pos1 < pos + length) + return true; + break; + + case EditOp::Remove: + if (overlaps(pos, length, cmd.pos1, cmd.length1)) + return true; + break; + + case EditOp::Flip: + if (overlaps(pos, length, cmd.pos1, cmd.length1)) + return true; + if (overlaps(pos, length, cmd.pos2, cmd.length2)) + return true; + break; + + case EditOp::Copy: + if (overlaps(pos, length, cmd.pos1, cmd.length1)) + return true; + if (cmd.pos2 > pos && cmd.pos2 < pos + length) + return true; + break; + + case EditOp::Unset: + break; + } + } + + return false; +} + +bool ChangeSet::isEmpty() const +{ + return m_operationList.isEmpty(); +} + +QList<ChangeSet::EditOp> ChangeSet::operationList() const +{ + return m_operationList; +} + +void ChangeSet::clear() +{ + m_string = 0; + m_cursor = 0; + m_operationList.clear(); + m_error = false; +} + +bool ChangeSet::replace(int pos, int length, const QString &replacement) +{ + if (hasOverlap(pos, length)) + m_error = true; + + EditOp cmd(EditOp::Replace); + cmd.pos1 = pos; + cmd.length1 = length; + cmd.text = replacement; + m_operationList += cmd; + + return !m_error; +} + +bool ChangeSet::move(int pos, int length, int to) +{ + if (hasOverlap(pos, length) + || hasOverlap(to, 0) + || overlaps(pos, length, to, 0)) + m_error = true; + + EditOp cmd(EditOp::Move); + cmd.pos1 = pos; + cmd.length1 = length; + cmd.pos2 = to; + m_operationList += cmd; + + return !m_error; +} + +bool ChangeSet::insert(int pos, const QString &text) +{ + if (hasOverlap(pos, 0)) + m_error = true; + + EditOp cmd(EditOp::Insert); + cmd.pos1 = pos; + cmd.text = text; + m_operationList += cmd; + + return !m_error; +} + +bool ChangeSet::remove(int pos, int length) +{ + if (hasOverlap(pos, length)) + m_error = true; + + EditOp cmd(EditOp::Remove); + cmd.pos1 = pos; + cmd.length1 = length; + m_operationList += cmd; + + return !m_error; +} + +bool ChangeSet::flip(int pos1, int length1, int pos2, int length2) +{ + if (hasOverlap(pos1, length1) + || hasOverlap(pos2, length2) + || overlaps(pos1, length1, pos2, length2)) + m_error = true; + + EditOp cmd(EditOp::Flip); + cmd.pos1 = pos1; + cmd.length1 = length1; + cmd.pos2 = pos2; + cmd.length2 = length2; + m_operationList += cmd; + + return !m_error; +} + +bool ChangeSet::copy(int pos, int length, int to) +{ + if (hasOverlap(pos, length) + || hasOverlap(to, 0) + || overlaps(pos, length, to, 0)) + m_error = true; + + EditOp cmd(EditOp::Copy); + cmd.pos1 = pos; + cmd.length1 = length; + cmd.pos2 = to; + m_operationList += cmd; + + return !m_error; +} + +void ChangeSet::doReplace(const EditOp &replace, QList<EditOp> *replaceList) +{ + Q_ASSERT(replace.type == EditOp::Replace); + + { + QMutableListIterator<EditOp> i(*replaceList); + while (i.hasNext()) { + EditOp &c = i.next(); + if (replace.pos1 <= c.pos1) + c.pos1 += replace.text.size(); + if (replace.pos1 < c.pos1) + c.pos1 -= replace.length1; + } + } + + if (m_string) { + m_string->replace(replace.pos1, replace.length1, replace.text); + } else if (m_cursor) { + m_cursor->setPosition(replace.pos1); + m_cursor->setPosition(replace.pos1 + replace.length1, QTextCursor::KeepAnchor); + m_cursor->insertText(replace.text); + } +} + +void ChangeSet::convertToReplace(const EditOp &op, QList<EditOp> *replaceList) +{ + EditOp replace1(EditOp::Replace); + EditOp replace2(EditOp::Replace); + + switch (op.type) { + case EditOp::Replace: + replaceList->append(op); + break; + + case EditOp::Move: + replace1.pos1 = op.pos1; + replace1.length1 = op.length1; + replaceList->append(replace1); + + replace2.pos1 = op.pos2; + replace2.text = textAt(op.pos1, op.length1); + replaceList->append(replace2); + break; + + case EditOp::Insert: + replace1.pos1 = op.pos1; + replace1.text = op.text; + replaceList->append(replace1); + break; + + case EditOp::Remove: + replace1.pos1 = op.pos1; + replace1.length1 = op.length1; + replaceList->append(replace1); + break; + + case EditOp::Flip: + replace1.pos1 = op.pos1; + replace1.length1 = op.length1; + replace1.text = textAt(op.pos2, op.length2); + replaceList->append(replace1); + + replace2.pos1 = op.pos2; + replace2.length1 = op.length2; + replace2.text = textAt(op.pos1, op.length1); + replaceList->append(replace2); + break; + + case EditOp::Copy: + replace1.pos1 = op.pos2; + replace1.text = textAt(op.pos1, op.length1); + replaceList->append(replace1); + break; + + case EditOp::Unset: + break; + } +} + +bool ChangeSet::hadErrors() +{ + return m_error; +} + +void ChangeSet::apply(QString *s) +{ + m_string = s; + apply_helper(); + m_string = 0; +} + +void ChangeSet::apply(QTextCursor *textCursor) +{ + m_cursor = textCursor; + apply_helper(); + m_cursor = 0; +} + +QString ChangeSet::textAt(int pos, int length) +{ + if (m_string) { + return m_string->mid(pos, length); + } else if (m_cursor) { + m_cursor->setPosition(pos); + m_cursor->setPosition(pos + length, QTextCursor::KeepAnchor); + return m_cursor->selectedText(); + } + return QString(); +} + +void ChangeSet::apply_helper() +{ + // convert all ops to replace + QList<EditOp> replaceList; + { + while (!m_operationList.isEmpty()) { + const EditOp cmd(m_operationList.first()); + m_operationList.removeFirst(); + convertToReplace(cmd, &replaceList); + } + } + + // execute replaces + if (m_cursor) + m_cursor->beginEditBlock(); + + while (!replaceList.isEmpty()) { + const EditOp cmd(replaceList.first()); + replaceList.removeFirst(); + doReplace(cmd, &replaceList); + } + + if (m_cursor) + m_cursor->endEditBlock(); +} + +} // end namespace Utils diff --git a/src/plugins/qmldesigner/core/filemanager/changeset.h b/src/plugins/qmldesigner/core/filemanager/changeset.h new file mode 100644 index 0000000000..2f46bd835d --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/changeset.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtDeclarative module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef CHANGESET_H +#define CHANGESET_H + +#include "utils_global.h" + +#include <QtCore/QString> +#include <QtCore/QList> +#include <QtCore/QSharedPointer> +#include <QtGui/QTextCursor> + +namespace Utils { + +class QTCREATOR_UTILS_EXPORT ChangeSet +{ +public: + struct EditOp { + enum Type + { + Unset, + Replace, + Move, + Insert, + Remove, + Flip, + Copy + }; + + EditOp(): type(Unset), pos1(0), pos2(0), length1(0), length2(0) {} + EditOp(Type t): type(t), pos1(0), pos2(0), length1(0), length2(0) {} + + Type type; + int pos1; + int pos2; + int length1; + int length2; + QString text; + }; + +public: + ChangeSet(); + + bool isEmpty() const; + + QList<EditOp> operationList() const; + + void clear(); + + bool replace(int pos, int length, const QString &replacement); + bool move(int pos, int length, int to); + bool insert(int pos, const QString &text); + bool remove(int pos, int length); + bool flip(int pos1, int length1, int pos2, int length2); + bool copy(int pos, int length, int to); + + bool hadErrors(); + + void apply(QString *s); + void apply(QTextCursor *textCursor); + +private: + bool hasOverlap(int pos, int length); + QString textAt(int pos, int length); + + void doReplace(const EditOp &replace, QList<EditOp> *replaceList); + void convertToReplace(const EditOp &op, QList<EditOp> *replaceList); + + void apply_helper(); + +private: + QString *m_string; + QTextCursor *m_cursor; + + QList<EditOp> m_operationList; + bool m_error; +}; + +} // namespace Utils + +#endif // CHANGESET_H diff --git a/src/plugins/qmldesigner/core/filemanager/filemanager.pri b/src/plugins/qmldesigner/core/filemanager/filemanager.pri new file mode 100644 index 0000000000..fb51eda8d5 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/filemanager.pri @@ -0,0 +1,41 @@ +include($$PWD/parser/parser.pri) +SOURCES += $$PWD/qmldocument.cpp \ + $$PWD/idcollector.cpp \ + $$PWD/qmlsymbol.cpp \ + $$PWD/qmlrewriter.cpp \ + $$PWD/qmlrefactoring.cpp \ + $$PWD/changeobjecttypevisitor.cpp \ + $$PWD/changepropertyvisitor.cpp \ + $$PWD/removeuiobjectmembervisitor.cpp \ + $$PWD/removepropertyvisitor.cpp \ + $$PWD/addpropertyvisitor.cpp \ + $$PWD/moveobjectvisitor.cpp \ + $$PWD/addobjectvisitor.cpp \ + $$PWD/addarraymembervisitor.cpp \ + $$PWD/astobjecttextextractor.cpp \ + $$PWD/indenter.cpp \ + $$PWD/changeset.cpp \ + $$PWD/objectlengthcalculator.cpp \ + $$PWD/firstdefinitionfinder.cpp \ + $$PWD/moveobjectbeforeobjectvisitor.cpp +HEADERS += $$PWD/qmldocument.h \ + $$PWD/idcollector.h \ + $$PWD/qmleditor_global.h \ + $$PWD/qmlsymbol.h \ + $$PWD/qmlrewriter.h \ + $$PWD/qmlrefactoring.h \ + $$PWD/changeobjecttypevisitor.h \ + $$PWD/changepropertyvisitor.h \ + $$PWD/removeuiobjectmembervisitor.h \ + $$PWD/removepropertyvisitor.h \ + $$PWD/addpropertyvisitor.h \ + $$PWD/moveobjectvisitor.h \ + $$PWD/addobjectvisitor.h \ + $$PWD/addarraymembervisitor.h \ + $$PWD/astobjecttextextractor.h \ + $$PWD/indenter.h \ + $$PWD/changeset.h \ + $$PWD/utils_global.h \ + $$PWD/objectlengthcalculator.h \ + $$PWD/firstdefinitionfinder.h \ + $$PWD/moveobjectbeforeobjectvisitor.h diff --git a/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.cpp b/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.cpp new file mode 100644 index 0000000000..64905c35aa --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.cpp @@ -0,0 +1,98 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "firstdefinitionfinder.h" + +#include <qmljsast_p.h> + +using namespace QmlDesigner; +using namespace QmlEditor; +using namespace QmlJS::AST; + +FirstDefinitionFinder::FirstDefinitionFinder(const QString &text): + m_doc(QmlDocument::create("<internal>")) +{ + m_doc->setSource(text); + bool ok = m_doc->parse(); + + Q_ASSERT(ok); +} + +/*! + \brief Finds the first object definition inside the object given by offset + + + \arg the offset of the object to search in + \return the offset of the first object definition + */ +quint32 FirstDefinitionFinder::operator()(quint32 offset) +{ + m_offset = offset; + m_firstObjectDefinition = 0; + + Node::accept(m_doc->program(), this); + + return m_firstObjectDefinition->firstSourceLocation().offset; +} + +void FirstDefinitionFinder::extractFirstObjectDefinition(UiObjectInitializer* ast) +{ + if (!ast) + return; + + for (UiObjectMemberList *iter = ast->members; iter; iter = iter->next) { + if (UiObjectDefinition *def = cast<UiObjectDefinition*>(iter->member)) { + m_firstObjectDefinition = def; + } + } +} + +bool FirstDefinitionFinder::visit(QmlJS::AST::UiObjectBinding *ast) +{ + if (ast->qualifiedTypeNameId && ast->qualifiedTypeNameId->identifierToken.isValid()) { + const quint32 start = ast->qualifiedTypeNameId->identifierToken.offset; + + if (start == m_offset) { + extractFirstObjectDefinition(ast->initializer); + return false; + } + } + return true; +} + +bool FirstDefinitionFinder::visit(QmlJS::AST::UiObjectDefinition *ast) +{ + const quint32 start = ast->firstSourceLocation().offset; + + if (start == m_offset) { + extractFirstObjectDefinition(ast->initializer); + return false; + } + return true; +} diff --git a/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.h b/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.h new file mode 100644 index 0000000000..170b7a2381 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/firstdefinitionfinder.h @@ -0,0 +1,63 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef FIRSTDEFINITIONFINDER_H +#define FIRSTDEFINITIONFINDER_H + +#include "qmldocument.h" + +#include <qmljsastvisitor_p.h> + +namespace QmlDesigner { + +class FirstDefinitionFinder: protected QmlJS::AST::Visitor +{ +public: + FirstDefinitionFinder(const QString &text); + + quint32 operator()(quint32 offset); + +protected: + using QmlJS::AST::Visitor::visit; + + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + + void extractFirstObjectDefinition(QmlJS::AST::UiObjectInitializer* ast); + +private: + QmlEditor::QmlDocument::Ptr m_doc; + quint32 m_offset; + QmlJS::AST::UiObjectDefinition *m_firstObjectDefinition; + +}; + +} // namespace QmlDesigner + +#endif // FIRSTDEFINITIONFINDER_H diff --git a/src/plugins/qmldesigner/core/filemanager/idcollector.cpp b/src/plugins/qmldesigner/core/filemanager/idcollector.cpp new file mode 100644 index 0000000000..54284a9fad --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/idcollector.cpp @@ -0,0 +1,93 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "idcollector.h" +#include "qmljsast_p.h" +#include "qmljsengine_p.h" + +using namespace QmlJS; +using namespace QmlJS::AST; +using namespace QmlEditor; +using namespace QmlEditor::Internal; + +QMap<QString, QmlIdSymbol*> IdCollector::operator()(const QString &fileName, QmlJS::AST::UiProgram *ast) +{ + _fileName = fileName; + _ids.clear(); + + Node::accept(ast, this); + + return _ids; +} + +bool IdCollector::visit(QmlJS::AST::UiObjectBinding *ast) +{ + _scopes.push(ast); + return true; +} + +bool IdCollector::visit(QmlJS::AST::UiObjectDefinition *ast) +{ + _scopes.push(ast); + return true; +} + +void IdCollector::endVisit(QmlJS::AST::UiObjectBinding *) +{ + _scopes.pop(); +} + +void IdCollector::endVisit(QmlJS::AST::UiObjectDefinition *) +{ + _scopes.pop(); +} + +bool IdCollector::visit(QmlJS::AST::UiScriptBinding *ast) +{ + if (!(ast->qualifiedId->next) && ast->qualifiedId->name->asString() == "id") + if (ExpressionStatement *e = cast<ExpressionStatement*>(ast->statement)) + if (IdentifierExpression *i = cast<IdentifierExpression*>(e->expression)) + addId(i->name->asString(), ast); + + return false; +} + +void IdCollector::addId(const QString &id, QmlJS::AST::UiScriptBinding *ast) +{ + if (!_ids.contains(id)) { + Node *parent = _scopes.top(); + + if (UiObjectBinding *binding = cast<UiObjectBinding*>(parent)) + _ids[id] = new QmlIdSymbol(_fileName, ast, QmlSymbolFromFile(_fileName, binding)); + else if (UiObjectDefinition *definition = cast<UiObjectDefinition*>(parent)) + _ids[id] = new QmlIdSymbol(_fileName, ast, QmlSymbolFromFile(_fileName, definition)); + else + Q_ASSERT(!"Unknown parent for id"); + } +} diff --git a/src/plugins/qmldesigner/core/filemanager/idcollector.h b/src/plugins/qmldesigner/core/filemanager/idcollector.h new file mode 100644 index 0000000000..b9f3211e9e --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/idcollector.h @@ -0,0 +1,69 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef IDCOLLECTOR_H +#define IDCOLLECTOR_H + +#include <QMap> +#include <QPair> +#include <QStack> +#include <QString> + +#include "qmljsastvisitor_p.h" +#include "qmlsymbol.h" + +namespace QmlEditor { +namespace Internal { + +class IdCollector: protected QmlJS::AST::Visitor +{ +public: + QMap<QString, QmlIdSymbol*> operator()(const QString &fileName, QmlJS::AST::UiProgram *ast); + +protected: + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + virtual bool visit(QmlJS::AST::UiScriptBinding *ast); + + virtual void endVisit(QmlJS::AST::UiObjectBinding *); + virtual void endVisit(QmlJS::AST::UiObjectDefinition *); + +private: + void addId(const QString &id, QmlJS::AST::UiScriptBinding *ast); + +private: + QString _fileName; + QMap<QString, QmlIdSymbol*> _ids; + QStack<QmlJS::AST::Node *> _scopes; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // IDCOLLECTOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/indenter.cpp b/src/plugins/qmldesigner/core/filemanager/indenter.cpp new file mode 100644 index 0000000000..55e709d7f2 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/indenter.cpp @@ -0,0 +1,90 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "indenter.h" + +using namespace QmlEditor; + +Indenter::Indenter() +{ +} + +//static int blockStartState(const QTextBlock &block) +//{ +// int state = block.userState(); +// +// if (state == -1) +// return 0; +// else +// return state & 0xff; +//} +// +//void ScriptEditor::indentBlock(QTextDocument *, QTextBlock block, QChar typedChar) +//{ +// TextEditor::TabSettings ts = tabSettings(); +// +// QTextCursor tc(block); +// +// const QString blockText = block.text(); +// int startState = blockStartState(block.previous()); +// +// QScriptIncrementalScanner scanner; +// const QList<QScriptIncrementalScanner::Token> tokens = scanner(blockText, startState); +// +// if (! tokens.isEmpty()) { +// const QScriptIncrementalScanner::Token tk = tokens.first(); +// +// if (tk.is(QScriptIncrementalScanner::Token::RightBrace) +// || tk.is(QScriptIncrementalScanner::Token::RightBracket)) { +// if (TextEditor::TextBlockUserData::findPreviousBlockOpenParenthesis(&tc)) { +// const QString text = tc.block().text(); +// int indent = ts.columnAt(text, ts.firstNonSpace(text)); +// ts.indentLine(block, indent); +// return; +// } +// } +// } +// +// int initialIndent = 0; +// for (QTextBlock it = block.previous(); it.isValid(); it = it.previous()) { +// const QString text = it.text(); +// +// if (! text.isEmpty()) { +// initialIndent = ts.columnAt(text, ts.firstNonSpace(text)); +// break; +// } +// } +// +// const int braceDepth = blockBraceDepth(block.previous()); +// const int previousBraceDepth = blockBraceDepth(block.previous().previous()); +// const int delta = qMax(0, braceDepth - previousBraceDepth); +// int indent = initialIndent + (delta * ts.m_indentSize); +// ts.indentLine(block, indent); +//} +// diff --git a/src/plugins/qmldesigner/core/filemanager/indenter.h b/src/plugins/qmldesigner/core/filemanager/indenter.h new file mode 100644 index 0000000000..b862003b2c --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/indenter.h @@ -0,0 +1,43 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef INDENTER_H +#define INDENTER_H + +namespace QmlEditor { + +class Indenter +{ +public: + Indenter(); +}; + +} // namespace QmlEditor + +#endif // INDENTER_H diff --git a/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.cpp new file mode 100644 index 0000000000..62a8ed5429 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.cpp @@ -0,0 +1,158 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <QtCore/QDebug> + +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +#include "moveobjectbeforeobjectvisitor.h" +#include "textmodifier.h" + +using namespace QmlJS; +using namespace QmlJS::AST; +using namespace QmlEditor::Internal; +using namespace QmlDesigner; + +MoveObjectBeforeObjectVisitor::MoveObjectBeforeObjectVisitor(TextModifier &modifier, + quint32 movingObjectLocation): + QMLRewriter(modifier), + movingObjectLocation(movingObjectLocation), + toEnd(true), + beforeObjectLocation(0) +{} + +MoveObjectBeforeObjectVisitor::MoveObjectBeforeObjectVisitor(TextModifier &modifier, + quint32 movingObjectLocation, + quint32 beforeObjectLocation): + QMLRewriter(modifier), + movingObjectLocation(movingObjectLocation), + toEnd(false), + beforeObjectLocation(beforeObjectLocation) +{} + +bool MoveObjectBeforeObjectVisitor::operator ()(QmlJS::AST::UiProgram *ast) +{ + movingObject = 0; + beforeObject = 0; + movingObjectParents.clear(); + + QMLRewriter::operator ()(ast); + + if (foundEverything()) { + doMove(); + } + + return didRewriting(); +} + +bool MoveObjectBeforeObjectVisitor::preVisit(Node *ast) +{ if (ast) parents.push(ast); return true; } + +void MoveObjectBeforeObjectVisitor::postVisit(Node *ast) +{ if (ast) parents.pop(); } + +bool MoveObjectBeforeObjectVisitor::visit(UiObjectDefinition *ast) +{ + if (foundEverything()) + return false; + + const quint32 start = ast->firstSourceLocation().offset; + if (start == movingObjectLocation) { + movingObject = ast; + movingObjectParents = parents; + movingObjectParents.pop(); + } else if (!toEnd && start == beforeObjectLocation) { + beforeObject = ast; + } + + if (movingObjectLocation < start) + return false; + else if (!toEnd && beforeObjectLocation < start) + return false; + else if (foundEverything()) + return false; + else + return true; +} + +void MoveObjectBeforeObjectVisitor::doMove() +{ + Q_ASSERT(movingObject); + Q_ASSERT(!movingObjectParents.isEmpty()); + + TextModifier::MoveInfo moveInfo; + + int start = movingObject->firstSourceLocation().offset; + int end = movingObject->lastSourceLocation().end(); + + moveInfo.objectStart = start; + moveInfo.objectEnd = end; + + includeSurroundingWhitespace(start, end); + moveInfo.leadingCharsToRemove = moveInfo.objectStart - start; + moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd; + + if (beforeObject) { + moveInfo.destination = beforeObject->firstSourceLocation().offset; + int dummy = -1; + includeSurroundingWhitespace(moveInfo.destination, dummy); + + moveInfo.prefixToInsert = QString(moveInfo.leadingCharsToRemove, QLatin1Char(' ')); + moveInfo.suffixToInsert = QLatin1String("\n\n"); + } else { + const SourceLocation insertionPoint = lastParentLocation(); + Q_ASSERT(insertionPoint.isValid()); + moveInfo.destination = insertionPoint.offset; + int dummy = -1; + includeSurroundingWhitespace(moveInfo.destination, dummy); + + moveInfo.prefixToInsert = QString(moveInfo.leadingCharsToRemove, QLatin1Char(' ')); + moveInfo.suffixToInsert = QLatin1String("\n"); + } + + move(moveInfo); + setDidRewriting(true); +} + +SourceLocation MoveObjectBeforeObjectVisitor::lastParentLocation() const +{ + dump(movingObjectParents); + + Node *parent; + if (movingObjectParents.size() > 1) + parent = movingObjectParents.at(movingObjectParents.size() - 2); + else + parent = 0; + + if (UiObjectInitializer *initializer = cast<UiObjectInitializer*>(parent)) + return initializer->rbraceToken; + else + return SourceLocation(); +} diff --git a/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.h b/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.h new file mode 100644 index 0000000000..4b405dd306 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/moveobjectbeforeobjectvisitor.h @@ -0,0 +1,79 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MOVEOBJECTBEFOREOBJECTVISITOR_H +#define MOVEOBJECTBEFOREOBJECTVISITOR_H + +#include "qmlrewriter.h" + +#include <QtCore/QStack> + +namespace QmlEditor { +namespace Internal { + +class MoveObjectBeforeObjectVisitor: public QMLRewriter +{ +public: + MoveObjectBeforeObjectVisitor(QmlDesigner::TextModifier &modifier, + quint32 movingObjectLocation); + MoveObjectBeforeObjectVisitor(QmlDesigner::TextModifier &modifier, + quint32 movingObjectLocation, + quint32 beforeObjectLocation); + + bool operator ()(QmlJS::AST::UiProgram *ast); + +protected: + virtual bool preVisit(QmlJS::AST::Node *ast); + virtual void postVisit(QmlJS::AST::Node *ast); + + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + +private: + bool foundEverything() const + { return movingObject != 0 && !movingObjectParents.isEmpty() && (toEnd || beforeObject != 0); } + + void doMove(); + + QmlJS::AST::SourceLocation lastParentLocation() const; + +private: + QStack<QmlJS::AST::Node *> parents; + quint32 movingObjectLocation; + bool toEnd; + quint32 beforeObjectLocation; + + QmlJS::AST::UiObjectDefinition *movingObject; + QmlJS::AST::UiObjectDefinition *beforeObject; + ASTPath movingObjectParents; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // MOVEOBJECTBEFOREOBJECTVISITOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.cpp new file mode 100644 index 0000000000..ce95b03bad --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.cpp @@ -0,0 +1,293 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <QtCore/QDebug> + +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +#include "moveobjectvisitor.h" +#include "textmodifier.h" + +using namespace QmlJS; +using namespace QmlJS::AST; +using namespace QmlEditor::Internal; +using namespace QmlDesigner; + +class Inserter: public QMLRewriter +{ +public: + Inserter(QmlDesigner::TextModifier &modifier, + quint32 targetParentObjectLocation, + const QString &targetPropertyName, + bool targetIsArrayBinding, + TextModifier::MoveInfo moveInfo, + const QStringList &propertyOrder): + QMLRewriter(modifier), + targetParentObjectLocation(targetParentObjectLocation), + targetPropertyName(targetPropertyName), + targetIsArrayBinding(targetIsArrayBinding), + moveInfo(moveInfo), + propertyOrder(propertyOrder) + {} + +protected: + virtual bool visit(UiObjectBinding *ast) + { + if (didRewriting()) + return false; + + if (ast->qualifiedTypeNameId->identifierToken.offset == targetParentObjectLocation) { + insertInto(ast->initializer); + } + + return !didRewriting(); + } + + virtual bool visit(UiObjectDefinition *ast) + { + if (didRewriting()) + return false; + + if (ast->firstSourceLocation().offset == targetParentObjectLocation) { + insertInto(ast->initializer); + } + + return !didRewriting(); + } + +private: + void insertInto(UiObjectInitializer *ast) + { + if (targetPropertyName.isEmpty()) { + // insert as UiObjectDefinition: + UiObjectMemberList *insertAfter = searchMemberToInsertAfter(ast->members, QString::null, propertyOrder); + + if (insertAfter && insertAfter->member) { + moveInfo.destination = insertAfter->member->lastSourceLocation().end(); + moveInfo.prefixToInsert = QLatin1String("\n\n"); + } else { + moveInfo.destination = ast->lbraceToken.end(); + moveInfo.prefixToInsert = QLatin1String("\n"); + } + + move(moveInfo); + + setDidRewriting(true); + return; + } + + // see if we need to insert into an UiArrayBinding: + for (UiObjectMemberList *iter = ast->members; iter; iter = iter->next) { + UiObjectMember *member = iter->member; + + if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(member)) { + if (flatten(arrayBinding->qualifiedId) == targetPropertyName) { + appendToArray(arrayBinding); + + setDidRewriting(true); + return; + } + } + } + + { // insert (create) a UiObjectBinding: + UiObjectMemberList *insertAfter = searchMemberToInsertAfter(ast->members, targetPropertyName, propertyOrder); + moveInfo.prefixToInsert = QLatin1String("\n") + targetPropertyName + (targetIsArrayBinding ? QLatin1String(": [") : QLatin1String(": ")); + moveInfo.suffixToInsert = targetIsArrayBinding ? QLatin1String("\n]") : QLatin1String(""); + + if (insertAfter && insertAfter->member) { + moveInfo.destination = insertAfter->member->lastSourceLocation().end(); + } else { + moveInfo.destination = ast->lbraceToken.end(); + } + + setDidRewriting(true); + } + } + + void appendToArray(UiArrayBinding *ast) + { + UiObjectMember *lastMember = 0; + + for (UiArrayMemberList *iter = ast->members; iter; iter = iter->next) { + if (iter->member) + lastMember = iter->member; + } + + if (!lastMember) + Q_ASSERT(!"Invalid QML: empty array found."); + + moveInfo.destination = lastMember->lastSourceLocation().end(); + moveInfo.suffixToInsert = QLatin1String(",\n"); + move(moveInfo); + } + +private: + quint32 targetParentObjectLocation; + QString targetPropertyName; + bool targetIsArrayBinding; + TextModifier::MoveInfo moveInfo; + QStringList propertyOrder; +}; + +MoveObjectVisitor::MoveObjectVisitor(QmlDesigner::TextModifier &modifier, + quint32 objectLocation, + const QString &targetPropertyName, + bool targetIsArrayBinding, + quint32 targetParentObjectLocation, + const QStringList &propertyOrder): + QMLRewriter(modifier), + objectLocation(objectLocation), + targetPropertyName(targetPropertyName), + targetIsArrayBinding(targetIsArrayBinding), + targetParentObjectLocation(targetParentObjectLocation), + propertyOrder(propertyOrder) +{ +} + +bool MoveObjectVisitor::operator()(UiProgram *ast) +{ + program = ast; + + return QMLRewriter::operator()(ast); +} + +bool MoveObjectVisitor::visit(UiArrayBinding *ast) +{ + if (didRewriting()) + return false; + + UiArrayMemberList *currentMember = 0; + + for (UiArrayMemberList *it = ast->members; it; it = it->next) { + if (it->member->firstSourceLocation().offset == objectLocation) { + currentMember = it; + break; + } + } + + if (currentMember) { + TextModifier::MoveInfo moveInfo; + moveInfo.objectEnd = currentMember->member->lastSourceLocation().end(); + + if (currentMember == ast->members && !currentMember->next) { + // array with 1 element, which is moved away, so also remove the array binding + int start = ast->firstSourceLocation().offset; + int end = ast->lastSourceLocation().end(); + includeSurroundingWhitespace(start, end); + moveInfo.leadingCharsToRemove = objectLocation - start; + moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd; + } else if (currentMember->next) { + // we're not the last element, so remove the trailing comma too + Q_ASSERT(currentMember->next->commaToken.isValid()); + + int start = objectLocation; + int end = currentMember->next->commaToken.end(); + includeSurroundingWhitespace(start, end); + moveInfo.leadingCharsToRemove = objectLocation - start; + moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd; + } else { + // we're the last member, but not the only member, so remove the preceeding comma too + Q_ASSERT(currentMember->commaToken.isValid()); + + int start = currentMember->commaToken.offset; + int end = moveInfo.objectEnd; + includeSurroundingWhitespace(start, end); + moveInfo.leadingCharsToRemove = objectLocation - start; + moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd; + } + + doMove(moveInfo); + } + + return !didRewriting(); +} + +bool MoveObjectVisitor::visit(UiObjectBinding *ast) +{ + if (didRewriting()) + return false; + + if (ast->qualifiedTypeNameId->identifierToken.offset == objectLocation) { + TextModifier::MoveInfo moveInfo; + moveInfo.objectEnd = ast->lastSourceLocation().end(); + + // remove leading indentation and property name: + int start = ast->firstSourceLocation().offset; + int end = moveInfo.objectEnd; + includeSurroundingWhitespace(start, end); + includeLeadingEmptyLine(start); + moveInfo.leadingCharsToRemove = objectLocation - start; + + // remove trailing indentation + moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd; + + doMove(moveInfo); + } + + return !didRewriting(); +} + +bool MoveObjectVisitor::visit(UiObjectDefinition *ast) +{ + if (didRewriting()) + return false; + + if (ast->qualifiedTypeNameId->identifierToken.offset == objectLocation) { + TextModifier::MoveInfo moveInfo; + moveInfo.objectStart = objectLocation; + moveInfo.objectEnd = ast->lastSourceLocation().end(); + + // remove leading indentation: + int start = objectLocation; + int end = moveInfo.objectEnd; + includeSurroundingWhitespace(start, end); + includeLeadingEmptyLine(start); + moveInfo.leadingCharsToRemove = objectLocation - start; + moveInfo.trailingCharsToRemove = end - moveInfo.objectEnd; + + doMove(moveInfo); + } + + return !didRewriting(); +} + +void MoveObjectVisitor::doMove(TextModifier::MoveInfo moveInfo) +{ + if (moveInfo.objectEnd > moveInfo.objectStart) { + Inserter findTargetAndInsert(*textModifier(), + targetParentObjectLocation, + targetPropertyName, + targetIsArrayBinding, + moveInfo, + propertyOrder); + setDidRewriting(findTargetAndInsert(program)); + } +} diff --git a/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.h b/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.h new file mode 100644 index 0000000000..5ec981cdb8 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/moveobjectvisitor.h @@ -0,0 +1,72 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef MOVEOBJECTVISITOR_H +#define MOVEOBJECTVISITOR_H + +#include "qmlrewriter.h" + +namespace QmlEditor { +namespace Internal { + +class MoveObjectVisitor: public QMLRewriter +{ +public: + MoveObjectVisitor(QmlDesigner::TextModifier &modifier, + quint32 objectLocation, + const QString &targetPropertyName, + bool targetIsArrayBinding, + quint32 targetParentObjectLocation, + const QStringList &propertyOrder); + + bool operator ()(QmlJS::AST::UiProgram *ast); + +protected: + virtual bool visit(QmlJS::AST::UiArrayBinding *ast); + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + +private: + void doMove(QmlDesigner::TextModifier::MoveInfo moveInfo); + +private: + QList<QmlJS::AST::Node *> parents; + quint32 objectLocation; + QString targetPropertyName; + bool targetIsArrayBinding; + quint32 targetParentObjectLocation; + QStringList propertyOrder; + + QmlJS::AST::UiProgram *program; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // MOVEOBJECTVISITOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp new file mode 100644 index 0000000000..cc9f229e14 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.cpp @@ -0,0 +1,91 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "objectlengthcalculator.h" + +#include <qmljsast_p.h> + +using namespace QmlDesigner; +using namespace QmlEditor; +using namespace QmlJS::AST; + +ObjectLengthCalculator::ObjectLengthCalculator(const QString &text): + m_doc(QmlDocument::create("<internal>")) +{ + m_doc->setSource(text); + bool ok = m_doc->parse(); + + Q_ASSERT(ok); +} + +quint32 ObjectLengthCalculator::operator()(quint32 offset) +{ + m_offset = offset; + m_length = 0; + + Node::accept(m_doc->program(), this); + + return m_length; +} + +bool ObjectLengthCalculator::visit(QmlJS::AST::UiObjectBinding *ast) +{ + if (m_length > 0) + return false; + + if (ast->qualifiedTypeNameId && ast->qualifiedTypeNameId->identifierToken.isValid()) { + const quint32 start = ast->qualifiedTypeNameId->identifierToken.offset; + const quint32 end = ast->lastSourceLocation().end(); + + if (start == m_offset) { + m_length = end - start; + return false; + } + + return m_offset < end; + } else { + return true; + } +} + +bool ObjectLengthCalculator::visit(QmlJS::AST::UiObjectDefinition *ast) +{ + if (m_length > 0) + return false; + + const quint32 start = ast->firstSourceLocation().offset; + const quint32 end = ast->lastSourceLocation().end(); + + if (start == m_offset) { + m_length = end - start; + return false; + } + + return m_offset < end; +} diff --git a/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h new file mode 100644 index 0000000000..a49352c8b7 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/objectlengthcalculator.h @@ -0,0 +1,60 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef OBJECTLENGTHCALCULATOR_H +#define OBJECTLENGTHCALCULATOR_H + +#include "qmldocument.h" + +#include <qmljsastvisitor_p.h> + +namespace QmlDesigner { + +class ObjectLengthCalculator: protected QmlJS::AST::Visitor +{ +public: + ObjectLengthCalculator(const QString &text); + + quint32 operator()(quint32 offset); + +protected: + using QmlJS::AST::Visitor::visit; + + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + +private: + QmlEditor::QmlDocument::Ptr m_doc; + quint32 m_offset; + quint32 m_length; +}; + +} // namespace QmlDesigner + +#endif // OBJECTLENGTHCALCULATOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/parser/parser.pri b/src/plugins/qmldesigner/core/filemanager/parser/parser.pri new file mode 100644 index 0000000000..986b14673c --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/parser.pri @@ -0,0 +1,22 @@ + +INCLUDEPATH += $$PWD +DEPENDPATH += $$PWD + +HEADERS += $$PWD/qmljsast_p.h \ + $$PWD/qmljsastfwd_p.h \ + $$PWD/qmljsastvisitor_p.h \ + $$PWD/qmljsengine_p.h \ + $$PWD/qmljsgrammar_p.h \ + $$PWD/qmljslexer_p.h \ + $$PWD/qmljsmemorypool_p.h \ + $$PWD/qmljsnodepool_p.h \ + $$PWD/qmljsparser_p.h \ + $$PWD/qmljsglobal_p.h + +SOURCES += $$PWD/qmljsast.cpp \ + $$PWD/qmljsastvisitor.cpp \ + $$PWD/qmljsengine_p.cpp \ + $$PWD/qmljsgrammar.cpp \ + $$PWD/qmljslexer.cpp \ + $$PWD/qmljsparser.cpp + diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljs.g b/src/plugins/qmldesigner/core/filemanager/parser/qmljs.g new file mode 100644 index 0000000000..8531ed5107 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljs.g @@ -0,0 +1,3029 @@ +---------------------------------------------------------------------------- +-- +-- This file is part of Qt Creator +-- +-- Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +-- +-- Contact: Nokia Corporation (qt-info@nokia.com) +-- +-- Commercial Usage +-- +-- Licensees holding valid Qt Commercial licenses may use this file in +-- accordance with the Qt Commercial License Agreement provided with the +-- Software or, alternatively, in accordance with the terms contained in +-- a written agreement between you and Nokia. +-- +-- GNU Lesser General Public License Usage +-- +-- Alternatively, this file may be used under the terms of the GNU Lesser +-- General Public License version 2.1 as published by the Free Software +-- Foundation and appearing in the file LICENSE.LGPL included in the +-- packaging of this file. Please review the following information to +-- ensure the GNU Lesser General Public License version 2.1 requirements +-- will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +-- +-- If you are unsure which license is appropriate for your use, please +-- contact the sales department at http://qt.nokia.com/contact. +-- +---------------------------------------------------------------------------- + +%parser QmlJSGrammar +%decl qmljsparser_p.h +%impl qmljsparser.cpp +%expect 2 +%expect-rr 2 + +%token T_AND "&" T_AND_AND "&&" T_AND_EQ "&=" +%token T_BREAK "break" T_CASE "case" T_CATCH "catch" +%token T_COLON ":" T_COMMA ";" T_CONTINUE "continue" +%token T_DEFAULT "default" T_DELETE "delete" T_DIVIDE_ "/" +%token T_DIVIDE_EQ "/=" T_DO "do" T_DOT "." +%token T_ELSE "else" T_EQ "=" T_EQ_EQ "==" +%token T_EQ_EQ_EQ "===" T_FINALLY "finally" T_FOR "for" +%token T_FUNCTION "function" T_GE ">=" T_GT ">" +%token T_GT_GT ">>" T_GT_GT_EQ ">>=" T_GT_GT_GT ">>>" +%token T_GT_GT_GT_EQ ">>>=" T_IDENTIFIER "identifier" T_IF "if" +%token T_IN "in" T_INSTANCEOF "instanceof" T_LBRACE "{" +%token T_LBRACKET "[" T_LE "<=" T_LPAREN "(" +%token T_LT "<" T_LT_LT "<<" T_LT_LT_EQ "<<=" +%token T_MINUS "-" T_MINUS_EQ "-=" T_MINUS_MINUS "--" +%token T_NEW "new" T_NOT "!" T_NOT_EQ "!=" +%token T_NOT_EQ_EQ "!==" T_NUMERIC_LITERAL "numeric literal" T_OR "|" +%token T_OR_EQ "|=" T_OR_OR "||" T_PLUS "+" +%token T_PLUS_EQ "+=" T_PLUS_PLUS "++" T_QUESTION "?" +%token T_RBRACE "}" T_RBRACKET "]" T_REMAINDER "%" +%token T_REMAINDER_EQ "%=" T_RETURN "return" T_RPAREN ")" +%token T_SEMICOLON ";" T_AUTOMATIC_SEMICOLON T_STAR "*" +%token T_STAR_EQ "*=" T_STRING_LITERAL "string literal" +%token T_PROPERTY "property" T_SIGNAL "signal" T_READONLY "readonly" +%token T_SWITCH "switch" T_THIS "this" T_THROW "throw" +%token T_TILDE "~" T_TRY "try" T_TYPEOF "typeof" +%token T_VAR "var" T_VOID "void" T_WHILE "while" +%token T_WITH "with" T_XOR "^" T_XOR_EQ "^=" +%token T_NULL "null" T_TRUE "true" T_FALSE "false" +%token T_CONST "const" +%token T_DEBUGGER "debugger" +%token T_RESERVED_WORD "reserved word" +%token T_MULTILINE_STRING_LITERAL "multiline string literal" +%token T_COMMENT "comment" + +--- context keywords. +%token T_PUBLIC "public" +%token T_IMPORT "import" +%token T_AS "as" + +--- feed tokens +%token T_FEED_UI_PROGRAM +%token T_FEED_UI_OBJECT_MEMBER +%token T_FEED_JS_STATEMENT +%token T_FEED_JS_EXPRESSION + +%nonassoc SHIFT_THERE +%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY +%nonassoc REDUCE_HERE + +%start TopLevel + +/. +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <QtCore/QtDebug> + +#include <string.h> + +#include "qmljsengine_p.h" +#include "qmljslexer_p.h" +#include "qmljsast_p.h" +#include "qmljsnodepool_p.h" + +./ + +/: +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +// +// This file is automatically generated from qmljs.g. +// Changes will be lost. +// + +#ifndef QMLJSPARSER_P_H +#define QMLJSPARSER_P_H + +#include "qmljsglobal_p.h" +#include "qmljsgrammar_p.h" +#include "qmljsast_p.h" +#include "qmljsengine_p.h" + +#include <QtCore/QList> +#include <QtCore/QString> + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { + +class Engine; +class NameId; + +class Parser: protected $table +{ +public: + union Value { + int ival; + double dval; + NameId *sval; + AST::ArgumentList *ArgumentList; + AST::CaseBlock *CaseBlock; + AST::CaseClause *CaseClause; + AST::CaseClauses *CaseClauses; + AST::Catch *Catch; + AST::DefaultClause *DefaultClause; + AST::ElementList *ElementList; + AST::Elision *Elision; + AST::ExpressionNode *Expression; + AST::Finally *Finally; + AST::FormalParameterList *FormalParameterList; + AST::FunctionBody *FunctionBody; + AST::FunctionDeclaration *FunctionDeclaration; + AST::Node *Node; + AST::PropertyName *PropertyName; + AST::PropertyNameAndValueList *PropertyNameAndValueList; + AST::SourceElement *SourceElement; + AST::SourceElements *SourceElements; + AST::Statement *Statement; + AST::StatementList *StatementList; + AST::Block *Block; + AST::VariableDeclaration *VariableDeclaration; + AST::VariableDeclarationList *VariableDeclarationList; + + AST::UiProgram *UiProgram; + AST::UiImportList *UiImportList; + AST::UiImport *UiImport; + AST::UiParameterList *UiParameterList; + AST::UiPublicMember *UiPublicMember; + AST::UiObjectDefinition *UiObjectDefinition; + AST::UiObjectInitializer *UiObjectInitializer; + AST::UiObjectBinding *UiObjectBinding; + AST::UiScriptBinding *UiScriptBinding; + AST::UiArrayBinding *UiArrayBinding; + AST::UiObjectMember *UiObjectMember; + AST::UiObjectMemberList *UiObjectMemberList; + AST::UiArrayMemberList *UiArrayMemberList; + AST::UiQualifiedId *UiQualifiedId; + AST::UiSignature *UiSignature; + AST::UiFormalList *UiFormalList; + AST::UiFormal *UiFormal; + }; + +public: + Parser(Engine *engine); + ~Parser(); + + // parse a UI program + bool parse() { return parse(T_FEED_UI_PROGRAM); } + bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } + bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } + bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); } + + AST::UiProgram *ast() const + { return AST::cast<AST::UiProgram *>(program); } + + AST::Statement *statement() const + { + if (! program) + return 0; + + return program->statementCast(); + } + + AST::ExpressionNode *expression() const + { + if (! program) + return 0; + + return program->expressionCast(); + } + + AST::UiObjectMember *uiObjectMember() const + { + if (! program) + return 0; + + return program->uiObjectMemberCast(); + } + + QList<DiagnosticMessage> diagnosticMessages() const + { return diagnostic_messages; } + + inline DiagnosticMessage diagnosticMessage() const + { + foreach (const DiagnosticMessage &d, diagnostic_messages) { + if (! d.kind == DiagnosticMessage::Warning) + return d; + } + + return DiagnosticMessage(); + } + + inline QString errorMessage() const + { return diagnosticMessage().message; } + + inline int errorLineNumber() const + { return diagnosticMessage().loc.startLine; } + + inline int errorColumnNumber() const + { return diagnosticMessage().loc.startColumn; } + +protected: + bool parse(int startToken); + + void reallocateStack(); + + inline Value &sym(int index) + { return sym_stack [tos + index - 1]; } + + inline AST::SourceLocation &loc(int index) + { return location_stack [tos + index - 1]; } + + AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); + +protected: + Engine *driver; + int tos; + int stack_size; + Value *sym_stack; + int *state_stack; + AST::SourceLocation *location_stack; + + AST::Node *program; + + // error recovery + enum { TOKEN_BUFFER_SIZE = 3 }; + + struct SavedToken { + int token; + double dval; + AST::SourceLocation loc; + }; + + double yylval; + AST::SourceLocation yylloc; + AST::SourceLocation yyprevlloc; + + SavedToken token_buffer[TOKEN_BUFFER_SIZE]; + SavedToken *first_token; + SavedToken *last_token; + + QList<DiagnosticMessage> diagnostic_messages; +}; + +} // end of namespace QmlJS + + +:/ + + +/. + +#include "qmljsparser_p.h" +#include <QVarLengthArray> + +// +// This file is automatically generated from qmljs.g. +// Changes will be lost. +// + +using namespace QmlJS; + +QT_QML_BEGIN_NAMESPACE + +void Parser::reallocateStack() +{ + if (! stack_size) + stack_size = 128; + else + stack_size <<= 1; + + sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value))); + state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int))); + location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation))); +} + +inline static bool automatic(Engine *driver, int token) +{ + return token == $table::T_RBRACE + || token == 0 + || driver->lexer()->prevTerminator(); +} + + +Parser::Parser(Engine *engine): + driver(engine), + tos(0), + stack_size(0), + sym_stack(0), + state_stack(0), + location_stack(0), + first_token(0), + last_token(0) +{ +} + +Parser::~Parser() +{ + if (stack_size) { + qFree(sym_stack); + qFree(state_stack); + qFree(location_stack); + } +} + +static inline AST::SourceLocation location(Lexer *lexer) +{ + AST::SourceLocation loc; + loc.offset = lexer->tokenOffset(); + loc.length = lexer->tokenLength(); + loc.startLine = lexer->startLineNo(); + loc.startColumn = lexer->startColumnNo(); + return loc; +} + +AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) +{ + QVarLengthArray<NameId *, 4> nameIds; + QVarLengthArray<AST::SourceLocation, 4> locations; + + AST::ExpressionNode *it = expr; + while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) { + nameIds.append(m->name); + locations.append(m->identifierToken); + it = m->base; + } + + if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) { + AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name); + q->identifierToken = idExpr->identifierToken; + + AST::UiQualifiedId *currentId = q; + for (int i = nameIds.size() - 1; i != -1; --i) { + currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]); + currentId->identifierToken = locations[i]; + } + + return currentId->finish(); + } + + return 0; +} + +bool Parser::parse(int startToken) +{ + Lexer *lexer = driver->lexer(); + bool hadErrors = false; + int yytoken = -1; + int action = 0; + + token_buffer[0].token = startToken; + first_token = &token_buffer[0]; + last_token = &token_buffer[1]; + + tos = -1; + program = 0; + + do { + if (++tos == stack_size) + reallocateStack(); + + state_stack[tos] = action; + + _Lcheck_token: + if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { + yyprevlloc = yylloc; + + if (first_token == last_token) { + yytoken = lexer->lex(); + yylval = lexer->dval(); + yylloc = location(lexer); + } else { + yytoken = first_token->token; + yylval = first_token->dval; + yylloc = first_token->loc; + ++first_token; + } + } + + action = t_action(action, yytoken); + if (action > 0) { + if (action != ACCEPT_STATE) { + yytoken = -1; + sym(1).dval = yylval; + loc(1) = yylloc; + } else { + --tos; + return ! hadErrors; + } + } else if (action < 0) { + const int r = -action - 1; + tos -= rhs[r]; + + switch (r) { +./ + +-------------------------------------------------------------------------------------------------------- +-- Declarative UI +-------------------------------------------------------------------------------------------------------- + +TopLevel: T_FEED_UI_PROGRAM UiProgram ; +/. +case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; +./ + +TopLevel: T_FEED_JS_STATEMENT Statement ; +/. +case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; +./ + +TopLevel: T_FEED_JS_EXPRESSION Expression ; +/. +case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; +./ + +TopLevel: T_FEED_UI_OBJECT_MEMBER UiObjectMember ; +/. +case $rule_number: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; +./ + +UiProgram: UiImportListOpt UiRootMember ; +/. +case $rule_number: { + sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList, + sym(2).UiObjectMemberList->finish()); +} break; +./ + +UiImportListOpt: Empty ; +UiImportListOpt: UiImportList ; +/. +case $rule_number: { + sym(1).Node = sym(1).UiImportList->finish(); +} break; +./ + +UiImportList: UiImport ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport); +} break; +./ + +UiImportList: UiImportList UiImport ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), + sym(1).UiImportList, sym(2).UiImport); +} break; +./ + +ImportId: MemberExpression ; + +UiImport: UiImportHead T_AUTOMATIC_SEMICOLON ; +UiImport: UiImportHead T_SEMICOLON ; +/. +case $rule_number: { + sym(1).UiImport->semicolonToken = loc(2); +} break; +./ + +UiImport: UiImportHead T_NUMERIC_LITERAL T_AUTOMATIC_SEMICOLON ; +UiImport: UiImportHead T_NUMERIC_LITERAL T_SEMICOLON ; +/. +case $rule_number: { + sym(1).UiImport->versionToken = loc(2); + sym(1).UiImport->semicolonToken = loc(3); +} break; +./ + +UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ; +UiImport: UiImportHead T_NUMERIC_LITERAL T_AS JsIdentifier T_SEMICOLON ; +/. +case $rule_number: { + sym(1).UiImport->versionToken = loc(2); + sym(1).UiImport->asToken = loc(3); + sym(1).UiImport->importIdToken = loc(4); + sym(1).UiImport->importId = sym(4).sval; + sym(1).UiImport->semicolonToken = loc(5); +} break; +./ + +UiImport: UiImportHead T_AS JsIdentifier T_AUTOMATIC_SEMICOLON ; +UiImport: UiImportHead T_AS JsIdentifier T_SEMICOLON ; +/. +case $rule_number: { + sym(1).UiImport->asToken = loc(2); + sym(1).UiImport->importIdToken = loc(3); + sym(1).UiImport->importId = sym(3).sval; + sym(1).UiImport->semicolonToken = loc(4); +} break; +./ + + +UiImportHead: T_IMPORT ImportId ; +/. +case $rule_number: { + AST::UiImport *node = 0; + + if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) { + node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value); + node->fileNameToken = loc(2); + } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { + QString text; + for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) { + text += q->name->asString(); + if (q->next) text += QLatin1String("."); + } + node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId); + node->fileNameToken = loc(2); + } + + sym(1).Node = node; + + if (! node) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), + QLatin1String("Expected a qualified name id or a string literal"))); + + return false; // ### remove me + } +} break; +./ + +Empty: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +UiRootMember: UiObjectDefinition ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember); +} break; +./ + +UiObjectMemberList: UiObjectMember ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember); +} break; +./ + +UiObjectMemberList: UiObjectMemberList UiObjectMember ; +/. +case $rule_number: { + AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(), + sym(1).UiObjectMemberList, sym(2).UiObjectMember); + sym(1).Node = node; +} break; +./ + +UiArrayMemberList: UiObjectDefinition ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember); +} break; +./ + +UiArrayMemberList: UiArrayMemberList T_COMMA UiObjectDefinition ; +/. +case $rule_number: { + AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), + sym(1).UiArrayMemberList, sym(3).UiObjectMember); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +UiObjectInitializer: T_LBRACE T_RBRACE ; +/. +case $rule_number: { + AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0); + node->lbraceToken = loc(1); + node->rbraceToken = loc(2); + sym(1).Node = node; +} break; +./ + +UiObjectInitializer: T_LBRACE UiObjectMemberList T_RBRACE ; +/. +case $rule_number: { + AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish()); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; +./ + +UiObjectDefinition: UiQualifiedId UiObjectInitializer ; +/. +case $rule_number: { + AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId, + sym(2).UiObjectInitializer); + sym(1).Node = node; +} break; +./ + +UiObjectMember: UiObjectDefinition ; + +UiObjectMember: UiQualifiedId T_COLON T_LBRACKET UiArrayMemberList T_RBRACKET ; +/. +case $rule_number: { + AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), + sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); + node->colonToken = loc(2); + node->lbracketToken = loc(3); + node->rbracketToken = loc(5); + sym(1).Node = node; +} break; +./ + +UiObjectMember: UiQualifiedId T_COLON UiQualifiedId UiObjectInitializer ; +/. +case $rule_number: { + AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), + sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +UiObjectMember: UiQualifiedId T_COLON Block ; +/.case $rule_number:./ + +UiObjectMember: UiQualifiedId T_COLON EmptyStatement ; +/.case $rule_number:./ + +UiObjectMember: UiQualifiedId T_COLON ExpressionStatement ; +/.case $rule_number:./ + +UiObjectMember: UiQualifiedId T_COLON IfStatement ; --- ### do we really want if statement in a binding? +/.case $rule_number:./ + +/. +{ + AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), + sym(1).UiQualifiedId, sym(3).Statement); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +UiPropertyType: T_VAR ; +/. +case $rule_number: +./ +UiPropertyType: T_RESERVED_WORD ; +/. +case $rule_number: { + sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); + break; +} +./ + +UiPropertyType: T_IDENTIFIER ; + +UiParameterListOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +UiParameterListOpt: UiParameterList ; +/. +case $rule_number: { + sym(1).Node = sym(1).UiParameterList->finish (); +} break; +./ + +UiParameterList: UiPropertyType JsIdentifier ; +/. +case $rule_number: { + AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval); + node->identifierToken = loc(2); + sym(1).Node = node; +} break; +./ + +UiParameterList: UiParameterList T_COMMA UiPropertyType JsIdentifier ; +/. +case $rule_number: { + AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval); + node->commaToken = loc(2); + node->identifierToken = loc(4); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_SIGNAL T_IDENTIFIER T_LPAREN UiParameterListOpt T_RPAREN T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); + node->type = AST::UiPublicMember::Signal; + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(2); + node->parameters = sym(4).UiParameterList; + node->semicolonToken = loc(6); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_SIGNAL T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_SIGNAL T_IDENTIFIER T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); + node->type = AST::UiPublicMember::Signal; + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_PROPERTY T_IDENTIFIER T_LT UiPropertyType T_GT T_IDENTIFIER T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval); + node->typeModifier = sym(2).sval; + node->propertyToken = loc(1); + node->typeModifierToken = loc(2); + node->typeToken = loc(4); + node->identifierToken = loc(6); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->semicolonToken = loc(4); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->semicolonToken = loc(5); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval, + sym(5).Expression); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->colonToken = loc(4); + node->semicolonToken = loc(6); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_READONLY T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_READONLY T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, + sym(6).Expression); + node->isReadonlyMember = true; + node->readonlyToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->colonToken = loc(5); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; +./ + +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_AUTOMATIC_SEMICOLON ; +UiObjectMember: T_DEFAULT T_PROPERTY UiPropertyType T_IDENTIFIER T_COLON Expression T_SEMICOLON ; +/. +case $rule_number: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, + sym(6).Expression); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->colonToken = loc(5); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; +./ + +UiObjectMember: FunctionDeclaration ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); +} break; +./ + +UiObjectMember: VariableStatement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); +} break; +./ + +JsIdentifier: T_IDENTIFIER; + +JsIdentifier: T_PROPERTY ; +/. +case $rule_number: { + QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]); + sym(1).sval = driver->intern(s.constData(), s.length()); + break; +} +./ + +JsIdentifier: T_SIGNAL ; +/. +case $rule_number: { + QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]); + sym(1).sval = driver->intern(s.constData(), s.length()); + break; +} +./ + +JsIdentifier: T_READONLY ; +/. +case $rule_number: { + QString s = QLatin1String(QmlJSGrammar::spell[T_READONLY]); + sym(1).sval = driver->intern(s.constData(), s.length()); + break; +} +./ + +-------------------------------------------------------------------------------------------------------- +-- Expressions +-------------------------------------------------------------------------------------------------------- + +PrimaryExpression: T_THIS ; +/. +case $rule_number: { + AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool()); + node->thisToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: JsIdentifier ; +/. +case $rule_number: { + AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_NULL ; +/. +case $rule_number: { + AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool()); + node->nullToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_TRUE ; +/. +case $rule_number: { + AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool()); + node->trueToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_FALSE ; +/. +case $rule_number: { + AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool()); + node->falseToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_NUMERIC_LITERAL ; +/. +case $rule_number: { + AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval); + node->literalToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_MULTILINE_STRING_LITERAL ; +/.case $rule_number:./ + +PrimaryExpression: T_STRING_LITERAL ; +/. +case $rule_number: { + AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval); + node->literalToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_DIVIDE_ ; +/: +#define J_SCRIPT_REGEXPLITERAL_RULE1 $rule_number +:/ +/. +case $rule_number: { + bool rx = lexer->scanRegExp(Lexer::NoPrefix); + if (!rx) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); + return false; // ### remove me + } + AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags); + node->literalToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_DIVIDE_EQ ; +/: +#define J_SCRIPT_REGEXPLITERAL_RULE2 $rule_number +:/ +/. +case $rule_number: { + bool rx = lexer->scanRegExp(Lexer::EqualPrefix); + if (!rx) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); + return false; + } + AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags); + node->literalToken = loc(1); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->rbracketToken = loc(2); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET Elision T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish()); + node->lbracketToken = loc(1); + node->rbracketToken = loc(3); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET ElementList T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ()); + node->lbracketToken = loc(1); + node->rbracketToken = loc(3); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET ElementList T_COMMA T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACKET ElementList T_COMMA Elision T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + sym(4).Elision->finish()); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(5); + sym(1).Node = node; +} break; +./ + +-- PrimaryExpression: T_LBRACE T_RBRACE ; +-- /. +-- case $rule_number: { +-- sym(1).Node = makeAstNode<AST::ObjectLiteral> (driver->nodePool()); +-- } break; +-- ./ + +PrimaryExpression: T_LBRACE PropertyNameAndValueListOpt T_RBRACE ; +/. +case $rule_number: { + AST::ObjectLiteral *node = 0; + if (sym(2).Node) + node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), + sym(2).PropertyNameAndValueList->finish ()); + else + node = makeAstNode<AST::ObjectLiteral> (driver->nodePool()); + node->lbraceToken = loc(1); + node->lbraceToken = loc(3); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LBRACE PropertyNameAndValueList T_COMMA T_RBRACE ; +/. +case $rule_number: { + AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), + sym(2).PropertyNameAndValueList->finish ()); + node->lbraceToken = loc(1); + node->lbraceToken = loc(4); + sym(1).Node = node; +} break; +./ + +PrimaryExpression: T_LPAREN Expression T_RPAREN ; +/. +case $rule_number: { + AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression); + node->lparenToken = loc(1); + node->rparenToken = loc(3); + sym(1).Node = node; +} break; +./ + +UiQualifiedId: MemberExpression ; +/. +case $rule_number: { + if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, + QLatin1String("Ignored annotation"))); + + sym(1).Expression = mem->base; + } + + if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) { + sym(1).UiQualifiedId = qualifiedId; + } else { + sym(1).UiQualifiedId = 0; + + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), + QLatin1String("Expected a qualified name id"))); + + return false; // ### recover + } +} break; +./ + +ElementList: AssignmentExpression ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); +} break; +./ + +ElementList: Elision AssignmentExpression ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); +} break; +./ + +ElementList: ElementList T_COMMA AssignmentExpression ; +/. +case $rule_number: { + AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, + (AST::Elision *) 0, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +ElementList: ElementList T_COMMA Elision AssignmentExpression ; +/. +case $rule_number: { + AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), + sym(4).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +Elision: T_COMMA ; +/. +case $rule_number: { + AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool()); + node->commaToken = loc(1); + sym(1).Node = node; +} break; +./ + +Elision: Elision T_COMMA ; +/. +case $rule_number: { + AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +PropertyNameAndValueList: PropertyName T_COLON AssignmentExpression ; +/. +case $rule_number: { + AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), + sym(1).PropertyName, sym(3).Expression); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +PropertyNameAndValueList: PropertyNameAndValueList T_COMMA PropertyName T_COLON AssignmentExpression ; +/. +case $rule_number: { + AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), + sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); + node->commaToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; +./ + +PropertyName: T_IDENTIFIER %prec REDUCE_HERE ; +/. +case $rule_number: { + AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +./ + +PropertyName: T_SIGNAL ; +/.case $rule_number:./ + +PropertyName: T_PROPERTY ; +/. +case $rule_number: { + AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +./ + +PropertyName: T_STRING_LITERAL ; +/. +case $rule_number: { + AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +./ + +PropertyName: T_NUMERIC_LITERAL ; +/. +case $rule_number: { + AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +./ + +PropertyName: ReservedIdentifier ; +/. +case $rule_number: { + AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +./ + +ReservedIdentifier: T_BREAK ; +/. +case $rule_number: +./ +ReservedIdentifier: T_CASE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_CATCH ; +/. +case $rule_number: +./ +ReservedIdentifier: T_CONTINUE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_DEFAULT ; +/. +case $rule_number: +./ +ReservedIdentifier: T_DELETE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_DO ; +/. +case $rule_number: +./ +ReservedIdentifier: T_ELSE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_FALSE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_FINALLY ; +/. +case $rule_number: +./ +ReservedIdentifier: T_FOR ; +/. +case $rule_number: +./ +ReservedIdentifier: T_FUNCTION ; +/. +case $rule_number: +./ +ReservedIdentifier: T_IF ; +/. +case $rule_number: +./ +ReservedIdentifier: T_IN ; +/. +case $rule_number: +./ +ReservedIdentifier: T_INSTANCEOF ; +/. +case $rule_number: +./ +ReservedIdentifier: T_NEW ; +/. +case $rule_number: +./ +ReservedIdentifier: T_NULL ; +/. +case $rule_number: +./ +ReservedIdentifier: T_RETURN ; +/. +case $rule_number: +./ +ReservedIdentifier: T_SWITCH ; +/. +case $rule_number: +./ +ReservedIdentifier: T_THIS ; +/. +case $rule_number: +./ +ReservedIdentifier: T_THROW ; +/. +case $rule_number: +./ +ReservedIdentifier: T_TRUE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_TRY ; +/. +case $rule_number: +./ +ReservedIdentifier: T_TYPEOF ; +/. +case $rule_number: +./ +ReservedIdentifier: T_VAR ; +/. +case $rule_number: +./ +ReservedIdentifier: T_VOID ; +/. +case $rule_number: +./ +ReservedIdentifier: T_WHILE ; +/. +case $rule_number: +./ +ReservedIdentifier: T_CONST ; +/. +case $rule_number: +./ +ReservedIdentifier: T_DEBUGGER ; +/. +case $rule_number: +./ +ReservedIdentifier: T_RESERVED_WORD ; +/. +case $rule_number: +./ +ReservedIdentifier: T_WITH ; +/. +case $rule_number: +{ + sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); +} break; +./ + +PropertyIdentifier: JsIdentifier ; +PropertyIdentifier: ReservedIdentifier ; + +MemberExpression: PrimaryExpression ; +MemberExpression: FunctionExpression ; + +MemberExpression: MemberExpression T_LBRACKET Expression T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->lbracketToken = loc(2); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; +./ + +MemberExpression: MemberExpression T_DOT PropertyIdentifier ; +/. +case $rule_number: { + AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; +./ + +MemberExpression: T_NEW MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; +/. +case $rule_number: { + AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); + node->newToken = loc(1); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + sym(1).Node = node; +} break; +./ + +NewExpression: MemberExpression ; + +NewExpression: T_NEW NewExpression ; +/. +case $rule_number: { + AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression); + node->newToken = loc(1); + sym(1).Node = node; +} break; +./ + +CallExpression: MemberExpression T_LPAREN ArgumentListOpt T_RPAREN ; +/. +case $rule_number: { + AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +CallExpression: CallExpression T_LPAREN ArgumentListOpt T_RPAREN ; +/. +case $rule_number: { + AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +CallExpression: CallExpression T_LBRACKET Expression T_RBRACKET ; +/. +case $rule_number: { + AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->lbracketToken = loc(2); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; +./ + +CallExpression: CallExpression T_DOT PropertyIdentifier ; +/. +case $rule_number: { + AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; +./ + +ArgumentListOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +ArgumentListOpt: ArgumentList ; +/. +case $rule_number: { + sym(1).Node = sym(1).ArgumentList->finish(); +} break; +./ + +ArgumentList: AssignmentExpression ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression); +} break; +./ + +ArgumentList: ArgumentList T_COMMA AssignmentExpression ; +/. +case $rule_number: { + AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +LeftHandSideExpression: NewExpression ; +LeftHandSideExpression: CallExpression ; +PostfixExpression: LeftHandSideExpression ; + +PostfixExpression: LeftHandSideExpression T_PLUS_PLUS ; +/. +case $rule_number: { + AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression); + node->incrementToken = loc(2); + sym(1).Node = node; +} break; +./ + +PostfixExpression: LeftHandSideExpression T_MINUS_MINUS ; +/. +case $rule_number: { + AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression); + node->decrementToken = loc(2); + sym(1).Node = node; +} break; +./ + +UnaryExpression: PostfixExpression ; + +UnaryExpression: T_DELETE UnaryExpression ; +/. +case $rule_number: { + AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression); + node->deleteToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_VOID UnaryExpression ; +/. +case $rule_number: { + AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression); + node->voidToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_TYPEOF UnaryExpression ; +/. +case $rule_number: { + AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression); + node->typeofToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_PLUS_PLUS UnaryExpression ; +/. +case $rule_number: { + AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression); + node->incrementToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_MINUS_MINUS UnaryExpression ; +/. +case $rule_number: { + AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression); + node->decrementToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_PLUS UnaryExpression ; +/. +case $rule_number: { + AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression); + node->plusToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_MINUS UnaryExpression ; +/. +case $rule_number: { + AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression); + node->minusToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_TILDE UnaryExpression ; +/. +case $rule_number: { + AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression); + node->tildeToken = loc(1); + sym(1).Node = node; +} break; +./ + +UnaryExpression: T_NOT UnaryExpression ; +/. +case $rule_number: { + AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression); + node->notToken = loc(1); + sym(1).Node = node; +} break; +./ + +MultiplicativeExpression: UnaryExpression ; + +MultiplicativeExpression: MultiplicativeExpression T_STAR UnaryExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Mul, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +MultiplicativeExpression: MultiplicativeExpression T_DIVIDE_ UnaryExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Div, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +MultiplicativeExpression: MultiplicativeExpression T_REMAINDER UnaryExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Mod, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +AdditiveExpression: MultiplicativeExpression ; + +AdditiveExpression: AdditiveExpression T_PLUS MultiplicativeExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Add, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +AdditiveExpression: AdditiveExpression T_MINUS MultiplicativeExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Sub, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +ShiftExpression: AdditiveExpression ; + +ShiftExpression: ShiftExpression T_LT_LT AdditiveExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::LShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +ShiftExpression: ShiftExpression T_GT_GT AdditiveExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::RShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +ShiftExpression: ShiftExpression T_GT_GT_GT AdditiveExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::URShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: ShiftExpression ; + +RelationalExpression: RelationalExpression T_LT ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Lt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: RelationalExpression T_GT ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Gt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: RelationalExpression T_LE ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Le, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: RelationalExpression T_GE ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Ge, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: RelationalExpression T_INSTANCEOF ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::InstanceOf, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpression: RelationalExpression T_IN ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::In, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpressionNotIn: ShiftExpression ; + +RelationalExpressionNotIn: RelationalExpressionNotIn T_LT ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Lt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpressionNotIn: RelationalExpressionNotIn T_GT ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Gt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpressionNotIn: RelationalExpressionNotIn T_LE ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Le, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpressionNotIn: RelationalExpressionNotIn T_GE ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Ge, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +RelationalExpressionNotIn: RelationalExpressionNotIn T_INSTANCEOF ShiftExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::InstanceOf, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpression: RelationalExpression ; + +EqualityExpression: EqualityExpression T_EQ_EQ RelationalExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Equal, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpression: EqualityExpression T_NOT_EQ RelationalExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::NotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpression: EqualityExpression T_EQ_EQ_EQ RelationalExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::StrictEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpression: EqualityExpression T_NOT_EQ_EQ RelationalExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::StrictNotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpressionNotIn: RelationalExpressionNotIn ; + +EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ RelationalExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Equal, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ RelationalExpressionNotIn; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::NotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpressionNotIn: EqualityExpressionNotIn T_EQ_EQ_EQ RelationalExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::StrictEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +EqualityExpressionNotIn: EqualityExpressionNotIn T_NOT_EQ_EQ RelationalExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::StrictNotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseANDExpression: EqualityExpression ; + +BitwiseANDExpression: BitwiseANDExpression T_AND EqualityExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitAnd, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseANDExpressionNotIn: EqualityExpressionNotIn ; + +BitwiseANDExpressionNotIn: BitwiseANDExpressionNotIn T_AND EqualityExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitAnd, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseXORExpression: BitwiseANDExpression ; + +BitwiseXORExpression: BitwiseXORExpression T_XOR BitwiseANDExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitXor, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseXORExpressionNotIn: BitwiseANDExpressionNotIn ; + +BitwiseXORExpressionNotIn: BitwiseXORExpressionNotIn T_XOR BitwiseANDExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitXor, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseORExpression: BitwiseXORExpression ; + +BitwiseORExpression: BitwiseORExpression T_OR BitwiseXORExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +BitwiseORExpressionNotIn: BitwiseXORExpressionNotIn ; + +BitwiseORExpressionNotIn: BitwiseORExpressionNotIn T_OR BitwiseXORExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +LogicalANDExpression: BitwiseORExpression ; + +LogicalANDExpression: LogicalANDExpression T_AND_AND BitwiseORExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +LogicalANDExpressionNotIn: BitwiseORExpressionNotIn ; + +LogicalANDExpressionNotIn: LogicalANDExpressionNotIn T_AND_AND BitwiseORExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +LogicalORExpression: LogicalANDExpression ; + +LogicalORExpression: LogicalORExpression T_OR_OR LogicalANDExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +LogicalORExpressionNotIn: LogicalANDExpressionNotIn ; + +LogicalORExpressionNotIn: LogicalORExpressionNotIn T_OR_OR LogicalANDExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +ConditionalExpression: LogicalORExpression ; + +ConditionalExpression: LogicalORExpression T_QUESTION AssignmentExpression T_COLON AssignmentExpression ; +/. +case $rule_number: { + AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, + sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; +./ + +ConditionalExpressionNotIn: LogicalORExpressionNotIn ; + +ConditionalExpressionNotIn: LogicalORExpressionNotIn T_QUESTION AssignmentExpressionNotIn T_COLON AssignmentExpressionNotIn ; +/. +case $rule_number: { + AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, + sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; +./ + +AssignmentExpression: ConditionalExpression ; + +AssignmentExpression: LeftHandSideExpression AssignmentOperator AssignmentExpression ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +AssignmentExpressionNotIn: ConditionalExpressionNotIn ; + +AssignmentExpressionNotIn: LeftHandSideExpression AssignmentOperator AssignmentExpressionNotIn ; +/. +case $rule_number: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; +./ + +AssignmentOperator: T_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::Assign; +} break; +./ + +AssignmentOperator: T_STAR_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceMul; +} break; +./ + +AssignmentOperator: T_DIVIDE_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceDiv; +} break; +./ + +AssignmentOperator: T_REMAINDER_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceMod; +} break; +./ + +AssignmentOperator: T_PLUS_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceAdd; +} break; +./ + +AssignmentOperator: T_MINUS_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceSub; +} break; +./ + +AssignmentOperator: T_LT_LT_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceLeftShift; +} break; +./ + +AssignmentOperator: T_GT_GT_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceRightShift; +} break; +./ + +AssignmentOperator: T_GT_GT_GT_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceURightShift; +} break; +./ + +AssignmentOperator: T_AND_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceAnd; +} break; +./ + +AssignmentOperator: T_XOR_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceXor; +} break; +./ + +AssignmentOperator: T_OR_EQ ; +/. +case $rule_number: { + sym(1).ival = QSOperator::InplaceOr; +} break; +./ + +Expression: AssignmentExpression ; + +Expression: Expression T_COMMA AssignmentExpression ; +/. +case $rule_number: { + AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +ExpressionOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +ExpressionOpt: Expression ; + +ExpressionNotIn: AssignmentExpressionNotIn ; + +ExpressionNotIn: ExpressionNotIn T_COMMA AssignmentExpressionNotIn ; +/. +case $rule_number: { + AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +ExpressionNotInOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +ExpressionNotInOpt: ExpressionNotIn ; + +Statement: Block ; +Statement: VariableStatement ; +Statement: EmptyStatement ; +Statement: ExpressionStatement ; +Statement: IfStatement ; +Statement: IterationStatement ; +Statement: ContinueStatement ; +Statement: BreakStatement ; +Statement: ReturnStatement ; +Statement: WithStatement ; +Statement: LabelledStatement ; +Statement: SwitchStatement ; +Statement: ThrowStatement ; +Statement: TryStatement ; +Statement: DebuggerStatement ; + + +Block: T_LBRACE StatementListOpt T_RBRACE ; +/. +case $rule_number: { + AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; +./ + +StatementList: Statement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement); +} break; +./ + +StatementList: StatementList Statement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement); +} break; +./ + +StatementListOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +StatementListOpt: StatementList ; +/. +case $rule_number: { + sym(1).Node = sym(1).StatementList->finish (); +} break; +./ + +VariableStatement: VariableDeclarationKind VariableDeclarationList T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +VariableStatement: VariableDeclarationKind VariableDeclarationList T_SEMICOLON ; +/. +case $rule_number: { + AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(), + sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); + node->declarationKindToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +VariableDeclarationKind: T_CONST ; +/. +case $rule_number: { + sym(1).ival = T_CONST; +} break; +./ + +VariableDeclarationKind: T_VAR ; +/. +case $rule_number: { + sym(1).ival = T_VAR; +} break; +./ + +VariableDeclarationList: VariableDeclaration ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); +} break; +./ + +VariableDeclarationList: VariableDeclarationList T_COMMA VariableDeclaration ; +/. +case $rule_number: { + AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), + sym(1).VariableDeclarationList, sym(3).VariableDeclaration); + node->commaToken = loc(2); + sym(1).Node = node; +} break; +./ + +VariableDeclarationListNotIn: VariableDeclarationNotIn ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); +} break; +./ + +VariableDeclarationListNotIn: VariableDeclarationListNotIn T_COMMA VariableDeclarationNotIn ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); +} break; +./ + +VariableDeclaration: JsIdentifier InitialiserOpt ; +/. +case $rule_number: { + AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +VariableDeclarationNotIn: JsIdentifier InitialiserNotInOpt ; +/. +case $rule_number: { + AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +Initialiser: T_EQ AssignmentExpression ; +/. +case $rule_number: { + // ### TODO: AST for initializer + sym(1) = sym(2); +} break; +./ + +InitialiserOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +InitialiserOpt: Initialiser ; + +InitialiserNotIn: T_EQ AssignmentExpressionNotIn ; +/. +case $rule_number: { + // ### TODO: AST for initializer + sym(1) = sym(2); +} break; +./ + +InitialiserNotInOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +InitialiserNotInOpt: InitialiserNotIn ; + +EmptyStatement: T_SEMICOLON ; +/. +case $rule_number: { + AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool()); + node->semicolonToken = loc(1); + sym(1).Node = node; +} break; +./ + +ExpressionStatement: Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +ExpressionStatement: Expression T_SEMICOLON ; +/. +case $rule_number: { + AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; +./ + +IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement T_ELSE Statement ; +/. +case $rule_number: { + AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); + node->ifToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + node->elseToken = loc(5); + sym(1).Node = node; +} break; +./ + +IfStatement: T_IF T_LPAREN Expression T_RPAREN Statement ; +/. +case $rule_number: { + AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->ifToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + + +IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +IterationStatement: T_DO Statement T_WHILE T_LPAREN Expression T_RPAREN T_SEMICOLON ; +/. +case $rule_number: { + AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression); + node->doToken = loc(1); + node->whileToken = loc(3); + node->lparenToken = loc(4); + node->rparenToken = loc(6); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; +./ + +IterationStatement: T_WHILE T_LPAREN Expression T_RPAREN Statement ; +/. +case $rule_number: { + AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->whileToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +IterationStatement: T_FOR T_LPAREN ExpressionNotInOpt T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; +/. +case $rule_number: { + AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression, + sym(5).Expression, sym(7).Expression, sym(9).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->firstSemicolonToken = loc(4); + node->secondSemicolonToken = loc(6); + node->rparenToken = loc(8); + sym(1).Node = node; +} break; +./ + +IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationListNotIn T_SEMICOLON ExpressionOpt T_SEMICOLON ExpressionOpt T_RPAREN Statement ; +/. +case $rule_number: { + AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(), + sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, + sym(8).Expression, sym(10).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->varToken = loc(3); + node->firstSemicolonToken = loc(5); + node->secondSemicolonToken = loc(7); + node->rparenToken = loc(9); + sym(1).Node = node; +} break; +./ + +IterationStatement: T_FOR T_LPAREN LeftHandSideExpression T_IN Expression T_RPAREN Statement ; +/. +case $rule_number: { + AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression, + sym(5).Expression, sym(7).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->inToken = loc(4); + node->rparenToken = loc(6); + sym(1).Node = node; +} break; +./ + +IterationStatement: T_FOR T_LPAREN T_VAR VariableDeclarationNotIn T_IN Expression T_RPAREN Statement ; +/. +case $rule_number: { + AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(), + sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->varToken = loc(3); + node->inToken = loc(5); + node->rparenToken = loc(7); + sym(1).Node = node; +} break; +./ + +ContinueStatement: T_CONTINUE T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +ContinueStatement: T_CONTINUE T_SEMICOLON ; +/. +case $rule_number: { + AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool()); + node->continueToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; +./ + +ContinueStatement: T_CONTINUE JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +ContinueStatement: T_CONTINUE JsIdentifier T_SEMICOLON ; +/. +case $rule_number: { + AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval); + node->continueToken = loc(1); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +BreakStatement: T_BREAK T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +BreakStatement: T_BREAK T_SEMICOLON ; +/. +case $rule_number: { + AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool()); + node->breakToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; +./ + +BreakStatement: T_BREAK JsIdentifier T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +BreakStatement: T_BREAK JsIdentifier T_SEMICOLON ; +/. +case $rule_number: { + AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval); + node->breakToken = loc(1); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +ReturnStatement: T_RETURN ExpressionOpt T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +ReturnStatement: T_RETURN ExpressionOpt T_SEMICOLON ; +/. +case $rule_number: { + AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression); + node->returnToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +WithStatement: T_WITH T_LPAREN Expression T_RPAREN Statement ; +/. +case $rule_number: { + AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->withToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +SwitchStatement: T_SWITCH T_LPAREN Expression T_RPAREN CaseBlock ; +/. +case $rule_number: { + AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); + node->switchToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +CaseBlock: T_LBRACE CaseClausesOpt T_RBRACE ; +/. +case $rule_number: { + AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; +./ + +CaseBlock: T_LBRACE CaseClausesOpt DefaultClause CaseClausesOpt T_RBRACE ; +/. +case $rule_number: { + AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); + node->lbraceToken = loc(1); + node->rbraceToken = loc(5); + sym(1).Node = node; +} break; +./ + +CaseClauses: CaseClause ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause); +} break; +./ + +CaseClauses: CaseClauses CaseClause ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); +} break; +./ + +CaseClausesOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +CaseClausesOpt: CaseClauses ; +/. +case $rule_number: { + sym(1).Node = sym(1).CaseClauses->finish (); +} break; +./ + +CaseClause: T_CASE Expression T_COLON StatementListOpt ; +/. +case $rule_number: { + AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList); + node->caseToken = loc(1); + node->colonToken = loc(3); + sym(1).Node = node; +} break; +./ + +DefaultClause: T_DEFAULT T_COLON StatementListOpt ; +/. +case $rule_number: { + AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList); + node->defaultToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +LabelledStatement: T_SIGNAL T_COLON Statement ; +/.case $rule_number:./ + +LabelledStatement: T_PROPERTY T_COLON Statement ; +/. +case $rule_number: { + AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); + node->identifierToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +LabelledStatement: T_IDENTIFIER T_COLON Statement ; +/. +case $rule_number: { + AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement); + node->identifierToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +./ + +ThrowStatement: T_THROW Expression T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +ThrowStatement: T_THROW Expression T_SEMICOLON ; +/. +case $rule_number: { + AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression); + node->throwToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; +./ + +TryStatement: T_TRY Block Catch ; +/. +case $rule_number: { + AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch); + node->tryToken = loc(1); + sym(1).Node = node; +} break; +./ + +TryStatement: T_TRY Block Finally ; +/. +case $rule_number: { + AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally); + node->tryToken = loc(1); + sym(1).Node = node; +} break; +./ + +TryStatement: T_TRY Block Catch Finally ; +/. +case $rule_number: { + AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); + node->tryToken = loc(1); + sym(1).Node = node; +} break; +./ + +Catch: T_CATCH T_LPAREN JsIdentifier T_RPAREN Block ; +/. +case $rule_number: { + AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block); + node->catchToken = loc(1); + node->lparenToken = loc(2); + node->identifierToken = loc(3); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; +./ + +Finally: T_FINALLY Block ; +/. +case $rule_number: { + AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block); + node->finallyToken = loc(1); + sym(1).Node = node; +} break; +./ + +DebuggerStatement: T_DEBUGGER T_AUTOMATIC_SEMICOLON ; -- automatic semicolon +DebuggerStatement: T_DEBUGGER T_SEMICOLON ; +/. +case $rule_number: { + AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool()); + node->debuggerToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; +./ + +FunctionDeclaration: T_FUNCTION JsIdentifier T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; +/. +case $rule_number: { + AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + node->functionToken = loc(1); + node->identifierToken = loc(2); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; +} break; +./ + +FunctionExpression: T_FUNCTION IdentifierOpt T_LPAREN FormalParameterListOpt T_RPAREN T_LBRACE FunctionBodyOpt T_RBRACE ; +/. +case $rule_number: { + AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + node->functionToken = loc(1); + if (sym(2).sval) + node->identifierToken = loc(2); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; +} break; +./ + +FormalParameterList: JsIdentifier ; +/. +case $rule_number: { + AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; +./ + +FormalParameterList: FormalParameterList T_COMMA JsIdentifier ; +/. +case $rule_number: { + AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); + node->commaToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; +./ + +FormalParameterListOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +FormalParameterListOpt: FormalParameterList ; +/. +case $rule_number: { + sym(1).Node = sym(1).FormalParameterList->finish (); +} break; +./ + +FunctionBodyOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +FunctionBodyOpt: FunctionBody ; + +FunctionBody: SourceElements ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ()); +} break; +./ + +--QmlJSProgram: SourceElements ; +--/. +--case $rule_number: { +-- sym(1).Node = makeAstNode<AST::Program> (driver->nodePool(), sym(1).SourceElements->finish ()); +-- driver->changeAbstractSyntaxTree(sym(1).Node); +--} break; +--./ + +SourceElements: SourceElement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement); +} break; +./ + +SourceElements: SourceElements SourceElement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); +} break; +./ + +SourceElement: Statement ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement); +} break; +./ + +SourceElement: FunctionDeclaration ; +/. +case $rule_number: { + sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration); +} break; +./ + +IdentifierOpt: ; +/. +case $rule_number: { + sym(1).sval = 0; +} break; +./ + +IdentifierOpt: JsIdentifier ; + +PropertyNameAndValueListOpt: ; +/. +case $rule_number: { + sym(1).Node = 0; +} break; +./ + +PropertyNameAndValueListOpt: PropertyNameAndValueList ; + +/. + } // switch + action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); + } // if + } while (action != 0); + + if (first_token == last_token) { + const int errorState = state_stack[tos]; + + // automatic insertion of `;' + if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) { + SavedToken &tk = token_buffer[0]; + tk.token = yytoken; + tk.dval = yylval; + tk.loc = yylloc; + + yylloc = yyprevlloc; + yylloc.offset += yylloc.length; + yylloc.startColumn += yylloc.length; + yylloc.length = 0; + + //const QString msg = QString::fromUtf8("Missing `;'"); + //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); + + first_token = &token_buffer[0]; + last_token = &token_buffer[1]; + + yytoken = T_SEMICOLON; + yylval = 0; + + action = errorState; + + goto _Lcheck_token; + } + + hadErrors = true; + + token_buffer[0].token = yytoken; + token_buffer[0].dval = yylval; + token_buffer[0].loc = yylloc; + + token_buffer[1].token = yytoken = lexer->lex(); + token_buffer[1].dval = yylval = lexer->dval(); + token_buffer[1].loc = yylloc = location(lexer); + + if (t_action(errorState, yytoken)) { + const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + action = errorState; + goto _Lcheck_token; + } + + static int tokens[] = { + T_PLUS, + T_EQ, + + T_COMMA, + T_COLON, + T_SEMICOLON, + + T_RPAREN, T_RBRACKET, T_RBRACE, + + T_NUMERIC_LITERAL, + T_IDENTIFIER, + + T_LPAREN, T_LBRACKET, T_LBRACE, + + EOF_SYMBOL + }; + + for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { + int a = t_action(errorState, *tk); + if (a > 0 && t_action(a, yytoken)) { + const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + yytoken = *tk; + yylval = 0; + yylloc = token_buffer[0].loc; + yylloc.length = 0; + + first_token = &token_buffer[0]; + last_token = &token_buffer[2]; + + action = errorState; + goto _Lcheck_token; + } + } + + for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { + if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || + tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION) + continue; + + int a = t_action(errorState, tk); + if (a > 0 && t_action(a, yytoken)) { + const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + yytoken = tk; + yylval = 0; + yylloc = token_buffer[0].loc; + yylloc.length = 0; + + action = errorState; + goto _Lcheck_token; + } + } + + const QString msg = QString::fromUtf8("Syntax error"); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + } + + return false; +} + +QT_QML_END_NAMESPACE + + +./ +/: +QT_QML_END_NAMESPACE + + + +#endif // QMLJSPARSER_P_H +:/ diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsast.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljsast.cpp new file mode 100644 index 0000000000..ec199e80ae --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsast.cpp @@ -0,0 +1,943 @@ +/**************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qmljsast_p.h" +#include "qmljsastvisitor_p.h" + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { namespace AST { + +void Node::accept(Visitor *visitor) +{ + if (visitor->preVisit(this)) { + accept0(visitor); + } + visitor->postVisit(this); +} + +void Node::accept(Node *node, Visitor *visitor) +{ + if (node) + node->accept(visitor); +} + +ExpressionNode *Node::expressionCast() +{ + return 0; +} + +BinaryExpression *Node::binaryExpressionCast() +{ + return 0; +} + +Statement *Node::statementCast() +{ + return 0; +} + +UiObjectMember *Node::uiObjectMemberCast() +{ + return 0; +} + +ExpressionNode *ExpressionNode::expressionCast() +{ + return this; +} + +BinaryExpression *BinaryExpression::binaryExpressionCast() +{ + return this; +} + +Statement *Statement::statementCast() +{ + return this; +} + +UiObjectMember *UiObjectMember::uiObjectMemberCast() +{ + return this; +} + +void NestedExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + visitor->endVisit(this); +} + +void ThisExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void IdentifierExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void NullExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void TrueLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void FalseLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void StringLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void NumericLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void RegExpLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void ArrayLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(elements, visitor); + accept(elision, visitor); + } + + visitor->endVisit(this); +} + +void ObjectLiteral::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(properties, visitor); + } + + visitor->endVisit(this); +} + +void ElementList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (ElementList *it = this; it; it = it->next) { + accept(it->elision, visitor); + accept(it->expression, visitor); + } + } + + visitor->endVisit(this); +} + +void Elision::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + // ### + } + + visitor->endVisit(this); +} + +void PropertyNameAndValueList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (PropertyNameAndValueList *it = this; it; it = it->next) { + accept(it->name, visitor); + accept(it->value, visitor); + } + } + + visitor->endVisit(this); +} + +void IdentifierPropertyName::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void StringLiteralPropertyName::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void NumericLiteralPropertyName::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void ArrayMemberExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(base, visitor); + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void FieldMemberExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(base, visitor); + } + + visitor->endVisit(this); +} + +void NewMemberExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(base, visitor); + accept(arguments, visitor); + } + + visitor->endVisit(this); +} + +void NewExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void CallExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(base, visitor); + accept(arguments, visitor); + } + + visitor->endVisit(this); +} + +void ArgumentList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (ArgumentList *it = this; it; it = it->next) { + accept(it->expression, visitor); + } + } + + visitor->endVisit(this); +} + +void PostIncrementExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(base, visitor); + } + + visitor->endVisit(this); +} + +void PostDecrementExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(base, visitor); + } + + visitor->endVisit(this); +} + +void DeleteExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void VoidExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void TypeOfExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void PreIncrementExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void PreDecrementExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void UnaryPlusExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void UnaryMinusExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void TildeExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void NotExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void BinaryExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(left, visitor); + accept(right, visitor); + } + + visitor->endVisit(this); +} + +void ConditionalExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + accept(ok, visitor); + accept(ko, visitor); + } + + visitor->endVisit(this); +} + +void Expression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(left, visitor); + accept(right, visitor); + } + + visitor->endVisit(this); +} + +void Block::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(statements, visitor); + } + + visitor->endVisit(this); +} + +void StatementList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (StatementList *it = this; it; it = it->next) { + accept(it->statement, visitor); + } + } + + visitor->endVisit(this); +} + +void VariableStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(declarations, visitor); + } + + visitor->endVisit(this); +} + +void VariableDeclarationList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (VariableDeclarationList *it = this; it; it = it->next) { + accept(it->declaration, visitor); + } + } + + visitor->endVisit(this); +} + +void VariableDeclaration::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void EmptyStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void ExpressionStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void IfStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + accept(ok, visitor); + accept(ko, visitor); + } + + visitor->endVisit(this); +} + +void DoWhileStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void WhileStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void ForStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(initialiser, visitor); + accept(condition, visitor); + accept(expression, visitor); + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void LocalForStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(declarations, visitor); + accept(condition, visitor); + accept(expression, visitor); + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void ForEachStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(initialiser, visitor); + accept(expression, visitor); + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void LocalForEachStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(declaration, visitor); + accept(expression, visitor); + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void ContinueStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void BreakStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void ReturnStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void WithStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void SwitchStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + accept(block, visitor); + } + + visitor->endVisit(this); +} + +void CaseBlock::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(clauses, visitor); + accept(defaultClause, visitor); + accept(moreClauses, visitor); + } + + visitor->endVisit(this); +} + +void CaseClauses::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (CaseClauses *it = this; it; it = it->next) { + accept(it->clause, visitor); + } + } + + visitor->endVisit(this); +} + +void CaseClause::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + accept(statements, visitor); + } + + visitor->endVisit(this); +} + +void DefaultClause::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(statements, visitor); + } + + visitor->endVisit(this); +} + +void LabelledStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void ThrowStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void TryStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + accept(catchExpression, visitor); + accept(finallyExpression, visitor); + } + + visitor->endVisit(this); +} + +void Catch::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void Finally::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void FunctionDeclaration::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(formals, visitor); + accept(body, visitor); + } + + visitor->endVisit(this); +} + +void FunctionExpression::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(formals, visitor); + accept(body, visitor); + } + + visitor->endVisit(this); +} + +void FormalParameterList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + // ### + } + + visitor->endVisit(this); +} + +void FunctionBody::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(elements, visitor); + } + + visitor->endVisit(this); +} + +void Program::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(elements, visitor); + } + + visitor->endVisit(this); +} + +void SourceElements::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (SourceElements *it = this; it; it = it->next) { + accept(it->element, visitor); + } + } + + visitor->endVisit(this); +} + +void FunctionSourceElement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(declaration, visitor); + } + + visitor->endVisit(this); +} + +void StatementSourceElement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void DebuggerStatement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + + +void UiProgram::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(imports, visitor); + accept(members, visitor); + } + + visitor->endVisit(this); +} + +void UiSignature::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(formals, visitor); + } + visitor->endVisit(this); +} + +void UiFormalList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (UiFormalList *it = this; it; it = it->next) { + accept(it->formal, visitor); + } + } + visitor->endVisit(this); +} + +void UiFormal::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + visitor->endVisit(this); +} + +void UiPublicMember::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(expression, visitor); + } + + visitor->endVisit(this); +} + +void UiObjectDefinition::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(qualifiedTypeNameId, visitor); + accept(initializer, visitor); + } + + visitor->endVisit(this); +} + +void UiObjectInitializer::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(members, visitor); + } + + visitor->endVisit(this); +} + +void UiObjectBinding::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(qualifiedId, visitor); + accept(qualifiedTypeNameId, visitor); + accept(initializer, visitor); + } + + visitor->endVisit(this); +} + +void UiScriptBinding::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(qualifiedId, visitor); + accept(statement, visitor); + } + + visitor->endVisit(this); +} + +void UiArrayBinding::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(qualifiedId, visitor); + accept(members, visitor); + } + + visitor->endVisit(this); +} + +void UiObjectMemberList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (UiObjectMemberList *it = this; it; it = it->next) + accept(it->member, visitor); + } + + visitor->endVisit(this); +} + +void UiArrayMemberList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + for (UiArrayMemberList *it = this; it; it = it->next) + accept(it->member, visitor); + } + + visitor->endVisit(this); +} + +void UiQualifiedId::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + } + + visitor->endVisit(this); +} + +void UiImport::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(importUri, visitor); + } + + visitor->endVisit(this); +} + +void UiImportList::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(import, visitor); + accept(next, visitor); + } + + visitor->endVisit(this); +} + +void UiSourceElement::accept0(Visitor *visitor) +{ + if (visitor->visit(this)) { + accept(sourceElement, visitor); + } + + visitor->endVisit(this); +} + +} } // namespace QmlJS::AST + +QT_QML_END_NAMESPACE + + diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsast_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsast_p.h new file mode 100644 index 0000000000..3ad1f0de82 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsast_p.h @@ -0,0 +1,2665 @@ +/**************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLJSAST_P_H +#define QMLJSAST_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qmljsastvisitor_p.h" +#include "qmljsglobal_p.h" +#include <QtCore/QString> + +QT_QML_BEGIN_NAMESPACE + +#define QMLJS_DECLARE_AST_NODE(name) \ + enum { K = Kind_##name }; + +namespace QSOperator // ### rename +{ + +enum Op { + Add, + And, + InplaceAnd, + Assign, + BitAnd, + BitOr, + BitXor, + InplaceSub, + Div, + InplaceDiv, + Equal, + Ge, + Gt, + In, + InplaceAdd, + InstanceOf, + Le, + LShift, + InplaceLeftShift, + Lt, + Mod, + InplaceMod, + Mul, + InplaceMul, + NotEqual, + Or, + InplaceOr, + RShift, + InplaceRightShift, + StrictEqual, + StrictNotEqual, + Sub, + URShift, + InplaceURightShift, + InplaceXor +}; + +} // namespace QSOperator + +namespace QmlJS { +class NameId; +namespace AST { + +template <typename _T1, typename _T2> +_T1 cast(_T2 *ast) +{ + if (ast && ast->kind == static_cast<_T1>(0)->K) + return static_cast<_T1>(ast); + + return 0; +} + +class Node +{ +public: + enum Kind { + Kind_Undefined, + + Kind_ArgumentList, + Kind_ArrayLiteral, + Kind_ArrayMemberExpression, + Kind_BinaryExpression, + Kind_Block, + Kind_BreakStatement, + Kind_CallExpression, + Kind_CaseBlock, + Kind_CaseClause, + Kind_CaseClauses, + Kind_Catch, + Kind_ConditionalExpression, + Kind_ContinueStatement, + Kind_DebuggerStatement, + Kind_DefaultClause, + Kind_DeleteExpression, + Kind_DoWhileStatement, + Kind_ElementList, + Kind_Elision, + Kind_EmptyStatement, + Kind_Expression, + Kind_ExpressionStatement, + Kind_FalseLiteral, + Kind_FieldMemberExpression, + Kind_Finally, + Kind_ForEachStatement, + Kind_ForStatement, + Kind_FormalParameterList, + Kind_FunctionBody, + Kind_FunctionDeclaration, + Kind_FunctionExpression, + Kind_FunctionSourceElement, + Kind_IdentifierExpression, + Kind_IdentifierPropertyName, + Kind_IfStatement, + Kind_LabelledStatement, + Kind_LocalForEachStatement, + Kind_LocalForStatement, + Kind_NewExpression, + Kind_NewMemberExpression, + Kind_NotExpression, + Kind_NullExpression, + Kind_NumericLiteral, + Kind_NumericLiteralPropertyName, + Kind_ObjectLiteral, + Kind_PostDecrementExpression, + Kind_PostIncrementExpression, + Kind_PreDecrementExpression, + Kind_PreIncrementExpression, + Kind_Program, + Kind_PropertyName, + Kind_PropertyNameAndValueList, + Kind_RegExpLiteral, + Kind_ReturnStatement, + Kind_SourceElement, + Kind_SourceElements, + Kind_StatementList, + Kind_StatementSourceElement, + Kind_StringLiteral, + Kind_StringLiteralPropertyName, + Kind_SwitchStatement, + Kind_ThisExpression, + Kind_ThrowStatement, + Kind_TildeExpression, + Kind_TrueLiteral, + Kind_TryStatement, + Kind_TypeOfExpression, + Kind_UnaryMinusExpression, + Kind_UnaryPlusExpression, + Kind_VariableDeclaration, + Kind_VariableDeclarationList, + Kind_VariableStatement, + Kind_VoidExpression, + Kind_WhileStatement, + Kind_WithStatement, + Kind_NestedExpression, + + Kind_UiArrayBinding, + Kind_UiImport, + Kind_UiImportList, + Kind_UiObjectBinding, + Kind_UiObjectDefinition, + Kind_UiObjectInitializer, + Kind_UiObjectMemberList, + Kind_UiArrayMemberList, + Kind_UiProgram, + Kind_UiParameterList, + Kind_UiPublicMember, + Kind_UiQualifiedId, + Kind_UiScriptBinding, + Kind_UiSourceElement, + Kind_UiFormal, + Kind_UiFormalList, + Kind_UiSignature + }; + + inline Node() + : kind(Kind_Undefined) {} + + virtual ~Node() {} + + virtual ExpressionNode *expressionCast(); + virtual BinaryExpression *binaryExpressionCast(); + virtual Statement *statementCast(); + virtual UiObjectMember *uiObjectMemberCast(); + + void accept(Visitor *visitor); + static void accept(Node *node, Visitor *visitor); + + inline static void acceptChild(Node *node, Visitor *visitor) + { return accept(node, visitor); } // ### remove + + virtual void accept0(Visitor *visitor) = 0; + +// attributes + int kind; +}; + +class ExpressionNode: public Node +{ +public: + ExpressionNode() {} + virtual ~ExpressionNode() {} + + virtual ExpressionNode *expressionCast(); + + virtual SourceLocation firstSourceLocation() const = 0; + virtual SourceLocation lastSourceLocation() const = 0; +}; + +class Statement: public Node +{ +public: + Statement() {} + virtual ~Statement() {} + + virtual Statement *statementCast(); + + virtual SourceLocation firstSourceLocation() const = 0; + virtual SourceLocation lastSourceLocation() const = 0; +}; + +class UiFormal: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiFormal) + + UiFormal(NameId *name, NameId *alias = 0) + : name(name), alias(alias) + { } + + virtual SourceLocation firstSourceLocation() const + { return SourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return SourceLocation(); } + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *name; + NameId *alias; + SourceLocation identifierToken; + SourceLocation asToken; + SourceLocation aliasToken; +}; + +class UiFormalList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiFormalList) + + UiFormalList(UiFormal *formal) + : formal(formal), next(this) {} + + UiFormalList(UiFormalList *previous, UiFormal *formal) + : formal(formal) + { + next = previous->next; + previous->next = this; + } + + UiFormalList *finish() + { + UiFormalList *head = next; + next = 0; + return head; + } + + virtual SourceLocation firstSourceLocation() const + { return SourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return SourceLocation(); } + + virtual void accept0(Visitor *visitor); + +// attributes + UiFormal *formal; + UiFormalList *next; +}; + +class UiSignature: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiSignature) + + UiSignature(UiFormalList *formals = 0) + : formals(formals) + { } + + virtual SourceLocation firstSourceLocation() const + { return SourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return SourceLocation(); } + + virtual void accept0(Visitor *visitor); + +// attributes + SourceLocation lparenToken; + UiFormalList *formals; + SourceLocation rparenToken; +}; + +class NestedExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NestedExpression) + + NestedExpression(ExpressionNode *expression) + : expression(expression) + { kind = K; } + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return lparenToken; } + + virtual SourceLocation lastSourceLocation() const + { return rparenToken; } + +// attributes + ExpressionNode *expression; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class ThisExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(ThisExpression) + + ThisExpression() { kind = K; } + virtual ~ThisExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return thisToken; } + + virtual SourceLocation lastSourceLocation() const + { return thisToken; } + +// attributes + SourceLocation thisToken; +}; + +class IdentifierExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(IdentifierExpression) + + IdentifierExpression(NameId *n): + name (n) { kind = K; } + + virtual ~IdentifierExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return identifierToken; } + +// attributes + NameId *name; + SourceLocation identifierToken; +}; + +class NullExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NullExpression) + + NullExpression() { kind = K; } + virtual ~NullExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return nullToken; } + + virtual SourceLocation lastSourceLocation() const + { return nullToken; } + +// attributes + SourceLocation nullToken; +}; + +class TrueLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(TrueLiteral) + + TrueLiteral() { kind = K; } + virtual ~TrueLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return trueToken; } + + virtual SourceLocation lastSourceLocation() const + { return trueToken; } + +// attributes + SourceLocation trueToken; +}; + +class FalseLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(FalseLiteral) + + FalseLiteral() { kind = K; } + virtual ~FalseLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return falseToken; } + + virtual SourceLocation lastSourceLocation() const + { return falseToken; } + +// attributes + SourceLocation falseToken; +}; + +class NumericLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NumericLiteral) + + NumericLiteral(double v): + value(v) { kind = K; } + virtual ~NumericLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return literalToken; } + + virtual SourceLocation lastSourceLocation() const + { return literalToken; } + +// attributes: + double value; + SourceLocation literalToken; +}; + +class StringLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(StringLiteral) + + StringLiteral(NameId *v): + value (v) { kind = K; } + + virtual ~StringLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return literalToken; } + + virtual SourceLocation lastSourceLocation() const + { return literalToken; } + +// attributes: + NameId *value; + SourceLocation literalToken; +}; + +class RegExpLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(RegExpLiteral) + + RegExpLiteral(NameId *p, int f): + pattern (p), flags (f) { kind = K; } + + virtual ~RegExpLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return literalToken; } + + virtual SourceLocation lastSourceLocation() const + { return literalToken; } + +// attributes: + NameId *pattern; + int flags; + SourceLocation literalToken; +}; + +class ArrayLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(ArrayLiteral) + + ArrayLiteral(Elision *e): + elements (0), elision (e) + { kind = K; } + + ArrayLiteral(ElementList *elts): + elements (elts), elision (0) + { kind = K; } + + ArrayLiteral(ElementList *elts, Elision *e): + elements (elts), elision (e) + { kind = K; } + + virtual ~ArrayLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return lbracketToken; } + + virtual SourceLocation lastSourceLocation() const + { return rbracketToken; } + +// attributes + ElementList *elements; + Elision *elision; + SourceLocation lbracketToken; + SourceLocation commaToken; + SourceLocation rbracketToken; +}; + +class ObjectLiteral: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(ObjectLiteral) + + ObjectLiteral(): + properties (0) { kind = K; } + + ObjectLiteral(PropertyNameAndValueList *plist): + properties (plist) { kind = K; } + + virtual ~ObjectLiteral() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return lbraceToken; } + + virtual SourceLocation lastSourceLocation() const + { return rbraceToken; } + +// attributes + PropertyNameAndValueList *properties; + SourceLocation lbraceToken; + SourceLocation rbraceToken; +}; + +class ElementList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(ElementList) + + ElementList(Elision *e, ExpressionNode *expr): + elision (e), expression (expr), next (this) + { kind = K; } + + ElementList(ElementList *previous, Elision *e, ExpressionNode *expr): + elision (e), expression (expr) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~ElementList() {} + + inline ElementList *finish () + { + ElementList *front = next; + next = 0; + return front; + } + + virtual void accept0(Visitor *visitor); + +// attributes + Elision *elision; + ExpressionNode *expression; + ElementList *next; + SourceLocation commaToken; +}; + +class Elision: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(Elision) + + Elision(): + next (this) { kind = K; } + + Elision(Elision *previous) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~Elision() {} + + virtual void accept0(Visitor *visitor); + + inline Elision *finish () + { + Elision *front = next; + next = 0; + return front; + } + +// attributes + Elision *next; + SourceLocation commaToken; +}; + +class PropertyNameAndValueList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(PropertyNameAndValueList) + + PropertyNameAndValueList(PropertyName *n, ExpressionNode *v): + name (n), value (v), next (this) + { kind = K; } + + PropertyNameAndValueList(PropertyNameAndValueList *previous, PropertyName *n, ExpressionNode *v): + name (n), value (v) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~PropertyNameAndValueList() {} + + virtual void accept0(Visitor *visitor); + + inline PropertyNameAndValueList *finish () + { + PropertyNameAndValueList *front = next; + next = 0; + return front; + } + +// attributes + PropertyName *name; + ExpressionNode *value; + PropertyNameAndValueList *next; + SourceLocation colonToken; + SourceLocation commaToken; +}; + +class PropertyName: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(PropertyName) + + PropertyName() { kind = K; } + virtual ~PropertyName() {} + +// attributes + SourceLocation propertyNameToken; +}; + +class IdentifierPropertyName: public PropertyName +{ +public: + QMLJS_DECLARE_AST_NODE(IdentifierPropertyName) + + IdentifierPropertyName(NameId *n): + id (n) { kind = K; } + + virtual ~IdentifierPropertyName() {} + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *id; +}; + +class StringLiteralPropertyName: public PropertyName +{ +public: + QMLJS_DECLARE_AST_NODE(StringLiteralPropertyName) + + StringLiteralPropertyName(NameId *n): + id (n) { kind = K; } + virtual ~StringLiteralPropertyName() {} + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *id; +}; + +class NumericLiteralPropertyName: public PropertyName +{ +public: + QMLJS_DECLARE_AST_NODE(NumericLiteralPropertyName) + + NumericLiteralPropertyName(double n): + id (n) { kind = K; } + virtual ~NumericLiteralPropertyName() {} + + virtual void accept0(Visitor *visitor); + +// attributes + double id; +}; + +class ArrayMemberExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(ArrayMemberExpression) + + ArrayMemberExpression(ExpressionNode *b, ExpressionNode *e): + base (b), expression (e) + { kind = K; } + + virtual ~ArrayMemberExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return base->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return rbracketToken; } + +// attributes + ExpressionNode *base; + ExpressionNode *expression; + SourceLocation lbracketToken; + SourceLocation rbracketToken; +}; + +class FieldMemberExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(FieldMemberExpression) + + FieldMemberExpression(ExpressionNode *b, NameId *n): + base (b), name (n) + { kind = K; } + + virtual ~FieldMemberExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return base->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return identifierToken; } + + // attributes + ExpressionNode *base; + NameId *name; + SourceLocation dotToken; + SourceLocation identifierToken; +}; + +class NewMemberExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NewMemberExpression) + + NewMemberExpression(ExpressionNode *b, ArgumentList *a): + base (b), arguments (a) + { kind = K; } + + virtual ~NewMemberExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return newToken; } + + virtual SourceLocation lastSourceLocation() const + { return rparenToken; } + + // attributes + ExpressionNode *base; + ArgumentList *arguments; + SourceLocation newToken; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class NewExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NewExpression) + + NewExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~NewExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return newToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation newToken; +}; + +class CallExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(CallExpression) + + CallExpression(ExpressionNode *b, ArgumentList *a): + base (b), arguments (a) + { kind = K; } + + virtual ~CallExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return base->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return rparenToken; } + +// attributes + ExpressionNode *base; + ArgumentList *arguments; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class ArgumentList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(ArgumentList) + + ArgumentList(ExpressionNode *e): + expression (e), next (this) + { kind = K; } + + ArgumentList(ArgumentList *previous, ExpressionNode *e): + expression (e) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~ArgumentList() {} + + virtual void accept0(Visitor *visitor); + + inline ArgumentList *finish () + { + ArgumentList *front = next; + next = 0; + return front; + } + +// attributes + ExpressionNode *expression; + ArgumentList *next; + SourceLocation commaToken; +}; + +class PostIncrementExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(PostIncrementExpression) + + PostIncrementExpression(ExpressionNode *b): + base (b) { kind = K; } + + virtual ~PostIncrementExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return base->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return incrementToken; } + +// attributes + ExpressionNode *base; + SourceLocation incrementToken; +}; + +class PostDecrementExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(PostDecrementExpression) + + PostDecrementExpression(ExpressionNode *b): + base (b) { kind = K; } + + virtual ~PostDecrementExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return base->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return decrementToken; } + +// attributes + ExpressionNode *base; + SourceLocation decrementToken; +}; + +class DeleteExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(DeleteExpression) + + DeleteExpression(ExpressionNode *e): + expression (e) { kind = K; } + virtual ~DeleteExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return deleteToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation deleteToken; +}; + +class VoidExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(VoidExpression) + + VoidExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~VoidExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return voidToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation voidToken; +}; + +class TypeOfExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(TypeOfExpression) + + TypeOfExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~TypeOfExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return typeofToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation typeofToken; +}; + +class PreIncrementExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(PreIncrementExpression) + + PreIncrementExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~PreIncrementExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return incrementToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation incrementToken; +}; + +class PreDecrementExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(PreDecrementExpression) + + PreDecrementExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~PreDecrementExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return decrementToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation decrementToken; +}; + +class UnaryPlusExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(UnaryPlusExpression) + + UnaryPlusExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~UnaryPlusExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return plusToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation plusToken; +}; + +class UnaryMinusExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(UnaryMinusExpression) + + UnaryMinusExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~UnaryMinusExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return minusToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation minusToken; +}; + +class TildeExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(TildeExpression) + + TildeExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~TildeExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return tildeToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation tildeToken; +}; + +class NotExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(NotExpression) + + NotExpression(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~NotExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return notToken; } + + virtual SourceLocation lastSourceLocation() const + { return expression->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + SourceLocation notToken; +}; + +class BinaryExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(BinaryExpression) + + BinaryExpression(ExpressionNode *l, int o, ExpressionNode *r): + left (l), op (o), right (r) + { kind = K; } + + virtual ~BinaryExpression() {} + + virtual BinaryExpression *binaryExpressionCast(); + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return left->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return right->lastSourceLocation(); } + +// attributes + ExpressionNode *left; + int op; + ExpressionNode *right; + SourceLocation operatorToken; +}; + +class ConditionalExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(ConditionalExpression) + + ConditionalExpression(ExpressionNode *e, ExpressionNode *t, ExpressionNode *f): + expression (e), ok (t), ko (f) + { kind = K; } + + virtual ~ConditionalExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return expression->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return ko->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + ExpressionNode *ok; + ExpressionNode *ko; + SourceLocation questionToken; + SourceLocation colonToken; +}; + +class Expression: public ExpressionNode // ### rename +{ +public: + QMLJS_DECLARE_AST_NODE(Expression) + + Expression(ExpressionNode *l, ExpressionNode *r): + left (l), right (r) { kind = K; } + + virtual ~Expression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return left->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return right->lastSourceLocation(); } + +// attributes + ExpressionNode *left; + ExpressionNode *right; + SourceLocation commaToken; +}; + +class Block: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(Block) + + Block(StatementList *slist): + statements (slist) { kind = K; } + + virtual ~Block() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return lbraceToken; } + + virtual SourceLocation lastSourceLocation() const + { return rbraceToken; } + + // attributes + StatementList *statements; + SourceLocation lbraceToken; + SourceLocation rbraceToken; +}; + +class StatementList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(StatementList) + + StatementList(Statement *stmt): + statement (stmt), next (this) + { kind = K; } + + StatementList(StatementList *previous, Statement *stmt): + statement (stmt) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~StatementList() {} + + virtual void accept0(Visitor *visitor); + + inline StatementList *finish () + { + StatementList *front = next; + next = 0; + return front; + } + +// attributes + Statement *statement; + StatementList *next; +}; + +class VariableStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(VariableStatement) + + VariableStatement(VariableDeclarationList *vlist): + declarations (vlist) + { kind = K; } + + virtual ~VariableStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return declarationKindToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + VariableDeclarationList *declarations; + SourceLocation declarationKindToken; + SourceLocation semicolonToken; +}; + +class VariableDeclaration: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(VariableDeclaration) + + VariableDeclaration(NameId *n, ExpressionNode *e): + name (n), expression (e), readOnly(false) + { kind = K; } + + virtual ~VariableDeclaration() {} + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *name; + ExpressionNode *expression; + bool readOnly; + SourceLocation identifierToken; +}; + +class VariableDeclarationList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(VariableDeclarationList) + + VariableDeclarationList(VariableDeclaration *decl): + declaration (decl), next (this) + { kind = K; } + + VariableDeclarationList(VariableDeclarationList *previous, VariableDeclaration *decl): + declaration (decl) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~VariableDeclarationList() {} + + virtual void accept0(Visitor *visitor); + + inline VariableDeclarationList *finish (bool readOnly) + { + VariableDeclarationList *front = next; + next = 0; + if (readOnly) { + VariableDeclarationList *vdl; + for (vdl = front; vdl != 0; vdl = vdl->next) + vdl->declaration->readOnly = true; + } + return front; + } + +// attributes + VariableDeclaration *declaration; + VariableDeclarationList *next; + SourceLocation commaToken; +}; + +class EmptyStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(EmptyStatement) + + EmptyStatement() { kind = K; } + virtual ~EmptyStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return semicolonToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + SourceLocation semicolonToken; +}; + +class ExpressionStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ExpressionStatement) + + ExpressionStatement(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~ExpressionStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return expression->firstSourceLocation(); } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + ExpressionNode *expression; + SourceLocation semicolonToken; +}; + +class IfStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(IfStatement) + + IfStatement(ExpressionNode *e, Statement *t, Statement *f = 0): + expression (e), ok (t), ko (f) + { kind = K; } + + virtual ~IfStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return ifToken; } + + virtual SourceLocation lastSourceLocation() const + { + if (ko) + return ko->lastSourceLocation(); + + return ok->lastSourceLocation(); + } + +// attributes + ExpressionNode *expression; + Statement *ok; + Statement *ko; + SourceLocation ifToken; + SourceLocation lparenToken; + SourceLocation rparenToken; + SourceLocation elseToken; +}; + +class DoWhileStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(DoWhileStatement) + + DoWhileStatement(Statement *stmt, ExpressionNode *e): + statement (stmt), expression (e) + { kind = K; } + + virtual ~DoWhileStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return doToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + Statement *statement; + ExpressionNode *expression; + SourceLocation doToken; + SourceLocation whileToken; + SourceLocation lparenToken; + SourceLocation rparenToken; + SourceLocation semicolonToken; +}; + +class WhileStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(WhileStatement) + + WhileStatement(ExpressionNode *e, Statement *stmt): + expression (e), statement (stmt) + { kind = K; } + + virtual ~WhileStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return whileToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + Statement *statement; + SourceLocation whileToken; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class ForStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ForStatement) + + ForStatement(ExpressionNode *i, ExpressionNode *c, ExpressionNode *e, Statement *stmt): + initialiser (i), condition (c), expression (e), statement (stmt) + { kind = K; } + + virtual ~ForStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return forToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + ExpressionNode *initialiser; + ExpressionNode *condition; + ExpressionNode *expression; + Statement *statement; + SourceLocation forToken; + SourceLocation lparenToken; + SourceLocation firstSemicolonToken; + SourceLocation secondSemicolonToken; + SourceLocation rparenToken; +}; + +class LocalForStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(LocalForStatement) + + LocalForStatement(VariableDeclarationList *vlist, ExpressionNode *c, ExpressionNode *e, Statement *stmt): + declarations (vlist), condition (c), expression (e), statement (stmt) + { kind = K; } + + virtual ~LocalForStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return forToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + VariableDeclarationList *declarations; + ExpressionNode *condition; + ExpressionNode *expression; + Statement *statement; + SourceLocation forToken; + SourceLocation lparenToken; + SourceLocation varToken; + SourceLocation firstSemicolonToken; + SourceLocation secondSemicolonToken; + SourceLocation rparenToken; +}; + +class ForEachStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ForEachStatement) + + ForEachStatement(ExpressionNode *i, ExpressionNode *e, Statement *stmt): + initialiser (i), expression (e), statement (stmt) + { kind = K; } + + virtual ~ForEachStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return forToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + ExpressionNode *initialiser; + ExpressionNode *expression; + Statement *statement; + SourceLocation forToken; + SourceLocation lparenToken; + SourceLocation inToken; + SourceLocation rparenToken; +}; + +class LocalForEachStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(LocalForEachStatement) + + LocalForEachStatement(VariableDeclaration *v, ExpressionNode *e, Statement *stmt): + declaration (v), expression (e), statement (stmt) + { kind = K; } + + virtual ~LocalForEachStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return forToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + VariableDeclaration *declaration; + ExpressionNode *expression; + Statement *statement; + SourceLocation forToken; + SourceLocation lparenToken; + SourceLocation varToken; + SourceLocation inToken; + SourceLocation rparenToken; +}; + +class ContinueStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ContinueStatement) + + ContinueStatement(NameId *l = 0): + label (l) { kind = K; } + + virtual ~ContinueStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return continueToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + NameId *label; + SourceLocation continueToken; + SourceLocation identifierToken; + SourceLocation semicolonToken; +}; + +class BreakStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(BreakStatement) + + BreakStatement(NameId *l = 0): + label (l) { kind = K; } + + virtual ~BreakStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return breakToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + + // attributes + NameId *label; + SourceLocation breakToken; + SourceLocation identifierToken; + SourceLocation semicolonToken; +}; + +class ReturnStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ReturnStatement) + + ReturnStatement(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~ReturnStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return returnToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + ExpressionNode *expression; + SourceLocation returnToken; + SourceLocation semicolonToken; +}; + +class WithStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(WithStatement) + + WithStatement(ExpressionNode *e, Statement *stmt): + expression (e), statement (stmt) + { kind = K; } + + virtual ~WithStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return withToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + ExpressionNode *expression; + Statement *statement; + SourceLocation withToken; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class CaseBlock: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(CaseBlock) + + CaseBlock(CaseClauses *c, DefaultClause *d = 0, CaseClauses *r = 0): + clauses (c), defaultClause (d), moreClauses (r) + { kind = K; } + + virtual ~CaseBlock() {} + + virtual void accept0(Visitor *visitor); + +// attributes + CaseClauses *clauses; + DefaultClause *defaultClause; + CaseClauses *moreClauses; + SourceLocation lbraceToken; + SourceLocation rbraceToken; +}; + +class SwitchStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(SwitchStatement) + + SwitchStatement(ExpressionNode *e, CaseBlock *b): + expression (e), block (b) + { kind = K; } + + virtual ~SwitchStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return switchToken; } + + virtual SourceLocation lastSourceLocation() const + { return block->rbraceToken; } + +// attributes + ExpressionNode *expression; + CaseBlock *block; + SourceLocation switchToken; + SourceLocation lparenToken; + SourceLocation rparenToken; +}; + +class CaseClauses: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(CaseClauses) + + CaseClauses(CaseClause *c): + clause (c), next (this) + { kind = K; } + + CaseClauses(CaseClauses *previous, CaseClause *c): + clause (c) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~CaseClauses() {} + + virtual void accept0(Visitor *visitor); + + inline CaseClauses *finish () + { + CaseClauses *front = next; + next = 0; + return front; + } + +//attributes + CaseClause *clause; + CaseClauses *next; +}; + +class CaseClause: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(CaseClause) + + CaseClause(ExpressionNode *e, StatementList *slist): + expression (e), statements (slist) + { kind = K; } + + virtual ~CaseClause() {} + + virtual void accept0(Visitor *visitor); + +// attributes + ExpressionNode *expression; + StatementList *statements; + SourceLocation caseToken; + SourceLocation colonToken; +}; + +class DefaultClause: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(DefaultClause) + + DefaultClause(StatementList *slist): + statements (slist) + { kind = K; } + + virtual ~DefaultClause() {} + + virtual void accept0(Visitor *visitor); + +// attributes + StatementList *statements; + SourceLocation defaultToken; + SourceLocation colonToken; +}; + +class LabelledStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(LabelledStatement) + + LabelledStatement(NameId *l, Statement *stmt): + label (l), statement (stmt) + { kind = K; } + + virtual ~LabelledStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + +// attributes + NameId *label; + Statement *statement; + SourceLocation identifierToken; + SourceLocation colonToken; +}; + +class ThrowStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(ThrowStatement) + + ThrowStatement(ExpressionNode *e): + expression (e) { kind = K; } + + virtual ~ThrowStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return throwToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + + // attributes + ExpressionNode *expression; + SourceLocation throwToken; + SourceLocation semicolonToken; +}; + +class Catch: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(Catch) + + Catch(NameId *n, Block *stmt): + name (n), statement (stmt) + { kind = K; } + + virtual ~Catch() {} + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *name; + Block *statement; + SourceLocation catchToken; + SourceLocation lparenToken; + SourceLocation identifierToken; + SourceLocation rparenToken; +}; + +class Finally: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(Finally) + + Finally(Block *stmt): + statement (stmt) + { kind = K; } + + virtual ~Finally() {} + + virtual void accept0(Visitor *visitor); + +// attributes + Block *statement; + SourceLocation finallyToken; +}; + +class TryStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(TryStatement) + + TryStatement(Statement *stmt, Catch *c, Finally *f): + statement (stmt), catchExpression (c), finallyExpression (f) + { kind = K; } + + TryStatement(Statement *stmt, Finally *f): + statement (stmt), catchExpression (0), finallyExpression (f) + { kind = K; } + + TryStatement(Statement *stmt, Catch *c): + statement (stmt), catchExpression (c), finallyExpression (0) + { kind = K; } + + virtual ~TryStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return tryToken; } + + virtual SourceLocation lastSourceLocation() const + { + if (finallyExpression) + return finallyExpression->statement->rbraceToken; + else if (catchExpression) + return catchExpression->statement->rbraceToken; + + return statement->lastSourceLocation(); + } + +// attributes + Statement *statement; + Catch *catchExpression; + Finally *finallyExpression; + SourceLocation tryToken; +}; + +class FunctionExpression: public ExpressionNode +{ +public: + QMLJS_DECLARE_AST_NODE(FunctionExpression) + + FunctionExpression(NameId *n, FormalParameterList *f, FunctionBody *b): + name (n), formals (f), body (b) + { kind = K; } + + virtual ~FunctionExpression() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return functionToken; } + + virtual SourceLocation lastSourceLocation() const + { return rbraceToken; } + +// attributes + NameId *name; + FormalParameterList *formals; + FunctionBody *body; + SourceLocation functionToken; + SourceLocation identifierToken; + SourceLocation lparenToken; + SourceLocation rparenToken; + SourceLocation lbraceToken; + SourceLocation rbraceToken; +}; + +class FunctionDeclaration: public FunctionExpression +{ +public: + QMLJS_DECLARE_AST_NODE(FunctionDeclaration) + + FunctionDeclaration(NameId *n, FormalParameterList *f, FunctionBody *b): + FunctionExpression(n, f, b) + { kind = K; } + + virtual ~FunctionDeclaration() {} + + virtual void accept0(Visitor *visitor); +}; + +class FormalParameterList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(FormalParameterList) + + FormalParameterList(NameId *n): + name (n), next (this) + { kind = K; } + + FormalParameterList(FormalParameterList *previous, NameId *n): + name (n) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~FormalParameterList() {} + + virtual void accept0(Visitor *visitor); + + inline FormalParameterList *finish () + { + FormalParameterList *front = next; + next = 0; + return front; + } + +// attributes + NameId *name; + FormalParameterList *next; + SourceLocation commaToken; + SourceLocation identifierToken; +}; + +class FunctionBody: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(FunctionBody) + + FunctionBody(SourceElements *elts): + elements (elts) + { kind = K; } + + virtual ~FunctionBody() {} + + virtual void accept0(Visitor *visitor); + +// attributes + SourceElements *elements; +}; + +class Program: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(Program) + + Program(SourceElements *elts): + elements (elts) + { kind = K; } + + virtual ~Program() {} + + virtual void accept0(Visitor *visitor); + +// attributes + SourceElements *elements; +}; + +class SourceElements: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(SourceElements) + + SourceElements(SourceElement *elt): + element (elt), next (this) + { kind = K; } + + SourceElements(SourceElements *previous, SourceElement *elt): + element (elt) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~SourceElements() {} + + virtual void accept0(Visitor *visitor); + + inline SourceElements *finish () + { + SourceElements *front = next; + next = 0; + return front; + } + +// attributes + SourceElement *element; + SourceElements *next; +}; + +class SourceElement: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(SourceElement) + + inline SourceElement() + { kind = K; } + + virtual ~SourceElement() {} +}; + +class FunctionSourceElement: public SourceElement +{ +public: + QMLJS_DECLARE_AST_NODE(FunctionSourceElement) + + FunctionSourceElement(FunctionDeclaration *f): + declaration (f) + { kind = K; } + + virtual ~FunctionSourceElement() {} + + virtual void accept0(Visitor *visitor); + +// attributes + FunctionDeclaration *declaration; +}; + +class StatementSourceElement: public SourceElement +{ +public: + QMLJS_DECLARE_AST_NODE(StatementSourceElement) + + StatementSourceElement(Statement *stmt): + statement (stmt) + { kind = K; } + + virtual ~StatementSourceElement() {} + + virtual void accept0(Visitor *visitor); + +// attributes + Statement *statement; +}; + +class DebuggerStatement: public Statement +{ +public: + QMLJS_DECLARE_AST_NODE(DebuggerStatement) + + DebuggerStatement() + { kind = K; } + + virtual ~DebuggerStatement() {} + + virtual void accept0(Visitor *visitor); + + virtual SourceLocation firstSourceLocation() const + { return debuggerToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + +// attributes + SourceLocation debuggerToken; + SourceLocation semicolonToken; +}; + +class UiProgram: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiProgram) + + UiProgram(UiImportList *imports, UiObjectMemberList *members) + : imports(imports), members(members) + { kind = K; } + + virtual void accept0(Visitor *visitor); + +// attributes + UiImportList *imports; + UiObjectMemberList *members; +}; + +class UiQualifiedId: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiQualifiedId) + + UiQualifiedId(NameId *name) + : next(this), name(name) + { kind = K; } + + UiQualifiedId(UiQualifiedId *previous, NameId *name) + : name(name) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~UiQualifiedId() {} + + UiQualifiedId *finish() + { + UiQualifiedId *head = next; + next = 0; + return head; + } + + virtual void accept0(Visitor *visitor); + +// attributes + UiQualifiedId *next; + NameId *name; + SourceLocation identifierToken; +}; + +class UiImport: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiImport) + + UiImport(NameId *fileName) + : fileName(fileName), importUri(0), importId(0) + { kind = K; } + + UiImport(UiQualifiedId *uri) + : fileName(0), importUri(uri), importId(0) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { return importToken; } + + virtual SourceLocation lastSourceLocation() const + { return semicolonToken; } + + virtual void accept0(Visitor *visitor); + +// attributes + NameId *fileName; + UiQualifiedId *importUri; + NameId *importId; + SourceLocation importToken; + SourceLocation fileNameToken; + SourceLocation versionToken; + SourceLocation asToken; + SourceLocation importIdToken; + SourceLocation semicolonToken; +}; + +class UiImportList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiImportList) + + UiImportList(UiImport *import) + : import(import), + next(this) + { kind = K; } + + UiImportList(UiImportList *previous, UiImport *import) + : import(import) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual SourceLocation firstSourceLocation() const + { + if (import) return import->firstSourceLocation(); + else return SourceLocation(); + } + + virtual SourceLocation lastSourceLocation() const + { + for (const UiImportList *it = this; it; it = it->next) + if (!it->next && it->import) + return it->import->lastSourceLocation(); + + return SourceLocation(); + } + + UiImportList *finish() + { + UiImportList *head = next; + next = 0; + return head; + } + + virtual void accept0(Visitor *visitor); + +// attributes + UiImport *import; + UiImportList *next; +}; + +class UiObjectMember: public Node +{ +public: + virtual SourceLocation firstSourceLocation() const = 0; + virtual SourceLocation lastSourceLocation() const = 0; + + virtual UiObjectMember *uiObjectMemberCast(); +}; + +class UiObjectMemberList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiObjectMemberList) + + UiObjectMemberList(UiObjectMember *member) + : next(this), member(member) + { kind = K; } + + UiObjectMemberList(UiObjectMemberList *previous, UiObjectMember *member) + : member(member) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual void accept0(Visitor *visitor); + + UiObjectMemberList *finish() + { + UiObjectMemberList *head = next; + next = 0; + return head; + } + +// attributes + UiObjectMemberList *next; + UiObjectMember *member; +}; + +class UiArrayMemberList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiArrayMemberList) + + UiArrayMemberList(UiObjectMember *member) + : next(this), member(member) + { kind = K; } + + UiArrayMemberList(UiArrayMemberList *previous, UiObjectMember *member) + : member(member) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual void accept0(Visitor *visitor); + + UiArrayMemberList *finish() + { + UiArrayMemberList *head = next; + next = 0; + return head; + } + +// attributes + UiArrayMemberList *next; + UiObjectMember *member; + SourceLocation commaToken; +}; + +class UiObjectInitializer: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiObjectInitializer) + + UiObjectInitializer(UiObjectMemberList *members) + : members(members) + { kind = K; } + + virtual void accept0(Visitor *visitor); + +// attributes + SourceLocation lbraceToken; + UiObjectMemberList *members; + SourceLocation rbraceToken; +}; + +class UiParameterList: public Node +{ +public: + QMLJS_DECLARE_AST_NODE(UiParameterList) + + UiParameterList(NameId *t, NameId *n): + type (t), name (n), next (this) + { kind = K; } + + UiParameterList(UiParameterList *previous, NameId *t, NameId *n): + type (t), name (n) + { + kind = K; + next = previous->next; + previous->next = this; + } + + virtual ~UiParameterList() {} + + virtual void accept0(Visitor *) {} + + inline UiParameterList *finish () + { + UiParameterList *front = next; + next = 0; + return front; + } + +// attributes + NameId *type; + NameId *name; + UiParameterList *next; + SourceLocation commaToken; + SourceLocation identifierToken; +}; + +class UiPublicMember: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiPublicMember) + + UiPublicMember(NameId *memberType, + NameId *name) + : type(Property), typeModifier(0), memberType(memberType), name(name), expression(0), isDefaultMember(false), isReadonlyMember(false), parameters(0) + { kind = K; } + + UiPublicMember(NameId *memberType, + NameId *name, + ExpressionNode *expression) + : type(Property), typeModifier(0), memberType(memberType), name(name), expression(expression), isDefaultMember(false), isReadonlyMember(false), parameters(0) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { + if (defaultToken.isValid()) + return defaultToken; + else if (readonlyToken.isValid()) + return readonlyToken; + + return propertyToken; + } + + virtual SourceLocation lastSourceLocation() const + { + return semicolonToken; + } + + virtual void accept0(Visitor *visitor); + +// attributes + enum { Signal, Property } type; + NameId *typeModifier; + NameId *memberType; + NameId *name; + ExpressionNode *expression; + bool isDefaultMember; + bool isReadonlyMember; + UiParameterList *parameters; + SourceLocation defaultToken; + SourceLocation readonlyToken; + SourceLocation propertyToken; + SourceLocation typeModifierToken; + SourceLocation typeToken; + SourceLocation identifierToken; + SourceLocation colonToken; + SourceLocation semicolonToken; +}; + +class UiObjectDefinition: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiObjectDefinition) + + UiObjectDefinition(UiQualifiedId *qualifiedTypeNameId, + UiObjectInitializer *initializer) + : qualifiedTypeNameId(qualifiedTypeNameId), initializer(initializer) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { return qualifiedTypeNameId->identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return initializer->rbraceToken; } + + virtual void accept0(Visitor *visitor); + +// attributes + UiQualifiedId *qualifiedTypeNameId; + UiObjectInitializer *initializer; +}; + +class UiSourceElement: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiSourceElement) + + UiSourceElement(Node *sourceElement) + : sourceElement(sourceElement) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { + if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement)) + return funDecl->firstSourceLocation(); + else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement)) + return varStmt->firstSourceLocation(); + + return SourceLocation(); + } + + virtual SourceLocation lastSourceLocation() const + { + if (FunctionDeclaration *funDecl = cast<FunctionDeclaration *>(sourceElement)) + return funDecl->lastSourceLocation(); + else if (VariableStatement *varStmt = cast<VariableStatement *>(sourceElement)) + return varStmt->lastSourceLocation(); + + return SourceLocation(); + } + + + virtual void accept0(Visitor *visitor); + +// attributes + Node *sourceElement; +}; + +class UiObjectBinding: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiObjectBinding) + + UiObjectBinding(UiQualifiedId *qualifiedId, + UiQualifiedId *qualifiedTypeNameId, + UiObjectInitializer *initializer) + : qualifiedId(qualifiedId), + qualifiedTypeNameId(qualifiedTypeNameId), + initializer(initializer) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { return qualifiedId->identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return initializer->rbraceToken; } + + virtual void accept0(Visitor *visitor); + +// attributes + UiQualifiedId *qualifiedId; + UiQualifiedId *qualifiedTypeNameId; + UiObjectInitializer *initializer; + SourceLocation colonToken; +}; + +class UiScriptBinding: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiScriptBinding) + + UiScriptBinding(UiQualifiedId *qualifiedId, + Statement *statement) + : qualifiedId(qualifiedId), + statement(statement) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { return qualifiedId->identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return statement->lastSourceLocation(); } + + virtual void accept0(Visitor *visitor); + +// attributes + UiQualifiedId *qualifiedId; + Statement *statement; + SourceLocation colonToken; +}; + +class UiArrayBinding: public UiObjectMember +{ +public: + QMLJS_DECLARE_AST_NODE(UiArrayBinding) + + UiArrayBinding(UiQualifiedId *qualifiedId, + UiArrayMemberList *members) + : qualifiedId(qualifiedId), + members(members) + { kind = K; } + + virtual SourceLocation firstSourceLocation() const + { return qualifiedId->identifierToken; } + + virtual SourceLocation lastSourceLocation() const + { return rbracketToken; } + + virtual void accept0(Visitor *visitor); + +// attributes + UiQualifiedId *qualifiedId; + UiArrayMemberList *members; + SourceLocation colonToken; + SourceLocation lbracketToken; + SourceLocation rbracketToken; +}; + +} } // namespace AST + + + +QT_QML_END_NAMESPACE + +#endif diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsastfwd_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastfwd_p.h new file mode 100644 index 0000000000..dd164e9e3c --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastfwd_p.h @@ -0,0 +1,176 @@ +/**************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLJSAST_FWD_P_H +#define QMLJSAST_FWD_P_H + +#include <QtCore/qglobal.h> +#include "qmljsglobal_p.h" + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { namespace AST { + +class SourceLocation +{ +public: + SourceLocation(quint32 offset = 0, quint32 length = 0, quint32 line = 0, quint32 column = 0) + : offset(offset), length(length), + startLine(line), startColumn(column) + { } + + bool isValid() const { return length != 0; } + + quint32 begin() const { return offset; } + quint32 end() const { return offset + length; } + +// attributes + // ### encode + quint32 offset; + quint32 length; + quint32 startLine; + quint32 startColumn; +}; + +class Visitor; +class Node; +class ExpressionNode; +class Statement; +class ThisExpression; +class IdentifierExpression; +class NullExpression; +class TrueLiteral; +class FalseLiteral; +class NumericLiteral; +class StringLiteral; +class RegExpLiteral; +class ArrayLiteral; +class ObjectLiteral; +class ElementList; +class Elision; +class PropertyNameAndValueList; +class PropertyName; +class IdentifierPropertyName; +class StringLiteralPropertyName; +class NumericLiteralPropertyName; +class ArrayMemberExpression; +class FieldMemberExpression; +class NewMemberExpression; +class NewExpression; +class CallExpression; +class ArgumentList; +class PostIncrementExpression; +class PostDecrementExpression; +class DeleteExpression; +class VoidExpression; +class TypeOfExpression; +class PreIncrementExpression; +class PreDecrementExpression; +class UnaryPlusExpression; +class UnaryMinusExpression; +class TildeExpression; +class NotExpression; +class BinaryExpression; +class ConditionalExpression; +class Expression; // ### rename +class Block; +class StatementList; +class VariableStatement; +class VariableDeclarationList; +class VariableDeclaration; +class EmptyStatement; +class ExpressionStatement; +class IfStatement; +class DoWhileStatement; +class WhileStatement; +class ForStatement; +class LocalForStatement; +class ForEachStatement; +class LocalForEachStatement; +class ContinueStatement; +class BreakStatement; +class ReturnStatement; +class WithStatement; +class SwitchStatement; +class CaseBlock; +class CaseClauses; +class CaseClause; +class DefaultClause; +class LabelledStatement; +class ThrowStatement; +class TryStatement; +class Catch; +class Finally; +class FunctionDeclaration; +class FunctionExpression; +class FormalParameterList; +class FunctionBody; +class Program; +class SourceElements; +class SourceElement; +class FunctionSourceElement; +class StatementSourceElement; +class DebuggerStatement; +class NestedExpression; + +// ui elements +class UiProgram; +class UiImportList; +class UiImport; +class UiPublicMember; +class UiObjectDefinition; +class UiObjectInitializer; +class UiObjectBinding; +class UiScriptBinding; +class UiSourceElement; +class UiArrayBinding; +class UiObjectMember; +class UiObjectMemberList; +class UiArrayMemberList; +class UiQualifiedId; +class UiFormalList; +class UiFormal; +class UiSignature; + +} } // namespace AST + +QT_QML_END_NAMESPACE + +#endif diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor.cpp new file mode 100644 index 0000000000..6a0d55a4f1 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor.cpp @@ -0,0 +1,46 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qmljsastvisitor_p.h" + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { namespace AST { + +Visitor::Visitor() +{ +} + +Visitor::~Visitor() +{ +} + +} } // namespace QmlJS::AST + +QT_QML_END_NAMESPACE diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor_p.h new file mode 100644 index 0000000000..09714ee0a0 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsastvisitor_p.h @@ -0,0 +1,323 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLJSASTVISITOR_P_H +#define QMLJSASTVISITOR_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include "qmljsastfwd_p.h" +#include "qmljsglobal_p.h" + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { namespace AST { + +class Visitor +{ +public: + Visitor(); + virtual ~Visitor(); + + virtual bool preVisit(Node *) { return true; } + virtual void postVisit(Node *) {} + + // Ui + virtual bool visit(UiProgram *) { return true; } + virtual bool visit(UiImportList *) { return true; } + virtual bool visit(UiImport *) { return true; } + virtual bool visit(UiPublicMember *) { return true; } + virtual bool visit(UiSourceElement *) { return true; } + virtual bool visit(UiObjectDefinition *) { return true; } + virtual bool visit(UiObjectInitializer *) { return true; } + virtual bool visit(UiObjectBinding *) { return true; } + virtual bool visit(UiScriptBinding *) { return true; } + virtual bool visit(UiArrayBinding *) { return true; } + virtual bool visit(UiObjectMemberList *) { return true; } + virtual bool visit(UiArrayMemberList *) { return true; } + virtual bool visit(UiQualifiedId *) { return true; } + virtual bool visit(UiSignature *) { return true; } + virtual bool visit(UiFormalList *) { return true; } + virtual bool visit(UiFormal *) { return true; } + + virtual void endVisit(UiProgram *) {} + virtual void endVisit(UiImportList *) {} + virtual void endVisit(UiImport *) {} + virtual void endVisit(UiPublicMember *) {} + virtual void endVisit(UiSourceElement *) {} + virtual void endVisit(UiObjectDefinition *) {} + virtual void endVisit(UiObjectInitializer *) {} + virtual void endVisit(UiObjectBinding *) {} + virtual void endVisit(UiScriptBinding *) {} + virtual void endVisit(UiArrayBinding *) {} + virtual void endVisit(UiObjectMemberList *) {} + virtual void endVisit(UiArrayMemberList *) {} + virtual void endVisit(UiQualifiedId *) {} + virtual void endVisit(UiSignature *) {} + virtual void endVisit(UiFormalList *) {} + virtual void endVisit(UiFormal *) {} + + // QmlJS + virtual bool visit(ThisExpression *) { return true; } + virtual void endVisit(ThisExpression *) {} + + virtual bool visit(IdentifierExpression *) { return true; } + virtual void endVisit(IdentifierExpression *) {} + + virtual bool visit(NullExpression *) { return true; } + virtual void endVisit(NullExpression *) {} + + virtual bool visit(TrueLiteral *) { return true; } + virtual void endVisit(TrueLiteral *) {} + + virtual bool visit(FalseLiteral *) { return true; } + virtual void endVisit(FalseLiteral *) {} + + virtual bool visit(StringLiteral *) { return true; } + virtual void endVisit(StringLiteral *) {} + + virtual bool visit(NumericLiteral *) { return true; } + virtual void endVisit(NumericLiteral *) {} + + virtual bool visit(RegExpLiteral *) { return true; } + virtual void endVisit(RegExpLiteral *) {} + + virtual bool visit(ArrayLiteral *) { return true; } + virtual void endVisit(ArrayLiteral *) {} + + virtual bool visit(ObjectLiteral *) { return true; } + virtual void endVisit(ObjectLiteral *) {} + + virtual bool visit(ElementList *) { return true; } + virtual void endVisit(ElementList *) {} + + virtual bool visit(Elision *) { return true; } + virtual void endVisit(Elision *) {} + + virtual bool visit(PropertyNameAndValueList *) { return true; } + virtual void endVisit(PropertyNameAndValueList *) {} + + virtual bool visit(NestedExpression *) { return true; } + virtual void endVisit(NestedExpression *) {} + + virtual bool visit(IdentifierPropertyName *) { return true; } + virtual void endVisit(IdentifierPropertyName *) {} + + virtual bool visit(StringLiteralPropertyName *) { return true; } + virtual void endVisit(StringLiteralPropertyName *) {} + + virtual bool visit(NumericLiteralPropertyName *) { return true; } + virtual void endVisit(NumericLiteralPropertyName *) {} + + virtual bool visit(ArrayMemberExpression *) { return true; } + virtual void endVisit(ArrayMemberExpression *) {} + + virtual bool visit(FieldMemberExpression *) { return true; } + virtual void endVisit(FieldMemberExpression *) {} + + virtual bool visit(NewMemberExpression *) { return true; } + virtual void endVisit(NewMemberExpression *) {} + + virtual bool visit(NewExpression *) { return true; } + virtual void endVisit(NewExpression *) {} + + virtual bool visit(CallExpression *) { return true; } + virtual void endVisit(CallExpression *) {} + + virtual bool visit(ArgumentList *) { return true; } + virtual void endVisit(ArgumentList *) {} + + virtual bool visit(PostIncrementExpression *) { return true; } + virtual void endVisit(PostIncrementExpression *) {} + + virtual bool visit(PostDecrementExpression *) { return true; } + virtual void endVisit(PostDecrementExpression *) {} + + virtual bool visit(DeleteExpression *) { return true; } + virtual void endVisit(DeleteExpression *) {} + + virtual bool visit(VoidExpression *) { return true; } + virtual void endVisit(VoidExpression *) {} + + virtual bool visit(TypeOfExpression *) { return true; } + virtual void endVisit(TypeOfExpression *) {} + + virtual bool visit(PreIncrementExpression *) { return true; } + virtual void endVisit(PreIncrementExpression *) {} + + virtual bool visit(PreDecrementExpression *) { return true; } + virtual void endVisit(PreDecrementExpression *) {} + + virtual bool visit(UnaryPlusExpression *) { return true; } + virtual void endVisit(UnaryPlusExpression *) {} + + virtual bool visit(UnaryMinusExpression *) { return true; } + virtual void endVisit(UnaryMinusExpression *) {} + + virtual bool visit(TildeExpression *) { return true; } + virtual void endVisit(TildeExpression *) {} + + virtual bool visit(NotExpression *) { return true; } + virtual void endVisit(NotExpression *) {} + + virtual bool visit(BinaryExpression *) { return true; } + virtual void endVisit(BinaryExpression *) {} + + virtual bool visit(ConditionalExpression *) { return true; } + virtual void endVisit(ConditionalExpression *) {} + + virtual bool visit(Expression *) { return true; } + virtual void endVisit(Expression *) {} + + virtual bool visit(Block *) { return true; } + virtual void endVisit(Block *) {} + + virtual bool visit(StatementList *) { return true; } + virtual void endVisit(StatementList *) {} + + virtual bool visit(VariableStatement *) { return true; } + virtual void endVisit(VariableStatement *) {} + + virtual bool visit(VariableDeclarationList *) { return true; } + virtual void endVisit(VariableDeclarationList *) {} + + virtual bool visit(VariableDeclaration *) { return true; } + virtual void endVisit(VariableDeclaration *) {} + + virtual bool visit(EmptyStatement *) { return true; } + virtual void endVisit(EmptyStatement *) {} + + virtual bool visit(ExpressionStatement *) { return true; } + virtual void endVisit(ExpressionStatement *) {} + + virtual bool visit(IfStatement *) { return true; } + virtual void endVisit(IfStatement *) {} + + virtual bool visit(DoWhileStatement *) { return true; } + virtual void endVisit(DoWhileStatement *) {} + + virtual bool visit(WhileStatement *) { return true; } + virtual void endVisit(WhileStatement *) {} + + virtual bool visit(ForStatement *) { return true; } + virtual void endVisit(ForStatement *) {} + + virtual bool visit(LocalForStatement *) { return true; } + virtual void endVisit(LocalForStatement *) {} + + virtual bool visit(ForEachStatement *) { return true; } + virtual void endVisit(ForEachStatement *) {} + + virtual bool visit(LocalForEachStatement *) { return true; } + virtual void endVisit(LocalForEachStatement *) {} + + virtual bool visit(ContinueStatement *) { return true; } + virtual void endVisit(ContinueStatement *) {} + + virtual bool visit(BreakStatement *) { return true; } + virtual void endVisit(BreakStatement *) {} + + virtual bool visit(ReturnStatement *) { return true; } + virtual void endVisit(ReturnStatement *) {} + + virtual bool visit(WithStatement *) { return true; } + virtual void endVisit(WithStatement *) {} + + virtual bool visit(SwitchStatement *) { return true; } + virtual void endVisit(SwitchStatement *) {} + + virtual bool visit(CaseBlock *) { return true; } + virtual void endVisit(CaseBlock *) {} + + virtual bool visit(CaseClauses *) { return true; } + virtual void endVisit(CaseClauses *) {} + + virtual bool visit(CaseClause *) { return true; } + virtual void endVisit(CaseClause *) {} + + virtual bool visit(DefaultClause *) { return true; } + virtual void endVisit(DefaultClause *) {} + + virtual bool visit(LabelledStatement *) { return true; } + virtual void endVisit(LabelledStatement *) {} + + virtual bool visit(ThrowStatement *) { return true; } + virtual void endVisit(ThrowStatement *) {} + + virtual bool visit(TryStatement *) { return true; } + virtual void endVisit(TryStatement *) {} + + virtual bool visit(Catch *) { return true; } + virtual void endVisit(Catch *) {} + + virtual bool visit(Finally *) { return true; } + virtual void endVisit(Finally *) {} + + virtual bool visit(FunctionDeclaration *) { return true; } + virtual void endVisit(FunctionDeclaration *) {} + + virtual bool visit(FunctionExpression *) { return true; } + virtual void endVisit(FunctionExpression *) {} + + virtual bool visit(FormalParameterList *) { return true; } + virtual void endVisit(FormalParameterList *) {} + + virtual bool visit(FunctionBody *) { return true; } + virtual void endVisit(FunctionBody *) {} + + virtual bool visit(Program *) { return true; } + virtual void endVisit(Program *) {} + + virtual bool visit(SourceElements *) { return true; } + virtual void endVisit(SourceElements *) {} + + virtual bool visit(FunctionSourceElement *) { return true; } + virtual void endVisit(FunctionSourceElement *) {} + + virtual bool visit(StatementSourceElement *) { return true; } + virtual void endVisit(StatementSourceElement *) {} + + virtual bool visit(DebuggerStatement *) { return true; } + virtual void endVisit(DebuggerStatement *) {} +}; + +} } // namespace AST + +QT_QML_END_NAMESPACE + +#endif // QMLJSASTVISITOR_P_H diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.cpp new file mode 100644 index 0000000000..6e7a45a506 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.cpp @@ -0,0 +1,198 @@ +/**************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qmljsglobal_p.h" +#include "qmljsengine_p.h" +#include "qmljsnodepool_p.h" +#include <qnumeric.h> +#include <QHash> + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { + +uint qHash(const QmlJS::NameId &id) +{ return qHash(id.asString()); } + +QString numberToString(double value) +{ return QString::number(value); } + +int Ecma::RegExp::flagFromChar(const QChar &ch) +{ + static QHash<QChar, int> flagsHash; + if (flagsHash.isEmpty()) { + flagsHash[QLatin1Char('g')] = Global; + flagsHash[QLatin1Char('i')] = IgnoreCase; + flagsHash[QLatin1Char('m')] = Multiline; + } + QHash<QChar, int>::const_iterator it; + it = flagsHash.constFind(ch); + if (it == flagsHash.constEnd()) + return 0; + return it.value(); +} + +QString Ecma::RegExp::flagsToString(int flags) +{ + QString result; + if (flags & Global) + result += QLatin1Char('g'); + if (flags & IgnoreCase) + result += QLatin1Char('i'); + if (flags & Multiline) + result += QLatin1Char('m'); + return result; +} + +NodePool::NodePool(const QString &fileName, Engine *engine) + : m_fileName(fileName), m_engine(engine) +{ + m_engine->setNodePool(this); +} + +NodePool::~NodePool() +{ +} + +Code *NodePool::createCompiledCode(AST::Node *, CompilationUnit &) +{ + Q_ASSERT(0); + return 0; +} + +static int toDigit(char c) +{ + if ((c >= '0') && (c <= '9')) + return c - '0'; + else if ((c >= 'a') && (c <= 'z')) + return 10 + c - 'a'; + else if ((c >= 'A') && (c <= 'Z')) + return 10 + c - 'A'; + return -1; +} + +double integerFromString(const char *buf, int size, int radix) +{ + if (size == 0) + return qSNaN(); + + double sign = 1.0; + int i = 0; + if (buf[0] == '+') { + ++i; + } else if (buf[0] == '-') { + sign = -1.0; + ++i; + } + + if (((size-i) >= 2) && (buf[i] == '0')) { + if (((buf[i+1] == 'x') || (buf[i+1] == 'X')) + && (radix < 34)) { + if ((radix != 0) && (radix != 16)) + return 0; + radix = 16; + i += 2; + } else { + if (radix == 0) { + radix = 8; + ++i; + } + } + } else if (radix == 0) { + radix = 10; + } + + int j = i; + for ( ; i < size; ++i) { + int d = toDigit(buf[i]); + if ((d == -1) || (d >= radix)) + break; + } + double result; + if (j == i) { + if (!qstrcmp(buf, "Infinity")) + result = qInf(); + else + result = qSNaN(); + } else { + result = 0; + double multiplier = 1; + for (--i ; i >= j; --i, multiplier *= radix) + result += toDigit(buf[i]) * multiplier; + } + result *= sign; + return result; +} + +double integerFromString(const QString &str, int radix) +{ + QByteArray ba = str.trimmed().toUtf8(); + return integerFromString(ba.constData(), ba.size(), radix); +} + + +Engine::Engine() + : _lexer(0), _nodePool(0) +{ } + +Engine::~Engine() +{ } + +QSet<NameId> Engine::literals() const +{ return _literals; } + +void Engine::addComment(int pos, int len, int line, int col) +{ if (len > 0) _comments.append(QmlJS::AST::SourceLocation(pos, len, line, col)); } + +QList<QmlJS::AST::SourceLocation> Engine::comments() const +{ return _comments; } + +NameId *Engine::intern(const QChar *u, int s) +{ return const_cast<NameId *>(&*_literals.insert(NameId(u, s))); } + +QString Engine::toString(NameId *id) +{ return id->asString(); } + +Lexer *Engine::lexer() const +{ return _lexer; } + +void Engine::setLexer(Lexer *lexer) +{ _lexer = lexer; } + +NodePool *Engine::nodePool() const +{ return _nodePool; } + +void Engine::setNodePool(NodePool *nodePool) +{ _nodePool = nodePool; } + + + +} // end of namespace QmlJS + +QT_QML_END_NAMESPACE diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.h new file mode 100644 index 0000000000..98e71c8879 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsengine_p.h @@ -0,0 +1,161 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLJSENGINE_P_H +#define QMLJSENGINE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QString> +#include <QSet> + +#include "qmljsglobal_p.h" +#include "qmljsastfwd_p.h" + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { +class NameId +{ + QString _text; + +public: + NameId(const QChar *u, int s) + : _text(u, s) + { } + + const QString asString() const + { return _text; } + + bool operator == (const NameId &other) const + { return _text == other._text; } + + bool operator != (const NameId &other) const + { return _text != other._text; } + + bool operator < (const NameId &other) const + { return _text < other._text; } +}; + +uint qHash(const QmlJS::NameId &id); + +} // end of namespace QmlJS + +#if defined(Q_CC_MSVC) && _MSC_VER <= 1300 +//this ensures that code outside QmlJS can use the hash function +//it also a workaround for some compilers +inline uint qHash(const QmlJS::NameId &nameId) { return QmlJS::qHash(nameId); } +#endif + +namespace QmlJS { + +class Lexer; +class NodePool; + +namespace Ecma { + +class RegExp +{ +public: + enum RegExpFlag { + Global = 0x01, + IgnoreCase = 0x02, + Multiline = 0x04 + }; + +public: + static int flagFromChar(const QChar &); + static QString flagsToString(int flags); +}; + +} // end of namespace Ecma + +class DiagnosticMessage +{ +public: + enum Kind { Warning, Error }; + + DiagnosticMessage() + : kind(Error) {} + + DiagnosticMessage(Kind kind, const AST::SourceLocation &loc, const QString &message) + : kind(kind), loc(loc), message(message) {} + + bool isWarning() const + { return kind == Warning; } + + bool isError() const + { return kind == Error; } + + Kind kind; + AST::SourceLocation loc; + QString message; +}; + +class Engine +{ + Lexer *_lexer; + NodePool *_nodePool; + QSet<NameId> _literals; + QList<QmlJS::AST::SourceLocation> _comments; + +public: + Engine(); + ~Engine(); + + QSet<NameId> literals() const; + + void addComment(int pos, int len, int line, int col); + QList<QmlJS::AST::SourceLocation> comments() const; + + NameId *intern(const QChar *u, int s); + + static QString toString(NameId *id); + + Lexer *lexer() const; + void setLexer(Lexer *lexer); + + NodePool *nodePool() const; + void setNodePool(NodePool *nodePool); +}; + +} // end of namespace QmlJS + +QT_QML_END_NAMESPACE + +#endif // QMLJSENGINE_P_H diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsglobal_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsglobal_p.h new file mode 100644 index 0000000000..96f1ced266 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsglobal_p.h @@ -0,0 +1,43 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLJSGLOBAL_P_H +#define QMLJSGLOBAL_P_H + +#include <QtCore/qglobal.h> + +#ifdef QT_CREATOR +#define QT_QML_BEGIN_NAMESPACE +#define QT_QML_END_NAMESPACE +#else // !QT_CREATOR +#define QT_QML_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE +#define QT_QML_END_NAMESPACE QT_END_NAMESPACE +#endif // QT_CREATOR + +#endif // QMLJSGLOBAL_P_H diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar.cpp new file mode 100644 index 0000000000..c71b759a35 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar.cpp @@ -0,0 +1,960 @@ +// This file was generated by qlalr - DO NOT EDIT! +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "qmljsgrammar_p.h" + +const char *const QmlJSGrammar::spell [] = { + "end of file", "&", "&&", "&=", "break", "case", "catch", ":", ";", "continue", + "default", "delete", "/", "/=", "do", ".", "else", "=", "==", "===", + "finally", "for", "function", ">=", ">", ">>", ">>=", ">>>", ">>>=", "identifier", + "if", "in", "instanceof", "{", "[", "<=", "(", "<", "<<", "<<=", + "-", "-=", "--", "new", "!", "!=", "!==", "numeric literal", "|", "|=", + "||", "+", "+=", "++", "?", "}", "]", "%", "%=", "return", + ")", ";", 0, "*", "*=", "string literal", "property", "signal", "readonly", "switch", + "this", "throw", "~", "try", "typeof", "var", "void", "while", "with", "^", + "^=", "null", "true", "false", "const", "debugger", "reserved word", "multiline string literal", "comment", "public", + "import", "as", 0, 0, 0, 0, 0, 0}; + +const int QmlJSGrammar::lhs [] = { + 98, 98, 98, 98, 99, 103, 103, 106, 106, 108, + 107, 107, 107, 107, 107, 107, 107, 107, 110, 105, + 104, 113, 113, 114, 114, 115, 115, 112, 102, 102, + 102, 102, 102, 102, 102, 121, 121, 121, 122, 122, + 123, 123, 102, 102, 102, 102, 102, 102, 102, 102, + 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, + 111, 111, 111, 111, 126, 126, 126, 126, 126, 126, + 126, 126, 126, 126, 126, 126, 126, 126, 126, 126, + 126, 126, 116, 128, 128, 128, 128, 127, 127, 130, + 130, 132, 132, 132, 132, 132, 132, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 133, 133, + 133, 133, 133, 133, 133, 133, 133, 133, 134, 134, + 109, 109, 109, 109, 109, 137, 137, 138, 138, 138, + 138, 136, 136, 139, 139, 140, 140, 141, 141, 141, + 142, 142, 142, 142, 142, 142, 142, 142, 142, 142, + 143, 143, 143, 143, 144, 144, 144, 145, 145, 145, + 145, 146, 146, 146, 146, 146, 146, 146, 147, 147, + 147, 147, 147, 147, 148, 148, 148, 148, 148, 149, + 149, 149, 149, 149, 150, 150, 151, 151, 152, 152, + 153, 153, 154, 154, 155, 155, 156, 156, 157, 157, + 158, 158, 159, 159, 160, 160, 161, 161, 131, 131, + 162, 162, 163, 163, 163, 163, 163, 163, 163, 163, + 163, 163, 163, 163, 101, 101, 164, 164, 165, 165, + 166, 166, 100, 100, 100, 100, 100, 100, 100, 100, + 100, 100, 100, 100, 100, 100, 100, 117, 178, 178, + 177, 177, 125, 125, 179, 179, 180, 180, 182, 182, + 181, 183, 186, 184, 184, 187, 185, 185, 118, 119, + 119, 120, 120, 167, 167, 167, 167, 167, 167, 167, + 168, 168, 168, 168, 169, 169, 169, 169, 170, 170, + 171, 173, 188, 188, 191, 191, 189, 189, 192, 190, + 172, 172, 172, 174, 174, 175, 175, 175, 193, 194, + 176, 176, 124, 135, 198, 198, 195, 195, 196, 196, + 199, 200, 200, 201, 201, 197, 197, 129, 129, 202}; + +const int QmlJSGrammar:: rhs[] = { + 2, 2, 2, 2, 2, 1, 1, 1, 2, 1, + 2, 2, 3, 3, 5, 5, 4, 4, 2, 0, + 1, 1, 2, 1, 3, 2, 3, 2, 1, 5, + 4, 3, 3, 3, 3, 1, 1, 1, 0, 1, + 2, 4, 6, 6, 3, 3, 7, 7, 4, 4, + 5, 5, 6, 6, 7, 7, 7, 7, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 2, 3, 3, 4, 5, 3, + 4, 3, 1, 1, 2, 3, 4, 1, 2, 3, + 5, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 4, 3, 5, 1, 2, 4, 4, 4, + 3, 0, 1, 1, 3, 1, 1, 1, 2, 2, + 1, 2, 2, 2, 2, 2, 2, 2, 2, 2, + 1, 3, 3, 3, 1, 3, 3, 1, 3, 3, + 3, 1, 3, 3, 3, 3, 3, 3, 1, 3, + 3, 3, 3, 3, 1, 3, 3, 3, 3, 1, + 3, 3, 3, 3, 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 3, 1, 3, 1, 3, + 1, 3, 1, 3, 1, 5, 1, 5, 1, 3, + 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 3, 0, 1, 1, 3, + 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 3, 1, 2, + 0, 1, 3, 3, 1, 1, 1, 3, 1, 3, + 2, 2, 2, 0, 1, 2, 0, 1, 1, 2, + 2, 7, 5, 7, 7, 5, 9, 10, 7, 8, + 2, 2, 3, 3, 2, 2, 3, 3, 3, 3, + 5, 5, 3, 5, 1, 2, 0, 1, 4, 3, + 3, 3, 3, 3, 3, 3, 3, 4, 5, 2, + 2, 2, 8, 8, 1, 3, 0, 1, 0, 1, + 1, 1, 2, 1, 1, 0, 1, 0, 1, 2}; + +const int QmlJSGrammar::action_default [] = { + 0, 0, 0, 0, 20, 0, 168, 235, 199, 207, + 203, 147, 219, 195, 3, 132, 66, 148, 211, 215, + 136, 165, 146, 151, 131, 185, 172, 0, 73, 74, + 69, 336, 61, 338, 0, 0, 0, 0, 71, 0, + 0, 67, 70, 0, 0, 62, 64, 63, 72, 65, + 0, 68, 0, 0, 161, 0, 0, 148, 167, 150, + 149, 0, 0, 0, 163, 164, 162, 166, 0, 196, + 0, 0, 0, 0, 186, 0, 0, 0, 0, 0, + 0, 176, 0, 0, 0, 170, 171, 169, 174, 178, + 177, 175, 173, 188, 187, 189, 0, 204, 0, 200, + 0, 0, 142, 129, 141, 130, 98, 99, 100, 125, + 101, 126, 102, 103, 104, 105, 106, 107, 108, 109, + 110, 111, 112, 113, 114, 127, 115, 116, 117, 118, + 119, 120, 121, 122, 123, 124, 128, 0, 0, 140, + 236, 143, 0, 144, 0, 145, 139, 0, 232, 225, + 223, 230, 231, 229, 228, 234, 227, 226, 224, 233, + 220, 0, 208, 0, 0, 212, 0, 0, 216, 0, + 0, 142, 134, 0, 133, 0, 138, 152, 0, 337, + 327, 328, 0, 325, 0, 326, 0, 329, 243, 250, + 249, 257, 245, 0, 246, 330, 0, 335, 247, 248, + 253, 251, 332, 331, 334, 254, 0, 265, 0, 0, + 0, 0, 336, 61, 0, 338, 62, 237, 279, 63, + 0, 0, 0, 266, 0, 0, 255, 256, 0, 244, + 252, 280, 281, 324, 333, 0, 295, 296, 297, 298, + 0, 291, 292, 293, 294, 321, 322, 0, 0, 0, + 0, 0, 284, 285, 241, 239, 201, 209, 205, 221, + 197, 242, 0, 148, 213, 217, 190, 179, 0, 0, + 198, 0, 0, 0, 0, 191, 0, 0, 0, 0, + 0, 183, 181, 184, 182, 180, 193, 192, 194, 0, + 206, 0, 202, 0, 240, 148, 0, 222, 237, 238, + 0, 237, 0, 0, 287, 0, 0, 0, 289, 0, + 210, 0, 0, 214, 0, 0, 218, 277, 0, 269, + 278, 272, 0, 276, 0, 237, 270, 0, 237, 0, + 0, 288, 0, 0, 0, 290, 337, 327, 0, 0, + 329, 0, 323, 0, 313, 0, 0, 0, 283, 0, + 282, 0, 339, 0, 97, 259, 262, 0, 98, 265, + 101, 126, 103, 104, 69, 108, 109, 61, 110, 113, + 67, 70, 62, 237, 63, 72, 116, 65, 118, 68, + 120, 121, 266, 123, 124, 128, 0, 90, 0, 0, + 92, 96, 94, 81, 93, 95, 0, 91, 80, 260, + 258, 136, 137, 142, 0, 135, 0, 312, 0, 299, + 300, 0, 311, 0, 0, 0, 302, 307, 305, 308, + 0, 0, 306, 307, 0, 303, 0, 304, 261, 310, + 0, 261, 309, 0, 314, 315, 0, 261, 316, 317, + 0, 0, 318, 0, 0, 0, 319, 320, 154, 153, + 0, 0, 0, 286, 0, 0, 0, 301, 274, 267, + 0, 275, 271, 0, 273, 263, 0, 264, 268, 84, + 0, 0, 88, 75, 0, 77, 86, 0, 78, 87, + 89, 79, 85, 76, 0, 82, 158, 156, 160, 157, + 155, 159, 2, 59, 83, 0, 0, 62, 64, 63, + 29, 4, 0, 60, 0, 38, 37, 36, 0, 0, + 51, 0, 52, 0, 57, 58, 0, 38, 0, 0, + 0, 0, 0, 47, 48, 0, 49, 0, 50, 0, + 53, 54, 0, 0, 0, 0, 0, 55, 56, 0, + 45, 39, 46, 40, 0, 0, 0, 0, 42, 0, + 43, 44, 41, 0, 0, 28, 32, 33, 34, 35, + 136, 261, 0, 0, 98, 265, 101, 126, 103, 104, + 69, 108, 109, 61, 110, 113, 67, 70, 62, 237, + 63, 72, 116, 65, 118, 68, 120, 121, 266, 123, + 124, 128, 136, 0, 24, 0, 0, 30, 25, 31, + 26, 22, 0, 27, 23, 6, 0, 8, 0, 7, + 0, 1, 19, 10, 0, 11, 0, 12, 0, 17, + 18, 0, 13, 14, 0, 15, 16, 9, 21, 5, + 340}; + +const int QmlJSGrammar::goto_default [] = { + 5, 611, 355, 193, 501, 610, 629, 605, 609, 607, + 612, 20, 608, 16, 500, 602, 593, 555, 502, 188, + 192, 194, 198, 518, 544, 543, 197, 229, 24, 471, + 470, 353, 352, 7, 351, 354, 104, 15, 142, 22, + 11, 141, 17, 23, 54, 21, 6, 26, 25, 266, + 13, 260, 8, 256, 10, 258, 9, 257, 18, 264, + 19, 265, 12, 259, 255, 296, 408, 261, 262, 199, + 190, 189, 201, 230, 200, 205, 226, 227, 191, 357, + 356, 228, 460, 459, 318, 319, 462, 321, 461, 320, + 416, 420, 423, 419, 418, 438, 439, 182, 196, 178, + 181, 195, 203, 202, 0}; + +const int QmlJSGrammar::action_index [] = { + 251, 1237, 2238, 974, -45, 51, 122, -98, 52, -11, + -39, 182, -98, 389, 36, -98, -98, 628, 58, 75, + 246, 228, -98, -98, -98, 438, 309, 1237, -98, -98, + -98, 348, -98, 2050, 1772, 1237, 1237, 1237, -98, 800, + 1237, -98, -98, 1237, 1237, -98, -98, -98, -98, -98, + 1237, -98, 1237, 1237, -98, 1237, 1237, 97, 226, -98, + -98, 1237, 1237, 1237, -98, -98, -98, 200, 1237, 389, + 1237, 1237, 1237, 1237, 418, 1237, 1237, 1237, 1237, 1237, + 1237, 212, 1237, 1237, 1237, 144, 121, 71, 309, 309, + 164, 156, 179, 448, 428, 408, 1237, -51, 1237, 101, + 1956, 1237, 1237, -98, -98, -98, -98, -98, -98, -98, + -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, + -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, + -98, -98, -98, -98, -98, -98, -98, 236, 1237, -98, + -98, 31, 16, -98, 1237, -98, -98, 1237, -98, -98, + -98, -98, -98, -98, -98, -98, -98, -98, -98, -98, + -98, 1237, 2, 1237, 1237, 41, 35, 1237, -98, 1956, + 1237, 1237, -98, 102, -98, 6, -98, -98, 20, -98, + 299, 53, 14, -98, 321, -98, -22, 2332, -98, -98, + -98, -98, -98, 216, -98, -98, -28, -98, -98, -98, + -98, -98, -98, 2332, -98, -98, 469, -98, 533, 115, + 2238, -2, 335, -3, -36, 2520, 50, 1237, -98, 64, + 33, 1237, 21, -98, 5, -14, -98, -98, 306, -98, + -98, -98, -98, -98, -98, 74, -98, -98, -98, -98, + 117, -98, -98, -98, -98, -98, -98, -57, -18, 1237, + 140, 109, -98, -98, 1324, -98, 104, 67, 27, -98, + 330, 84, 29, 585, 80, 92, 464, 171, 295, 1237, + 314, 1237, 1237, 1237, 1237, 346, 1237, 1237, 1237, 1237, + 1237, 309, 309, 309, 309, 309, 386, 464, 464, 1237, + 27, 1237, 87, 1237, -98, 529, 1237, -98, 1237, 83, + 38, 1237, 48, 2238, -98, 1237, 143, 2238, -98, 1237, + 30, 1237, 1237, 81, 77, 1237, -98, 56, 126, 90, + -98, -98, 1237, -98, 290, 1237, -98, 42, 1237, 44, + 2238, -98, 1237, 133, 2238, -98, 22, 285, -37, -9, + 2332, -30, -98, 2238, -98, 1237, 141, 2238, 10, 2238, + -98, 26, 24, -24, -98, -98, 2238, 25, 453, 23, + 533, 106, 1237, 2238, 9, -29, 361, -4, -31, 800, + -6, 55, -98, 1415, -98, -1, -23, 8, 1237, 7, + -21, 1237, 1, 1237, -27, -19, 1237, -98, 2144, 28, + -98, -98, -98, -98, -98, -98, 1237, -98, -98, -98, + -98, 211, -98, 1237, 17, -98, 2238, -98, 98, -98, + -98, 2238, -98, 1237, 105, 37, -98, 63, -98, 62, + 99, 1237, -98, 60, 57, -98, 4, -98, 2238, -98, + 116, 2238, -98, 180, -98, -98, 112, 2238, 18, -98, + 11, 13, -98, 325, 3, 19, -98, -98, -98, -98, + 1237, 132, 2238, -98, 1237, 139, 2238, -98, 32, -98, + 174, -98, -98, 1237, -98, -98, 229, -98, -98, -98, + 108, 1682, -98, -98, 1862, -98, -98, 1505, -98, -98, + -98, -98, -98, -98, 125, -98, -98, -98, -98, -98, + -98, -98, -98, -98, 111, 46, 792, 184, 34, 85, + -98, -98, 136, -98, 185, -98, -98, -98, 65, 204, + -98, 1237, -98, 207, -98, -98, 193, 61, 43, 225, + 73, 88, 66, -98, -98, 214, -98, 1237, -98, 158, + -98, -98, 181, 91, 72, 1237, 172, -98, -98, 187, + -98, 157, -98, 47, -50, 274, 178, 250, -98, 113, + -98, -98, -98, 1592, 1062, -98, -98, -98, -98, -98, + 271, 2426, 1772, 15, 461, 146, 445, 76, 1237, 2238, + -5, 0, 370, 12, -15, 706, 89, 78, -98, 1415, + -98, 100, 59, 82, 1237, 86, 54, 1237, 79, 1237, + 45, 39, 279, 149, -98, 68, 617, -98, -98, -98, + -98, -98, 1150, -98, -98, -98, 886, -98, 240, -61, + 714, -98, -98, 129, 259, -98, 190, -98, 69, -98, + -98, 255, -98, -98, 94, -98, -98, -98, -98, -98, + -98, + + -105, 23, 25, 216, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -44, -105, -105, + -105, -105, -105, -105, -105, -105, -105, 70, -105, -105, + -105, 28, -105, -105, 20, 39, 97, 163, -105, 178, + 159, -105, -105, 156, 164, -105, -105, -105, -105, -105, + 132, -105, 153, 135, -105, 139, 140, -105, -105, -105, + -105, 103, 92, 144, -105, -105, -105, -105, 125, -105, + 154, 162, 83, 84, -105, 88, 82, 81, 75, 66, + 122, -105, 116, 98, 104, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, 106, -105, 113, -105, + 86, 80, 52, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, 34, -105, + -105, -105, -105, -105, 38, -105, -105, 43, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, 136, -105, 91, -29, -105, -105, 3, -105, 225, + 37, 71, -105, -105, -105, -105, -105, -105, -105, -105, + -3, -105, -105, -105, 18, -105, -105, 27, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, 87, -105, -105, 62, -105, 56, -105, + 50, -105, 31, -105, -105, -105, -105, 59, -105, -105, + -105, 47, 69, -105, -105, -105, -105, -105, 67, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, 30, + -105, -105, -105, -105, 96, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, 10, 184, + -105, 222, 226, 232, 202, -105, 124, 114, 112, 110, + 95, -105, -105, -105, -105, -105, -105, -105, -105, 212, + -105, 192, -105, 177, -105, -105, 208, -105, 107, -105, + -105, 255, -105, 11, -105, 13, -105, 44, -105, 206, + -105, 169, 176, -105, -105, 183, -105, -105, -105, -105, + -105, -105, 173, -105, 167, 117, -105, -105, 191, -105, + 54, -105, 55, -105, 58, -105, -105, 102, -105, -105, + 89, -105, -105, 57, -105, 46, -105, 45, -105, 49, + -105, -105, -105, -105, -105, -105, 77, -105, 64, -105, + 51, -105, 109, 61, -105, -105, 48, -105, -105, 152, + -105, -105, -105, 79, -105, -105, -105, -105, 4, -105, + -16, 153, -105, 74, -105, -105, -11, -105, 0, -105, + -105, -105, -105, -105, -105, -105, -5, -105, -105, -105, + -105, -105, -105, 68, -105, -105, 41, -105, -105, -105, + -105, 90, -105, -1, -105, -105, -105, -105, -105, -93, + -105, 32, -105, -4, -105, -105, -105, -105, -22, -105, + -105, -14, -105, -105, -105, -105, -105, -105, -26, -105, + -105, -2, -105, 60, -105, 53, -105, -105, -105, -105, + 65, -105, 76, -105, 78, -105, 72, -105, -105, -105, + -105, -105, -105, 21, -105, -105, 85, -105, -105, -105, + -105, 22, -105, -105, 180, -105, -105, 33, -105, -105, + -105, -105, -105, -105, -105, -105, -105, -105, -105, -105, + -105, -105, -105, -105, -105, -105, 73, -105, -105, -105, + -105, -105, -105, -105, 63, -105, -105, -105, -105, -105, + -105, 12, -105, -105, -105, -105, -105, -105, -105, -12, + -105, -105, -105, -105, -105, -105, -105, 6, -105, -105, + -105, -105, -15, -105, -105, 9, -105, -105, -105, -105, + -105, -9, -105, -105, -105, -7, -18, -13, -105, -105, + -105, -105, -105, 277, 266, -105, -105, -105, -105, -105, + -105, -105, 269, 2, 26, -105, 24, -105, 170, 16, + -105, -105, 19, -105, -105, 182, -105, -105, -105, 35, + -105, -105, -105, -105, 42, -105, 29, 153, -105, 128, + -105, -105, -105, -105, -105, -105, 349, -105, -105, -105, + -105, -105, 274, -105, -105, -105, 14, -105, -105, 15, + 218, -105, -105, -105, 7, -105, -105, -105, -105, -105, + -105, 17, -105, -105, -105, -105, -105, -105, -105, -105, + -105}; + +const int QmlJSGrammar::action_info [] = { + 345, -114, -106, -92, 343, 345, -95, 254, -122, 450, + 549, 187, 437, 413, -119, -117, -106, 454, 249, -92, + 248, 345, 454, 339, 340, 342, 349, 233, 98, 606, + -125, 398, 388, 386, 254, 396, 254, 96, 441, 144, + 98, 450, 167, 161, 138, 606, 437, 443, 554, 463, + 96, 630, 437, 68, 437, 546, 180, 406, 337, 427, + 161, 184, -96, 445, 428, 421, 176, 421, 421, 413, + 417, 411, 525, 322, 186, 454, 146, 405, 289, 535, + 400, 450, 309, 309, 315, -96, -122, 437, 269, -117, + 298, 138, 293, -119, 509, 413, -114, 521, 519, 301, + 532, 554, 68, 328, 330, 269, 291, -95, 303, 424, + 138, 55, 504, 138, 539, 289, 474, 522, 440, 0, + 534, 332, 56, 431, 138, 163, 169, 524, 523, 164, + 620, 619, 441, 138, 324, 239, 238, 246, 245, 59, + 138, 138, 311, 553, 169, 170, 312, 138, 138, 138, + 60, 138, 0, -125, 425, 626, 625, 596, 174, 410, + 409, 55, 55, 170, 475, 415, 138, 246, 245, 554, + 253, 252, 56, 56, 551, 550, 246, 245, 244, 243, + 138, 82, 466, 83, 55, 485, 505, 325, 138, 82, + 0, 83, 452, 334, 84, 56, 82, 100, 83, 456, + 251, 347, 84, 307, 82, 597, 83, 505, 169, 84, + 505, 511, 61, 517, 505, 138, 101, 84, 102, 531, + 530, 527, 0, 541, 138, 0, 169, 170, 0, 403, + 0, 0, 507, 538, 537, 467, 465, 82, 61, 83, + 61, 435, 434, 506, 138, 170, 0, 403, 542, 540, + 84, 623, 622, 507, 505, 0, 507, 62, 32, 507, + 507, 169, 0, 63, 506, 512, 510, 506, 515, 514, + 506, 506, 0, 0, 0, 528, 526, 232, 231, 32, + 170, 621, 171, 62, 32, 62, 169, 616, 32, 63, + 0, 63, 139, 0, 169, 45, 47, 46, 0, 0, + 507, 617, 615, 32, -83, 170, 0, 171, 0, 0, + 0, 506, -83, 170, 32, 171, 45, 47, 46, 32, + 0, 45, 47, 46, 32, 45, 47, 46, 32, 0, + 0, 614, 271, 272, 82, 32, 83, 0, 0, 0, + 45, 47, 46, 4, 3, 2, 1, 84, 271, 272, + 32, 45, 47, 46, 32, 0, 45, 47, 46, 273, + 274, 45, 47, 46, 32, 45, 47, 46, 0, 276, + 277, 0, 45, 47, 46, 273, 274, 32, 278, 0, + 0, 279, 0, 280, 0, 0, 0, 45, 47, 46, + 32, 45, 47, 46, 0, 0, 0, -336, 0, 32, + 0, 45, 47, 46, 0, 0, -336, 70, 71, 276, + 277, 0, 0, 0, 45, 47, 46, 0, 278, 0, + 0, 279, 0, 280, 0, 0, 0, 45, 47, 46, + 0, 75, 76, 0, 72, 73, 45, 47, 46, 77, + 78, 75, 76, 79, 0, 80, 0, 0, 0, 77, + 78, 75, 76, 79, 0, 80, 0, 0, 0, 77, + 78, 75, 76, 79, 0, 80, 0, 0, 0, 77, + 78, 75, 76, 79, 32, 80, 0, 0, 0, 77, + 78, 0, 32, 79, 0, 80, 0, 276, 277, 0, + 32, 0, 0, 0, 0, 0, 278, 0, 32, 279, + 0, 280, 0, 0, 0, 0, 242, 241, 0, 0, + 0, 45, 47, 46, 237, 236, 0, 0, 0, 45, + 47, 46, 237, 236, 0, 0, 0, 45, 47, 46, + 237, 236, 148, 0, 0, 45, 47, 46, 0, 0, + 0, 0, 149, 0, 0, 0, 150, 0, 0, 0, + 0, 0, 0, 0, 0, 151, 0, 152, 0, 0, + 0, 0, 32, 0, 0, 0, 0, 0, 153, 0, + 154, 59, 0, 0, 0, 0, 0, 0, 155, 0, + 0, 156, 60, 0, 0, 0, 0, 157, 148, 0, + 0, 0, 0, 158, 242, 241, 0, 0, 149, 45, + 47, 46, 150, 0, 0, 0, 0, 0, 0, 159, + 0, 151, 0, 152, 0, 0, 305, 0, 0, 0, + 0, 0, 0, 0, 153, 0, 154, 59, 0, 28, + 29, 148, 0, 0, 155, 0, 0, 156, 60, 31, + 0, 149, 0, 157, 0, 150, 32, 0, 0, 158, + 33, 34, 0, 35, 151, 0, 152, 0, 0, 0, + 496, 0, 0, 0, 42, 159, 0, 153, 0, 154, + 59, 0, 0, 0, 0, 0, 0, 155, 0, 0, + 156, 60, 48, 45, 47, 46, 157, 49, 0, 0, + 0, 0, 158, 0, 0, 0, 0, 0, 41, 51, + 30, 0, 0, 0, 38, 0, 0, 0, 159, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, + 0, 0, 0, 0, 0, 0, 28, 29, 31, 0, + 0, 0, 0, 0, 0, 32, 31, 0, 0, 33, + 34, 0, 35, 32, 0, 0, 0, 33, 34, 39, + 35, 0, 0, 42, 0, 0, 0, 496, 0, 0, + 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 48, 45, 47, 46, 0, 49, 0, 0, 48, + 45, 47, 46, 0, 49, 0, 0, 41, 51, 30, + 0, 0, 0, 38, 0, 41, 51, 30, 0, 0, + 0, 38, 0, 0, 28, 29, 0, 0, 0, 0, + 0, 0, 28, 29, 31, 0, 0, 0, 0, 0, + 0, 32, 31, 0, 0, 33, 34, 0, 35, 32, + 0, 0, 0, 33, 34, 496, 35, 0, 0, 42, + 0, 0, 0, 39, 0, 0, 0, 42, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 48, 45, 47, + 46, 0, 49, 0, 0, 48, 45, 47, 46, 0, + 49, 0, 0, 41, 51, 30, 0, 0, 0, 38, + 0, 41, 51, 30, 0, 0, 0, 38, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 28, 29, + 0, 0, 0, 0, 0, 0, 0, 0, 31, 0, + 0, 0, 0, 0, 0, 32, 0, 0, 0, 33, + 34, 0, 35, 0, 0, 0, 0, 0, 0, 496, + 0, 0, 0, 42, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 48, 45, 47, 46, 0, 49, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 41, 51, 30, + 0, 0, 0, 38, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 495, 0, 28, 29, 0, 0, + 0, 0, 0, 0, 0, 0, 212, 0, 0, 0, + 0, 0, 0, 32, 0, 0, 0, 33, 34, 0, + 35, 0, 0, 0, 0, 0, 0, 496, 0, 0, + 0, 42, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, + 497, 499, 498, 0, 49, 0, 0, 0, 0, 223, + 0, 0, 0, 0, 0, 41, 51, 30, 207, 0, + 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 495, 0, 28, 29, 0, 0, 0, 0, + 0, 0, 0, 0, 212, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 33, 34, 0, 35, 0, + 0, 0, 0, 0, 0, 496, 0, 0, 0, 42, + 0, 0, 0, 0, 0, 0, 0, 600, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 48, 497, 499, + 498, 0, 49, 0, 0, 0, 0, 223, 0, 0, + 0, 0, 0, 41, 51, 30, 207, 0, 0, 38, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 495, 0, 28, 29, 0, 0, 0, 0, 0, 0, + 0, 0, 212, 0, 0, 0, 0, 0, 0, 32, + 0, 0, 0, 33, 34, 0, 35, 0, 0, 0, + 0, 0, 0, 496, 0, 0, 0, 42, 0, 0, + 0, 0, 0, 0, 0, 603, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 48, 497, 499, 498, 0, + 49, 0, 0, 0, 0, 223, 0, 0, 0, 0, + 0, 41, 51, 30, 207, 0, 0, 38, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 27, 28, + 29, 0, 0, 0, 0, 0, 0, 0, 0, 31, + 0, 0, 0, 0, 0, 0, 32, 0, 0, 0, + 33, 34, 0, 35, 0, 0, 0, 36, 0, 37, + 39, 40, 0, 0, 42, 0, 0, 0, 43, 0, + 44, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 48, 45, 47, 46, 0, 49, 0, 50, + 0, 52, 0, 53, 0, 0, 0, 0, 41, 51, + 30, 0, 0, 0, 38, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 27, 28, 29, 0, 0, + 0, 0, 0, 0, 0, 0, 31, 0, 0, 0, + 0, 0, 0, 32, 0, 0, 0, 33, 34, 0, + 35, 0, 0, 0, 36, 0, 37, 39, 40, 0, + 0, 42, 0, 0, 0, 43, 0, 44, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 48, + 45, 47, 46, 0, 49, 0, 50, 0, 52, 268, + 53, 0, 0, 0, 0, 41, 51, 30, 0, 0, + 0, 38, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, -115, 0, 0, 0, 27, 28, 29, 0, + 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 32, 0, 0, 0, 33, 34, + 0, 35, 0, 0, 0, 36, 0, 37, 39, 40, + 0, 0, 42, 0, 0, 0, 43, 0, 44, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 45, 47, 46, 0, 49, 0, 50, 0, 52, + 0, 53, 0, 0, 0, 0, 41, 51, 30, 0, + 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 480, 0, 0, 27, 28, 29, 0, + 0, 0, 0, 0, 0, 0, 0, 31, 0, 0, + 0, 0, 0, 0, 32, 0, 0, 0, 33, 34, + 0, 35, 0, 0, 0, 36, 0, 37, 39, 40, + 0, 0, 42, 0, 0, 0, 43, 0, 44, 0, + 0, 481, 0, 0, 0, 0, 0, 0, 0, 0, + 48, 45, 47, 46, 0, 49, 0, 50, 0, 52, + 0, 53, 0, 0, 0, 0, 41, 51, 30, 0, + 0, 0, 38, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 27, 28, 29, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, + 0, 32, 214, 0, 0, 561, 562, 0, 35, 0, + 0, 0, 36, 0, 37, 39, 40, 0, 0, 42, + 0, 0, 0, 43, 0, 44, 0, 0, 0, 0, + 0, 0, 0, 218, 0, 0, 0, 48, 45, 47, + 46, 0, 49, 0, 50, 0, 52, 0, 53, 0, + 0, 0, 0, 41, 51, 30, 0, 0, 0, 38, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 480, 0, 0, 27, 28, 29, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 33, 34, 0, 35, 0, + 0, 0, 36, 0, 37, 39, 40, 0, 0, 42, + 0, 0, 0, 43, 0, 44, 0, 0, 483, 0, + 0, 0, 0, 0, 0, 0, 0, 48, 45, 47, + 46, 0, 49, 0, 50, 0, 52, 0, 53, 0, + 0, 0, 0, 41, 51, 30, 0, 0, 0, 38, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 472, 0, 0, 27, 28, 29, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 33, 34, 0, 35, 0, + 0, 0, 36, 0, 37, 39, 40, 0, 0, 42, + 0, 0, 0, 43, 0, 44, 0, 0, 473, 0, + 0, 0, 0, 0, 0, 0, 0, 48, 45, 47, + 46, 0, 49, 0, 50, 0, 52, 0, 53, 0, + 0, 0, 0, 41, 51, 30, 0, 0, 0, 38, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 472, 0, 0, 27, 28, 29, 0, 0, 0, 0, + 0, 0, 0, 0, 31, 0, 0, 0, 0, 0, + 0, 32, 0, 0, 0, 33, 34, 0, 35, 0, + 0, 0, 36, 0, 37, 39, 40, 0, 0, 42, + 0, 0, 0, 43, 0, 44, 0, 0, 478, 0, + 0, 0, 0, 0, 0, 0, 0, 48, 45, 47, + 46, 0, 49, 0, 50, 0, 52, 0, 53, 0, + 0, 0, 0, 41, 51, 30, 0, 0, 0, 38, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 106, 107, 108, 0, 0, 110, 112, 113, 0, 0, + 114, 0, 115, 0, 0, 0, 117, 118, 119, 0, + 0, 0, 0, 0, 0, 32, 120, 121, 122, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 123, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 126, 0, 0, 0, 0, + 0, 0, 45, 47, 46, 127, 128, 129, 0, 131, + 132, 133, 134, 135, 136, 0, 0, 124, 130, 116, + 109, 111, 125, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 106, 107, 108, 0, 0, 110, + 112, 113, 0, 0, 114, 0, 115, 0, 0, 0, + 117, 118, 119, 0, 0, 0, 0, 0, 0, 390, + 120, 121, 122, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 123, 0, 0, 0, 391, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 126, + 0, 0, 0, 0, 0, 395, 392, 394, 0, 127, + 128, 129, 0, 131, 132, 133, 134, 135, 136, 0, + 0, 124, 130, 116, 109, 111, 125, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 106, 107, + 108, 0, 0, 110, 112, 113, 0, 0, 114, 0, + 115, 0, 0, 0, 117, 118, 119, 0, 0, 0, + 0, 0, 0, 390, 120, 121, 122, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 123, 0, 0, + 0, 391, 0, 0, 0, 0, 0, 0, 0, 393, + 0, 0, 0, 126, 0, 0, 0, 0, 0, 395, + 392, 394, 0, 127, 128, 129, 0, 131, 132, 133, + 134, 135, 136, 0, 0, 124, 130, 116, 109, 111, + 125, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 206, 0, 0, 0, 0, 208, 0, 27, + 28, 29, 210, 0, 0, 0, 0, 0, 0, 211, + 31, 0, 0, 0, 0, 0, 0, 213, 214, 0, + 0, 215, 34, 0, 35, 0, 0, 0, 36, 0, + 37, 39, 40, 0, 0, 42, 0, 0, 0, 43, + 0, 44, 0, 0, 0, 0, 0, 217, 0, 218, + 0, 0, 0, 48, 216, 219, 46, 220, 49, 221, + 50, 222, 52, 223, 53, 224, 225, 0, 0, 41, + 51, 30, 207, 209, 0, 38, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 206, 0, 0, 0, + 0, 208, 0, 27, 28, 29, 210, 0, 0, 0, + 0, 0, 0, 211, 212, 0, 0, 0, 0, 0, + 0, 213, 214, 0, 0, 215, 34, 0, 35, 0, + 0, 0, 36, 0, 37, 39, 40, 0, 0, 42, + 0, 0, 0, 43, 0, 44, 0, 0, 0, 0, + 0, 217, 0, 218, 0, 0, 0, 48, 216, 219, + 46, 220, 49, 221, 50, 222, 52, 223, 53, 224, + 225, 0, 0, 41, 51, 30, 207, 209, 0, 38, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 564, 107, 108, 0, 0, 566, 112, 568, 28, 29, + 569, 0, 115, 0, 0, 0, 117, 571, 572, 0, + 0, 0, 0, 0, 0, 573, 574, 121, 122, 215, + 34, 0, 35, 0, 0, 0, 36, 0, 37, 575, + 40, 0, 0, 577, 0, 0, 0, 43, 0, 44, + 0, 0, 0, 0, 0, 579, 0, 218, 0, 0, + 0, 581, 578, 580, 46, 582, 583, 584, 50, 586, + 587, 588, 589, 590, 591, 0, 0, 576, 585, 570, + 565, 567, 125, 38, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 358, 107, 108, 0, 0, 360, + 112, 362, 28, 29, 363, 0, 115, 0, 0, 0, + 117, 365, 366, 0, 0, 0, 0, 0, 0, 367, + 368, 121, 122, 215, 34, 0, 35, 0, 0, 0, + 36, 0, 37, 369, 40, 0, 0, 371, 0, 0, + 0, 43, 0, 44, 0, -261, 0, 0, 0, 373, + 0, 218, 0, 0, 0, 375, 372, 374, 46, 376, + 377, 378, 50, 380, 381, 382, 383, 384, 385, 0, + 0, 370, 379, 364, 359, 361, 125, 38, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + + 548, 422, 414, 436, 166, 547, 552, 433, 533, 529, + 183, 520, 536, 304, 545, 513, 306, 447, 247, 599, + 618, 147, 387, 317, 627, 613, 14, 492, 397, 204, + 624, 185, 179, 250, 389, 430, 168, 240, 299, 235, + 173, 179, 484, 407, 336, 433, 308, 348, 436, 346, + 433, 350, 247, 469, 464, 482, 331, 429, 333, 344, + 335, 179, 299, 247, 240, 432, 479, 140, 451, 240, + 442, 145, 446, 444, 457, 235, 160, 235, 453, 399, + 458, 455, 299, 137, 516, 143, 508, 426, 436, 204, + 0, 204, 412, 0, 0, 0, 0, 0, 458, 103, + 0, 143, 0, 0, 143, 0, 404, 0, 57, 175, + 299, 0, 57, 91, 177, 183, 57, 57, 449, 0, + 299, 105, 90, 57, 57, 57, 57, 0, 89, 88, + 57, 94, 95, 57, 57, 81, 65, 57, 263, 57, + 57, 486, 285, 267, 86, 57, 57, 64, 57, 165, + 87, 57, 57, 177, 57, 57, 57, 284, 57, 283, + 97, 282, 85, 401, 57, 99, 57, 57, 468, 92, + 57, 281, 449, 300, 57, 69, 491, 57, 57, 449, + 317, 57, 57, 327, 58, 67, 57, 341, 66, 401, + 234, 402, 162, 401, 299, 57, 57, 448, 57, 338, + 489, 57, 74, 488, 57, 57, 57, 487, 490, 477, + 93, 57, 57, 476, 177, 295, 267, 402, 295, 295, + 267, 402, 0, 267, 267, 295, 57, 494, 313, 494, + 267, 267, 628, 0, 57, 270, 595, 323, 103, 267, + 314, 294, 493, 503, 57, 292, 0, 316, 57, 267, + 295, 288, 326, 267, 57, 267, 0, 329, 299, 267, + 105, 172, 0, 310, 57, 0, 0, 290, 57, 267, + 601, 275, 297, 267, 57, 286, 0, 494, 604, 267, + 592, 287, 0, 594, 0, 494, 0, 595, 560, 0, + 0, 0, 493, 503, 0, 563, 556, 557, 558, 559, + 493, 503, 469, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 302, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 494, 0, 0, 598, 0, 0, 0, 595, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0}; + +const int QmlJSGrammar::action_check [] = { + 36, 7, 7, 7, 7, 36, 7, 36, 7, 36, + 60, 33, 33, 36, 7, 7, 7, 36, 36, 7, + 77, 36, 36, 60, 33, 55, 16, 55, 79, 90, + 7, 55, 8, 7, 36, 7, 36, 48, 20, 8, + 79, 36, 7, 2, 8, 90, 33, 36, 33, 17, + 48, 0, 33, 1, 33, 8, 36, 7, 36, 55, + 2, 8, 7, 60, 7, 5, 60, 5, 5, 36, + 33, 7, 29, 17, 60, 36, 60, 60, 48, 7, + 55, 36, 2, 2, 7, 7, 7, 33, 1, 7, + 61, 8, 8, 7, 29, 36, 7, 24, 37, 61, + 66, 33, 1, 61, 60, 1, 79, 7, 60, 10, + 8, 40, 66, 8, 29, 48, 8, 29, 6, -1, + 29, 31, 51, 7, 8, 50, 15, 61, 62, 54, + 61, 62, 20, 8, 8, 61, 62, 61, 62, 42, + 8, 8, 50, 7, 15, 34, 54, 8, 8, 8, + 53, 8, -1, 7, 55, 61, 62, 8, 56, 61, + 62, 40, 40, 34, 56, 60, 8, 61, 62, 33, + 61, 62, 51, 51, 61, 62, 61, 62, 61, 62, + 8, 25, 8, 27, 40, 60, 29, 61, 8, 25, + -1, 27, 60, 60, 38, 51, 25, 15, 27, 60, + 60, 60, 38, 60, 25, 56, 27, 29, 15, 38, + 29, 7, 12, 29, 29, 8, 34, 38, 36, 61, + 62, 7, -1, 36, 8, -1, 15, 34, -1, 36, + -1, -1, 75, 61, 62, 61, 62, 25, 12, 27, + 12, 61, 62, 86, 8, 34, -1, 36, 61, 62, + 38, 61, 62, 75, 29, -1, 75, 57, 29, 75, + 75, 15, -1, 63, 86, 61, 62, 86, 61, 62, + 86, 86, -1, -1, -1, 61, 62, 61, 62, 29, + 34, 91, 36, 57, 29, 57, 15, 47, 29, 63, + -1, 63, 56, -1, 15, 66, 67, 68, -1, -1, + 75, 61, 62, 29, 33, 34, -1, 36, -1, -1, + -1, 86, 33, 34, 29, 36, 66, 67, 68, 29, + -1, 66, 67, 68, 29, 66, 67, 68, 29, -1, + -1, 91, 18, 19, 25, 29, 27, -1, -1, -1, + 66, 67, 68, 92, 93, 94, 95, 38, 18, 19, + 29, 66, 67, 68, 29, -1, 66, 67, 68, 45, + 46, 66, 67, 68, 29, 66, 67, 68, -1, 23, + 24, -1, 66, 67, 68, 45, 46, 29, 32, -1, + -1, 35, -1, 37, -1, -1, -1, 66, 67, 68, + 29, 66, 67, 68, -1, -1, -1, 36, -1, 29, + -1, 66, 67, 68, -1, -1, 36, 18, 19, 23, + 24, -1, -1, -1, 66, 67, 68, -1, 32, -1, + -1, 35, -1, 37, -1, -1, -1, 66, 67, 68, + -1, 23, 24, -1, 45, 46, 66, 67, 68, 31, + 32, 23, 24, 35, -1, 37, -1, -1, -1, 31, + 32, 23, 24, 35, -1, 37, -1, -1, -1, 31, + 32, 23, 24, 35, -1, 37, -1, -1, -1, 31, + 32, 23, 24, 35, 29, 37, -1, -1, -1, 31, + 32, -1, 29, 35, -1, 37, -1, 23, 24, -1, + 29, -1, -1, -1, -1, -1, 32, -1, 29, 35, + -1, 37, -1, -1, -1, -1, 61, 62, -1, -1, + -1, 66, 67, 68, 61, 62, -1, -1, -1, 66, + 67, 68, 61, 62, -1, -1, -1, 66, 67, 68, + 61, 62, 3, -1, -1, 66, 67, 68, -1, -1, + -1, -1, 13, -1, -1, -1, 17, -1, -1, -1, + -1, -1, -1, -1, -1, 26, -1, 28, -1, -1, + -1, -1, 29, -1, -1, -1, -1, -1, 39, -1, + 41, 42, -1, -1, -1, -1, -1, -1, 49, -1, + -1, 52, 53, -1, -1, -1, -1, 58, 3, -1, + -1, -1, -1, 64, 61, 62, -1, -1, 13, 66, + 67, 68, 17, -1, -1, -1, -1, -1, -1, 80, + -1, 26, -1, 28, -1, -1, 31, -1, -1, -1, + -1, -1, -1, -1, 39, -1, 41, 42, -1, 12, + 13, 3, -1, -1, 49, -1, -1, 52, 53, 22, + -1, 13, -1, 58, -1, 17, 29, -1, -1, 64, + 33, 34, -1, 36, 26, -1, 28, -1, -1, -1, + 43, -1, -1, -1, 47, 80, -1, 39, -1, 41, + 42, -1, -1, -1, -1, -1, -1, 49, -1, -1, + 52, 53, 65, 66, 67, 68, 58, 70, -1, -1, + -1, -1, 64, -1, -1, -1, -1, -1, 81, 82, + 83, -1, -1, -1, 87, -1, -1, -1, 80, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 12, 13, + -1, -1, -1, -1, -1, -1, 12, 13, 22, -1, + -1, -1, -1, -1, -1, 29, 22, -1, -1, 33, + 34, -1, 36, 29, -1, -1, -1, 33, 34, 43, + 36, -1, -1, 47, -1, -1, -1, 43, -1, -1, + -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 65, 66, 67, 68, -1, 70, -1, -1, 65, + 66, 67, 68, -1, 70, -1, -1, 81, 82, 83, + -1, -1, -1, 87, -1, 81, 82, 83, -1, -1, + -1, 87, -1, -1, 12, 13, -1, -1, -1, -1, + -1, -1, 12, 13, 22, -1, -1, -1, -1, -1, + -1, 29, 22, -1, -1, 33, 34, -1, 36, 29, + -1, -1, -1, 33, 34, 43, 36, -1, -1, 47, + -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, -1, 65, 66, 67, 68, -1, + 70, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, 81, 82, 83, -1, -1, -1, 87, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 12, 13, + -1, -1, -1, -1, -1, -1, -1, -1, 22, -1, + -1, -1, -1, -1, -1, 29, -1, -1, -1, 33, + 34, -1, 36, -1, -1, -1, -1, -1, -1, 43, + -1, -1, -1, 47, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 65, 66, 67, 68, -1, 70, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 81, 82, 83, + -1, -1, -1, 87, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 10, -1, 12, 13, -1, -1, + -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, + -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, + 36, -1, -1, -1, -1, -1, -1, 43, -1, -1, + -1, 47, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, + 66, 67, 68, -1, 70, -1, -1, -1, -1, 75, + -1, -1, -1, -1, -1, 81, 82, 83, 84, -1, + -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 10, -1, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, -1, -1, -1, 43, -1, -1, -1, 47, + -1, -1, -1, -1, -1, -1, -1, 55, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, -1, -1, -1, 75, -1, -1, + -1, -1, -1, 81, 82, 83, 84, -1, -1, 87, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 10, -1, 12, 13, -1, -1, -1, -1, -1, -1, + -1, -1, 22, -1, -1, -1, -1, -1, -1, 29, + -1, -1, -1, 33, 34, -1, 36, -1, -1, -1, + -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, + -1, -1, -1, -1, -1, 55, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 65, 66, 67, 68, -1, + 70, -1, -1, -1, -1, 75, -1, -1, -1, -1, + -1, 81, 82, 83, 84, -1, -1, 87, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 11, 12, + 13, -1, -1, -1, -1, -1, -1, -1, -1, 22, + -1, -1, -1, -1, -1, -1, 29, -1, -1, -1, + 33, 34, -1, 36, -1, -1, -1, 40, -1, 42, + 43, 44, -1, -1, 47, -1, -1, -1, 51, -1, + 53, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 65, 66, 67, 68, -1, 70, -1, 72, + -1, 74, -1, 76, -1, -1, -1, -1, 81, 82, + 83, -1, -1, -1, 87, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 11, 12, 13, -1, -1, + -1, -1, -1, -1, -1, -1, 22, -1, -1, -1, + -1, -1, -1, 29, -1, -1, -1, 33, 34, -1, + 36, -1, -1, -1, 40, -1, 42, 43, 44, -1, + -1, 47, -1, -1, -1, 51, -1, 53, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 65, + 66, 67, 68, -1, 70, -1, 72, -1, 74, 75, + 76, -1, -1, -1, -1, 81, 82, 83, -1, -1, + -1, 87, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 7, -1, -1, -1, 11, 12, 13, -1, + -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, + -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, + -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, + -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, + -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, + -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 8, -1, -1, 11, 12, 13, -1, + -1, -1, -1, -1, -1, -1, -1, 22, -1, -1, + -1, -1, -1, -1, 29, -1, -1, -1, 33, 34, + -1, 36, -1, -1, -1, 40, -1, 42, 43, 44, + -1, -1, 47, -1, -1, -1, 51, -1, 53, -1, + -1, 56, -1, -1, -1, -1, -1, -1, -1, -1, + 65, 66, 67, 68, -1, 70, -1, 72, -1, 74, + -1, 76, -1, -1, -1, -1, 81, 82, 83, -1, + -1, -1, 87, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 11, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, + -1, -1, -1, 61, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, + -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, + -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, + -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 8, -1, -1, 11, 12, 13, -1, -1, -1, -1, + -1, -1, -1, -1, 22, -1, -1, -1, -1, -1, + -1, 29, -1, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, 56, -1, + -1, -1, -1, -1, -1, -1, -1, 65, 66, 67, + 68, -1, 70, -1, 72, -1, 74, -1, 76, -1, + -1, -1, -1, 81, 82, 83, -1, -1, -1, 87, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 4, 5, 6, -1, -1, 9, 10, 11, -1, -1, + 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, + -1, -1, -1, -1, -1, 29, 30, 31, 32, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 43, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 59, -1, -1, -1, -1, + -1, -1, 66, 67, 68, 69, 70, 71, -1, 73, + 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, + 84, 85, 86, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, + 10, 11, -1, -1, 14, -1, 16, -1, -1, -1, + 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, + 30, 31, 32, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 43, -1, -1, -1, 47, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 59, + -1, -1, -1, -1, -1, 65, 66, 67, -1, 69, + 70, 71, -1, 73, 74, 75, 76, 77, 78, -1, + -1, 81, 82, 83, 84, 85, 86, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, 4, 5, + 6, -1, -1, 9, 10, 11, -1, -1, 14, -1, + 16, -1, -1, -1, 20, 21, 22, -1, -1, -1, + -1, -1, -1, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 43, -1, -1, + -1, 47, -1, -1, -1, -1, -1, -1, -1, 55, + -1, -1, -1, 59, -1, -1, -1, -1, -1, 65, + 66, 67, -1, 69, 70, 71, -1, 73, 74, 75, + 76, 77, 78, -1, -1, 81, 82, 83, 84, 85, + 86, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 4, -1, -1, -1, -1, 9, -1, 11, + 12, 13, 14, -1, -1, -1, -1, -1, -1, 21, + 22, -1, -1, -1, -1, -1, -1, 29, 30, -1, + -1, 33, 34, -1, 36, -1, -1, -1, 40, -1, + 42, 43, 44, -1, -1, 47, -1, -1, -1, 51, + -1, 53, -1, -1, -1, -1, -1, 59, -1, 61, + -1, -1, -1, 65, 66, 67, 68, 69, 70, 71, + 72, 73, 74, 75, 76, 77, 78, -1, -1, 81, + 82, 83, 84, 85, -1, 87, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 4, -1, -1, -1, + -1, 9, -1, 11, 12, 13, 14, -1, -1, -1, + -1, -1, -1, 21, 22, -1, -1, -1, -1, -1, + -1, 29, 30, -1, -1, 33, 34, -1, 36, -1, + -1, -1, 40, -1, 42, 43, 44, -1, -1, 47, + -1, -1, -1, 51, -1, 53, -1, -1, -1, -1, + -1, 59, -1, 61, -1, -1, -1, 65, 66, 67, + 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, + 78, -1, -1, 81, 82, 83, 84, 85, -1, 87, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 4, 5, 6, -1, -1, 9, 10, 11, 12, 13, + 14, -1, 16, -1, -1, -1, 20, 21, 22, -1, + -1, -1, -1, -1, -1, 29, 30, 31, 32, 33, + 34, -1, 36, -1, -1, -1, 40, -1, 42, 43, + 44, -1, -1, 47, -1, -1, -1, 51, -1, 53, + -1, -1, -1, -1, -1, 59, -1, 61, -1, -1, + -1, 65, 66, 67, 68, 69, 70, 71, 72, 73, + 74, 75, 76, 77, 78, -1, -1, 81, 82, 83, + 84, 85, 86, 87, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 4, 5, 6, -1, -1, 9, + 10, 11, 12, 13, 14, -1, 16, -1, -1, -1, + 20, 21, 22, -1, -1, -1, -1, -1, -1, 29, + 30, 31, 32, 33, 34, -1, 36, -1, -1, -1, + 40, -1, 42, 43, 44, -1, -1, 47, -1, -1, + -1, 51, -1, 53, -1, 55, -1, -1, -1, 59, + -1, 61, -1, -1, -1, 65, 66, 67, 68, 69, + 70, 71, 72, 73, 74, 75, 76, 77, 78, -1, + -1, 81, 82, 83, 84, 85, 86, 87, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, + + 13, 94, 3, 19, 33, 23, 13, 3, 23, 3, + 13, 23, 3, 2, 23, 3, 3, 19, 2, 17, + 13, 65, 33, 13, 9, 11, 3, 2, 33, 2, + 13, 13, 13, 3, 34, 3, 33, 13, 3, 13, + 3, 13, 3, 2, 13, 3, 2, 2, 19, 3, + 3, 2, 2, 33, 33, 33, 2, 79, 3, 2, + 2, 13, 3, 2, 13, 79, 33, 33, 3, 13, + 96, 33, 19, 13, 2, 13, 33, 13, 2, 2, + 13, 3, 3, 3, 11, 33, 23, 91, 19, 2, + -1, 2, 2, -1, -1, -1, -1, -1, 13, 13, + -1, 33, -1, -1, 33, -1, 38, -1, 42, 38, + 3, -1, 42, 47, 44, 13, 42, 42, 44, -1, + 3, 35, 47, 42, 42, 42, 42, -1, 47, 47, + 42, 48, 48, 42, 42, 47, 44, 42, 42, 42, + 42, 44, 47, 47, 46, 42, 42, 44, 42, 58, + 46, 42, 42, 44, 42, 42, 42, 47, 42, 47, + 54, 47, 46, 11, 42, 52, 42, 42, 83, 47, + 42, 47, 44, 66, 42, 50, 44, 42, 42, 44, + 13, 42, 42, 66, 45, 45, 42, 98, 44, 11, + 103, 39, 56, 11, 3, 42, 42, 44, 42, 97, + 44, 42, 48, 44, 42, 42, 42, 44, 44, 29, + 48, 42, 42, 33, 44, 42, 47, 39, 42, 42, + 47, 39, -1, 47, 47, 42, 42, 11, 59, 11, + 47, 47, 14, -1, 42, 51, 18, 64, 13, 47, + 64, 64, 26, 27, 42, 53, -1, 64, 42, 47, + 42, 49, 85, 47, 42, 47, -1, 66, 3, 47, + 35, 36, -1, 57, 42, -1, -1, 55, 42, 47, + 4, 49, 64, 47, 42, 49, -1, 11, 4, 47, + 11, 49, -1, 14, -1, 11, -1, 18, 11, -1, + -1, -1, 26, 27, -1, 18, 19, 20, 21, 22, + 26, 27, 33, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 66, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 11, -1, -1, 14, -1, -1, -1, 18, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1}; + diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar_p.h new file mode 100644 index 0000000000..7de77c03a0 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsgrammar_p.h @@ -0,0 +1,207 @@ +// This file was generated by qlalr - DO NOT EDIT! +/**************************************************************************** +** +** Copyright (C) 2009 Nokia Corporation and/or its subsidiary(-ies). +** All rights reserved. +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** No Commercial Usage +** This file contains pre-release code and may not be distributed. +** You may use this file in accordance with the terms and conditions +** contained in the Technology Preview License Agreement accompanying +** this package. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** In addition, as a special exception, Nokia gives you certain additional +** rights. These rights are described in the Nokia Qt LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** If you have questions regarding the use of this file, please contact +** Nokia at qt-info@nokia.com. +** +** +** +** +** +** +** +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists for the convenience +// of other Qt classes. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#ifndef QMLJSGRAMMAR_P_H +#define QMLJSGRAMMAR_P_H + +class QmlJSGrammar +{ +public: + enum { + EOF_SYMBOL = 0, + REDUCE_HERE = 97, + SHIFT_THERE = 96, + T_AND = 1, + T_AND_AND = 2, + T_AND_EQ = 3, + T_AS = 91, + T_AUTOMATIC_SEMICOLON = 62, + T_BREAK = 4, + T_CASE = 5, + T_CATCH = 6, + T_COLON = 7, + T_COMMA = 8, + T_COMMENT = 88, + T_CONST = 84, + T_CONTINUE = 9, + T_DEBUGGER = 85, + T_DEFAULT = 10, + T_DELETE = 11, + T_DIVIDE_ = 12, + T_DIVIDE_EQ = 13, + T_DO = 14, + T_DOT = 15, + T_ELSE = 16, + T_EQ = 17, + T_EQ_EQ = 18, + T_EQ_EQ_EQ = 19, + T_FALSE = 83, + T_FEED_JS_EXPRESSION = 95, + T_FEED_JS_STATEMENT = 94, + T_FEED_UI_OBJECT_MEMBER = 93, + T_FEED_UI_PROGRAM = 92, + T_FINALLY = 20, + T_FOR = 21, + T_FUNCTION = 22, + T_GE = 23, + T_GT = 24, + T_GT_GT = 25, + T_GT_GT_EQ = 26, + T_GT_GT_GT = 27, + T_GT_GT_GT_EQ = 28, + T_IDENTIFIER = 29, + T_IF = 30, + T_IMPORT = 90, + T_IN = 31, + T_INSTANCEOF = 32, + T_LBRACE = 33, + T_LBRACKET = 34, + T_LE = 35, + T_LPAREN = 36, + T_LT = 37, + T_LT_LT = 38, + T_LT_LT_EQ = 39, + T_MINUS = 40, + T_MINUS_EQ = 41, + T_MINUS_MINUS = 42, + T_MULTILINE_STRING_LITERAL = 87, + T_NEW = 43, + T_NOT = 44, + T_NOT_EQ = 45, + T_NOT_EQ_EQ = 46, + T_NULL = 81, + T_NUMERIC_LITERAL = 47, + T_OR = 48, + T_OR_EQ = 49, + T_OR_OR = 50, + T_PLUS = 51, + T_PLUS_EQ = 52, + T_PLUS_PLUS = 53, + T_PROPERTY = 66, + T_PUBLIC = 89, + T_QUESTION = 54, + T_RBRACE = 55, + T_RBRACKET = 56, + T_READONLY = 68, + T_REMAINDER = 57, + T_REMAINDER_EQ = 58, + T_RESERVED_WORD = 86, + T_RETURN = 59, + T_RPAREN = 60, + T_SEMICOLON = 61, + T_SIGNAL = 67, + T_STAR = 63, + T_STAR_EQ = 64, + T_STRING_LITERAL = 65, + T_SWITCH = 69, + T_THIS = 70, + T_THROW = 71, + T_TILDE = 72, + T_TRUE = 82, + T_TRY = 73, + T_TYPEOF = 74, + T_VAR = 75, + T_VOID = 76, + T_WHILE = 77, + T_WITH = 78, + T_XOR = 79, + T_XOR_EQ = 80, + + ACCEPT_STATE = 630, + RULE_COUNT = 340, + STATE_COUNT = 631, + TERMINAL_COUNT = 98, + NON_TERMINAL_COUNT = 105, + + GOTO_INDEX_OFFSET = 631, + GOTO_INFO_OFFSET = 2618, + GOTO_CHECK_OFFSET = 2618 + }; + + static const char *const spell []; + static const int lhs []; + static const int rhs []; + static const int goto_default []; + static const int action_default []; + static const int action_index []; + static const int action_info []; + static const int action_check []; + + static inline int nt_action (int state, int nt) + { + const int *const goto_index = &action_index [GOTO_INDEX_OFFSET]; + const int *const goto_check = &action_check [GOTO_CHECK_OFFSET]; + + const int yyn = goto_index [state] + nt; + + if (yyn < 0 || goto_check [yyn] != nt) + return goto_default [nt]; + + const int *const goto_info = &action_info [GOTO_INFO_OFFSET]; + return goto_info [yyn]; + } + + static inline int t_action (int state, int token) + { + const int yyn = action_index [state] + token; + + if (yyn < 0 || action_check [yyn] != token) + return - action_default [state]; + + return action_info [yyn]; + } +}; + + +#endif // QMLJSGRAMMAR_P_H + diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer.cpp new file mode 100644 index 0000000000..a52ea7c089 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer.cpp @@ -0,0 +1,1141 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include "qmljsglobal_p.h" +#include "qmljsengine_p.h" +#include "qmljslexer_p.h" +#include "qmljsgrammar_p.h" + +#include <ctype.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> + +QT_QML_BEGIN_NAMESPACE + +extern double qstrtod(const char *s00, char const **se, bool *ok); + +#define shiftWindowsLineBreak() \ + do { \ + if (((current == '\r') && (next1 == '\n')) \ + || ((current == '\n') && (next1 == '\r'))) { \ + shift(1); \ + } \ + } \ + while (0) + +namespace QmlJS { +extern double integerFromString(const char *buf, int size, int radix); +} + +using namespace QmlJS; + +Lexer::Lexer(Engine *eng, bool tokenizeComments) + : driver(eng), + yylineno(0), + done(false), + size8(128), size16(128), + pos8(0), pos16(0), + terminator(false), + restrKeyword(false), + delimited(false), + stackToken(-1), + state(Start), + pos(0), + code(0), length(0), + yycolumn(0), + startpos(0), + startlineno(0), startcolumn(0), + bol(true), + current(0), next1(0), next2(0), next3(0), + err(NoError), + wantRx(false), + check_reserved(true), + parenthesesState(IgnoreParentheses), + parenthesesCount(0), + prohibitAutomaticSemicolon(false), + tokenizeComments(tokenizeComments) +{ + driver->setLexer(this); + // allocate space for read buffers + buffer8 = new char[size8]; + buffer16 = new QChar[size16]; + pattern = 0; + flags = 0; + +} + +Lexer::~Lexer() +{ + delete [] buffer8; + delete [] buffer16; +} + +void Lexer::setCode(const QString &c, int lineno) +{ + errmsg = QString(); + yylineno = lineno; + yycolumn = 1; + restrKeyword = false; + delimited = false; + stackToken = -1; + pos = 0; + code = c.unicode(); + length = c.length(); + bol = true; + + // read first characters + current = (length > 0) ? code[0].unicode() : 0; + next1 = (length > 1) ? code[1].unicode() : 0; + next2 = (length > 2) ? code[2].unicode() : 0; + next3 = (length > 3) ? code[3].unicode() : 0; +} + +void Lexer::shift(uint p) +{ + while (p--) { + ++pos; + ++yycolumn; + current = next1; + next1 = next2; + next2 = next3; + next3 = (pos + 3 < length) ? code[pos+3].unicode() : 0; + } +} + +void Lexer::setDone(State s) +{ + state = s; + done = true; +} + +int Lexer::findReservedWord(const QChar *c, int size) const +{ + switch (size) { + case 2: { + if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o')) + return QmlJSGrammar::T_DO; + else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('f')) + return QmlJSGrammar::T_IF; + else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n')) + return QmlJSGrammar::T_IN; + else if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('s')) + return QmlJSGrammar::T_AS; + } break; + + case 3: { + if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('o') && c[2] == QLatin1Char('r')) + return QmlJSGrammar::T_FOR; + else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('e') && c[2] == QLatin1Char('w')) + return QmlJSGrammar::T_NEW; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') && c[2] == QLatin1Char('y')) + return QmlJSGrammar::T_TRY; + else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('a') && c[2] == QLatin1Char('r')) + return QmlJSGrammar::T_VAR; + else if (check_reserved) { + if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') && c[2] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 4: { + if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a') + && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e')) + return QmlJSGrammar::T_CASE; + else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('l') + && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('e')) + return QmlJSGrammar::T_ELSE; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('s')) + return QmlJSGrammar::T_THIS; + else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('d')) + return QmlJSGrammar::T_VOID; + else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('i') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('h')) + return QmlJSGrammar::T_WITH; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('e')) + return QmlJSGrammar::T_TRUE; + else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('u') + && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('l')) + return QmlJSGrammar::T_NULL; + else if (check_reserved) { + if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('n') + && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('m')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('y') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('l') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('g')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('r')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('g') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('o')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 5: { + if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('e') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('k')) + return QmlJSGrammar::T_BREAK; + else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('a') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('c') + && c[4] == QLatin1Char('h')) + return QmlJSGrammar::T_CATCH; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o') + && c[4] == QLatin1Char('w')) + return QmlJSGrammar::T_THROW; + else if (c[0] == QLatin1Char('w') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('l') + && c[4] == QLatin1Char('e')) + return QmlJSGrammar::T_WHILE; + else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('s') + && c[4] == QLatin1Char('t')) + return QmlJSGrammar::T_CONST; + else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('a') + && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('s') + && c[4] == QLatin1Char('e')) + return QmlJSGrammar::T_FALSE; + else if (check_reserved) { + if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('r') + && c[4] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('u') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e') + && c[4] == QLatin1Char('r')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('l')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('l') + && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('s') + && c[4] == QLatin1Char('s')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('l') + && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 6: { + if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') + && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('e') + && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('e')) + return QmlJSGrammar::T_DELETE; + else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('u') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('n')) + return QmlJSGrammar::T_RETURN; + else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('w') + && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('c') && c[5] == QLatin1Char('h')) + return QmlJSGrammar::T_SWITCH; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('y') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('e') + && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('f')) + return QmlJSGrammar::T_TYPEOF; + else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) + return QmlJSGrammar::T_IMPORT; + else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('i') + && c[2] == QLatin1Char('g') && c[3] == QLatin1Char('n') + && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('l')) + return QmlJSGrammar::T_SIGNAL; + else if (check_reserved) { + if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('t') + && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('u') && c[3] == QLatin1Char('b') + && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('o') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('u') + && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('l') + && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('c')) + return QmlJSGrammar::T_PUBLIC; + else if (c[0] == QLatin1Char('n') && c[1] == QLatin1Char('a') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('i') + && c[4] == QLatin1Char('v') && c[5] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('h') + && c[2] == QLatin1Char('r') && c[3] == QLatin1Char('o') + && c[4] == QLatin1Char('w') && c[5] == QLatin1Char('s')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 7: { + if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') + && c[2] == QLatin1Char('f') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('u') && c[5] == QLatin1Char('l') + && c[6] == QLatin1Char('t')) + return QmlJSGrammar::T_DEFAULT; + else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('i') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('l') && c[5] == QLatin1Char('l') + && c[6] == QLatin1Char('y')) + return QmlJSGrammar::T_FINALLY; + else if (check_reserved) { + if (c[0] == QLatin1Char('b') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('l') + && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('a') + && c[6] == QLatin1Char('n')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('e') && c[1] == QLatin1Char('x') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e') + && c[4] == QLatin1Char('n') && c[5] == QLatin1Char('d') + && c[6] == QLatin1Char('s')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('a') + && c[2] == QLatin1Char('c') && c[3] == QLatin1Char('k') + && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('g') + && c[6] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('i') && c[3] == QLatin1Char('v') + && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('t') + && c[6] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 8: { + if (c[0] == QLatin1Char('c') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('i') && c[5] == QLatin1Char('n') + && c[6] == QLatin1Char('u') && c[7] == QLatin1Char('e')) + return QmlJSGrammar::T_CONTINUE; + else if (c[0] == QLatin1Char('f') && c[1] == QLatin1Char('u') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c') + && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i') + && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n')) + return QmlJSGrammar::T_FUNCTION; + else if (c[0] == QLatin1Char('d') && c[1] == QLatin1Char('e') + && c[2] == QLatin1Char('b') && c[3] == QLatin1Char('u') + && c[4] == QLatin1Char('g') && c[5] == QLatin1Char('g') + && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('r')) + return QmlJSGrammar::T_DEBUGGER; + else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('p') + && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('r') + && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('y')) + return QmlJSGrammar::T_PROPERTY; + else if (c[0] == QLatin1Char('r') && c[1] == QLatin1Char('e') + && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('d') + && c[4] == QLatin1Char('o') && c[5] == QLatin1Char('n') + && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('y')) + return QmlJSGrammar::T_READONLY; + else if (check_reserved) { + if (c[0] == QLatin1Char('a') && c[1] == QLatin1Char('b') + && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('a') + && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('v') && c[1] == QLatin1Char('o') + && c[2] == QLatin1Char('l') && c[3] == QLatin1Char('a') + && c[4] == QLatin1Char('t') && c[5] == QLatin1Char('i') + && c[6] == QLatin1Char('l') && c[7] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 9: { + if (check_reserved) { + if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') + && c[2] == QLatin1Char('t') && c[3] == QLatin1Char('e') + && c[4] == QLatin1Char('r') && c[5] == QLatin1Char('f') + && c[6] == QLatin1Char('a') && c[7] == QLatin1Char('c') + && c[8] == QLatin1Char('e')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('t') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('a') && c[3] == QLatin1Char('n') + && c[4] == QLatin1Char('s') && c[5] == QLatin1Char('i') + && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n') + && c[8] == QLatin1Char('t')) + return QmlJSGrammar::T_RESERVED_WORD; + else if (c[0] == QLatin1Char('p') && c[1] == QLatin1Char('r') + && c[2] == QLatin1Char('o') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('c') + && c[6] == QLatin1Char('t') && c[7] == QLatin1Char('e') + && c[8] == QLatin1Char('d')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 10: { + if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('n') + && c[2] == QLatin1Char('s') && c[3] == QLatin1Char('t') + && c[4] == QLatin1Char('a') && c[5] == QLatin1Char('n') + && c[6] == QLatin1Char('c') && c[7] == QLatin1Char('e') + && c[8] == QLatin1Char('o') && c[9] == QLatin1Char('f')) + return QmlJSGrammar::T_INSTANCEOF; + else if (check_reserved) { + if (c[0] == QLatin1Char('i') && c[1] == QLatin1Char('m') + && c[2] == QLatin1Char('p') && c[3] == QLatin1Char('l') + && c[4] == QLatin1Char('e') && c[5] == QLatin1Char('m') + && c[6] == QLatin1Char('e') && c[7] == QLatin1Char('n') + && c[8] == QLatin1Char('t') && c[9] == QLatin1Char('s')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + case 12: { + if (check_reserved) { + if (c[0] == QLatin1Char('s') && c[1] == QLatin1Char('y') + && c[2] == QLatin1Char('n') && c[3] == QLatin1Char('c') + && c[4] == QLatin1Char('h') && c[5] == QLatin1Char('r') + && c[6] == QLatin1Char('o') && c[7] == QLatin1Char('n') + && c[8] == QLatin1Char('i') && c[9] == QLatin1Char('z') + && c[10] == QLatin1Char('e') && c[11] == QLatin1Char('d')) + return QmlJSGrammar::T_RESERVED_WORD; + } + } break; + + } // switch + + return -1; +} + +int Lexer::lex() +{ + int token = 0; + state = Start; + ushort stringType = 0; // either single or double quotes + bool multiLineString = false; + pos8 = pos16 = 0; + done = false; + terminator = false; + + // did we push a token on the stack previously ? + // (after an automatic semicolon insertion) + if (stackToken >= 0) { + setDone(Other); + token = stackToken; + stackToken = -1; + } + + while (!done) { + switch (state) { + case Start: + if (isWhiteSpace()) { + // do nothing + } else if (current == '/' && next1 == '/') { + recordStartPos(); + shift(1); + state = InSingleLineComment; + } else if (current == '/' && next1 == '*') { + recordStartPos(); + shift(1); + state = InMultiLineComment; + } else if (current == 0) { + syncProhibitAutomaticSemicolon(); + if (!terminator && !delimited && !prohibitAutomaticSemicolon) { + // automatic semicolon insertion if program incomplete + token = QmlJSGrammar::T_SEMICOLON; + stackToken = 0; + setDone(Other); + } else { + setDone(Eof); + } + } else if (isLineTerminator()) { + shiftWindowsLineBreak(); + yylineno++; + yycolumn = 0; + bol = true; + terminator = true; + syncProhibitAutomaticSemicolon(); + if (restrKeyword) { + token = QmlJSGrammar::T_SEMICOLON; + setDone(Other); + } + } else if (current == '"' || current == '\'') { + recordStartPos(); + state = InString; + multiLineString = false; + stringType = current; + } else if (isIdentLetter(current)) { + recordStartPos(); + record16(current); + state = InIdentifier; + } else if (current == '0') { + recordStartPos(); + record8(current); + state = InNum0; + } else if (isDecimalDigit(current)) { + recordStartPos(); + record8(current); + state = InNum; + } else if (current == '.' && isDecimalDigit(next1)) { + recordStartPos(); + record8(current); + state = InDecimal; + } else { + recordStartPos(); + token = matchPunctuator(current, next1, next2, next3); + if (token != -1) { + if (terminator && !delimited && !prohibitAutomaticSemicolon + && (token == QmlJSGrammar::T_PLUS_PLUS + || token == QmlJSGrammar::T_MINUS_MINUS)) { + // automatic semicolon insertion + stackToken = token; + token = QmlJSGrammar::T_SEMICOLON; + } + setDone(Other); + } + else { + setDone(Bad); + err = IllegalCharacter; + errmsg = QLatin1String("Illegal character"); + } + } + break; + case InString: + if (current == stringType) { + shift(1); + setDone(String); + } else if (isLineTerminator()) { + multiLineString = true; + record16(current); + } else if (current == 0 || isLineTerminator()) { + setDone(Bad); + err = UnclosedStringLiteral; + errmsg = QLatin1String("Unclosed string at end of line"); + } else if (current == '\\') { + state = InEscapeSequence; + } else { + record16(current); + } + break; + // Escape Sequences inside of strings + case InEscapeSequence: + if (isOctalDigit(current)) { + if (current >= '0' && current <= '3' && + isOctalDigit(next1) && isOctalDigit(next2)) { + record16(convertOctal(current, next1, next2)); + shift(2); + state = InString; + } else if (isOctalDigit(current) && + isOctalDigit(next1)) { + record16(convertOctal('0', current, next1)); + shift(1); + state = InString; + } else if (isOctalDigit(current)) { + record16(convertOctal('0', '0', current)); + state = InString; + } else { + setDone(Bad); + err = IllegalEscapeSequence; + errmsg = QLatin1String("Illegal escape squence"); + } + } else if (current == 'x') + state = InHexEscape; + else if (current == 'u') + state = InUnicodeEscape; + else { + if (isLineTerminator()) { + shiftWindowsLineBreak(); + yylineno++; + yycolumn = 0; + bol = true; + } else { + record16(singleEscape(current)); + } + state = InString; + } + break; + case InHexEscape: + if (isHexDigit(current) && isHexDigit(next1)) { + state = InString; + record16(QLatin1Char(convertHex(current, next1))); + shift(1); + } else if (current == stringType) { + record16(QLatin1Char('x')); + shift(1); + setDone(String); + } else { + record16(QLatin1Char('x')); + record16(current); + state = InString; + } + break; + case InUnicodeEscape: + if (isHexDigit(current) && isHexDigit(next1) && + isHexDigit(next2) && isHexDigit(next3)) { + record16(convertUnicode(current, next1, next2, next3)); + shift(3); + state = InString; + } else if (current == stringType) { + record16(QLatin1Char('u')); + shift(1); + setDone(String); + } else { + setDone(Bad); + err = IllegalUnicodeEscapeSequence; + errmsg = QLatin1String("Illegal unicode escape sequence"); + } + break; + case InSingleLineComment: + if (isLineTerminator()) { + shiftWindowsLineBreak(); + yylineno++; + yycolumn = 0; + terminator = true; + bol = true; + if (restrKeyword) { + token = QmlJSGrammar::T_SEMICOLON; + setDone(Other); + } else + state = Start; + driver->addComment(startpos, tokenLength(), startlineno, startcolumn); + } else if (current == 0) { + driver->addComment(startpos, tokenLength(), startlineno, startcolumn); + setDone(Eof); + } + + break; + case InMultiLineComment: + if (current == 0) { + setDone(Bad); + err = UnclosedComment; + errmsg = QLatin1String("Unclosed comment at end of file"); + driver->addComment(startpos, tokenLength(), startlineno, startcolumn); + } else if (isLineTerminator()) { + shiftWindowsLineBreak(); + yylineno++; + } else if (current == '*' && next1 == '/') { + state = Start; + shift(1); + driver->addComment(startpos, tokenLength(), startlineno, startcolumn); + } + + break; + case InIdentifier: + if (isIdentLetter(current) || isDecimalDigit(current)) { + record16(current); + break; + } + setDone(Identifier); + break; + case InNum0: + if (current == 'x' || current == 'X') { + record8(current); + state = InHex; + } else if (current == '.') { + record8(current); + state = InDecimal; + } else if (current == 'e' || current == 'E') { + record8(current); + state = InExponentIndicator; + } else if (isOctalDigit(current)) { + record8(current); + state = InOctal; + } else if (isDecimalDigit(current)) { + record8(current); + state = InDecimal; + } else { + setDone(Number); + } + break; + case InHex: + if (isHexDigit(current)) + record8(current); + else + setDone(Hex); + break; + case InOctal: + if (isOctalDigit(current)) { + record8(current); + } else if (isDecimalDigit(current)) { + record8(current); + state = InDecimal; + } else { + setDone(Octal); + } + break; + case InNum: + if (isDecimalDigit(current)) { + record8(current); + } else if (current == '.') { + record8(current); + state = InDecimal; + } else if (current == 'e' || current == 'E') { + record8(current); + state = InExponentIndicator; + } else { + setDone(Number); + } + break; + case InDecimal: + if (isDecimalDigit(current)) { + record8(current); + } else if (current == 'e' || current == 'E') { + record8(current); + state = InExponentIndicator; + } else { + setDone(Number); + } + break; + case InExponentIndicator: + if (current == '+' || current == '-') { + record8(current); + } else if (isDecimalDigit(current)) { + record8(current); + state = InExponent; + } else { + setDone(Bad); + err = IllegalExponentIndicator; + errmsg = QLatin1String("Illegal syntax for exponential number"); + } + break; + case InExponent: + if (isDecimalDigit(current)) { + record8(current); + } else { + setDone(Number); + } + break; + default: + Q_ASSERT_X(0, "Lexer::lex", "Unhandled state in switch statement"); + } + + // move on to the next character + if (!done) + shift(1); + if (state != Start && state != InSingleLineComment) + bol = false; + } + + // no identifiers allowed directly after numeric literal, e.g. "3in" is bad + if ((state == Number || state == Octal || state == Hex) + && isIdentLetter(current)) { + state = Bad; + err = IllegalIdentifier; + errmsg = QLatin1String("Identifier cannot start with numeric literal"); + } + + // terminate string + buffer8[pos8] = '\0'; + + double dval = 0; + if (state == Number) { + dval = qstrtod(buffer8, 0, 0); + } else if (state == Hex) { // scan hex numbers + dval = integerFromString(buffer8, pos8, 16); + state = Number; + } else if (state == Octal) { // scan octal number + dval = integerFromString(buffer8, pos8, 8); + state = Number; + } + + restrKeyword = false; + delimited = false; + + switch (parenthesesState) { + case IgnoreParentheses: + break; + case CountParentheses: + if (token == QmlJSGrammar::T_RPAREN) { + --parenthesesCount; + if (parenthesesCount == 0) + parenthesesState = BalancedParentheses; + } else if (token == QmlJSGrammar::T_LPAREN) { + ++parenthesesCount; + } + break; + case BalancedParentheses: + parenthesesState = IgnoreParentheses; + break; + } + + switch (state) { + case Eof: + return 0; + case Other: + if (token == QmlJSGrammar::T_RBRACE || token == QmlJSGrammar::T_SEMICOLON) + delimited = true; + return token; + case Identifier: + if ((token = findReservedWord(buffer16, pos16)) < 0) { + /* TODO: close leak on parse error. same holds true for String */ + if (driver) + qsyylval.ustr = driver->intern(buffer16, pos16); + else + qsyylval.ustr = 0; + return QmlJSGrammar::T_IDENTIFIER; + } + if (token == QmlJSGrammar::T_CONTINUE || token == QmlJSGrammar::T_BREAK + || token == QmlJSGrammar::T_RETURN || token == QmlJSGrammar::T_THROW) { + restrKeyword = true; + } else if (token == QmlJSGrammar::T_IF || token == QmlJSGrammar::T_FOR + || token == QmlJSGrammar::T_WHILE || token == QmlJSGrammar::T_WITH) { + parenthesesState = CountParentheses; + parenthesesCount = 0; + } else if (token == QmlJSGrammar::T_DO) { + parenthesesState = BalancedParentheses; + } + return token; + case String: + if (driver) + qsyylval.ustr = driver->intern(buffer16, pos16); + else + qsyylval.ustr = 0; + return multiLineString?QmlJSGrammar::T_MULTILINE_STRING_LITERAL:QmlJSGrammar::T_STRING_LITERAL; + case Number: + qsyylval.dval = dval; + return QmlJSGrammar::T_NUMERIC_LITERAL; + case Bad: + return -1; + default: + Q_ASSERT(!"unhandled numeration value in switch"); + return -1; + } +} + +bool Lexer::isWhiteSpace() const +{ + return (current == ' ' || current == '\t' || + current == 0x0b || current == 0x0c); +} + +bool Lexer::isLineTerminator() const +{ + return (current == '\n' || current == '\r'); +} + +bool Lexer::isIdentLetter(ushort c) +{ + /* TODO: allow other legitimate unicode chars */ + return ((c >= 'a' && c <= 'z') + || (c >= 'A' && c <= 'Z') + || c == '$' + || c == '_'); +} + +bool Lexer::isDecimalDigit(ushort c) +{ + return (c >= '0' && c <= '9'); +} + +bool Lexer::isHexDigit(ushort c) const +{ + return ((c >= '0' && c <= '9') + || (c >= 'a' && c <= 'f') + || (c >= 'A' && c <= 'F')); +} + +bool Lexer::isOctalDigit(ushort c) const +{ + return (c >= '0' && c <= '7'); +} + +int Lexer::matchPunctuator(ushort c1, ushort c2, + ushort c3, ushort c4) +{ + if (c1 == '>' && c2 == '>' && c3 == '>' && c4 == '=') { + shift(4); + return QmlJSGrammar::T_GT_GT_GT_EQ; + } else if (c1 == '=' && c2 == '=' && c3 == '=') { + shift(3); + return QmlJSGrammar::T_EQ_EQ_EQ; + } else if (c1 == '!' && c2 == '=' && c3 == '=') { + shift(3); + return QmlJSGrammar::T_NOT_EQ_EQ; + } else if (c1 == '>' && c2 == '>' && c3 == '>') { + shift(3); + return QmlJSGrammar::T_GT_GT_GT; + } else if (c1 == '<' && c2 == '<' && c3 == '=') { + shift(3); + return QmlJSGrammar::T_LT_LT_EQ; + } else if (c1 == '>' && c2 == '>' && c3 == '=') { + shift(3); + return QmlJSGrammar::T_GT_GT_EQ; + } else if (c1 == '<' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_LE; + } else if (c1 == '>' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_GE; + } else if (c1 == '!' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_NOT_EQ; + } else if (c1 == '+' && c2 == '+') { + shift(2); + return QmlJSGrammar::T_PLUS_PLUS; + } else if (c1 == '-' && c2 == '-') { + shift(2); + return QmlJSGrammar::T_MINUS_MINUS; + } else if (c1 == '=' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_EQ_EQ; + } else if (c1 == '+' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_PLUS_EQ; + } else if (c1 == '-' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_MINUS_EQ; + } else if (c1 == '*' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_STAR_EQ; + } else if (c1 == '/' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_DIVIDE_EQ; + } else if (c1 == '&' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_AND_EQ; + } else if (c1 == '^' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_XOR_EQ; + } else if (c1 == '%' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_REMAINDER_EQ; + } else if (c1 == '|' && c2 == '=') { + shift(2); + return QmlJSGrammar::T_OR_EQ; + } else if (c1 == '<' && c2 == '<') { + shift(2); + return QmlJSGrammar::T_LT_LT; + } else if (c1 == '>' && c2 == '>') { + shift(2); + return QmlJSGrammar::T_GT_GT; + } else if (c1 == '&' && c2 == '&') { + shift(2); + return QmlJSGrammar::T_AND_AND; + } else if (c1 == '|' && c2 == '|') { + shift(2); + return QmlJSGrammar::T_OR_OR; + } + + switch(c1) { + case '=': shift(1); return QmlJSGrammar::T_EQ; + case '>': shift(1); return QmlJSGrammar::T_GT; + case '<': shift(1); return QmlJSGrammar::T_LT; + case ',': shift(1); return QmlJSGrammar::T_COMMA; + case '!': shift(1); return QmlJSGrammar::T_NOT; + case '~': shift(1); return QmlJSGrammar::T_TILDE; + case '?': shift(1); return QmlJSGrammar::T_QUESTION; + case ':': shift(1); return QmlJSGrammar::T_COLON; + case '.': shift(1); return QmlJSGrammar::T_DOT; + case '+': shift(1); return QmlJSGrammar::T_PLUS; + case '-': shift(1); return QmlJSGrammar::T_MINUS; + case '*': shift(1); return QmlJSGrammar::T_STAR; + case '/': shift(1); return QmlJSGrammar::T_DIVIDE_; + case '&': shift(1); return QmlJSGrammar::T_AND; + case '|': shift(1); return QmlJSGrammar::T_OR; + case '^': shift(1); return QmlJSGrammar::T_XOR; + case '%': shift(1); return QmlJSGrammar::T_REMAINDER; + case '(': shift(1); return QmlJSGrammar::T_LPAREN; + case ')': shift(1); return QmlJSGrammar::T_RPAREN; + case '{': shift(1); return QmlJSGrammar::T_LBRACE; + case '}': shift(1); return QmlJSGrammar::T_RBRACE; + case '[': shift(1); return QmlJSGrammar::T_LBRACKET; + case ']': shift(1); return QmlJSGrammar::T_RBRACKET; + case ';': shift(1); return QmlJSGrammar::T_SEMICOLON; + + default: return -1; + } +} + +ushort Lexer::singleEscape(ushort c) const +{ + switch(c) { + case 'b': + return 0x08; + case 't': + return 0x09; + case 'n': + return 0x0A; + case 'v': + return 0x0B; + case 'f': + return 0x0C; + case 'r': + return 0x0D; + case '"': + return 0x22; + case '\'': + return 0x27; + case '\\': + return 0x5C; + default: + return c; + } +} + +ushort Lexer::convertOctal(ushort c1, ushort c2, + ushort c3) const +{ + return ((c1 - '0') * 64 + (c2 - '0') * 8 + c3 - '0'); +} + +unsigned char Lexer::convertHex(ushort c) +{ + if (c >= '0' && c <= '9') + return (c - '0'); + else if (c >= 'a' && c <= 'f') + return (c - 'a' + 10); + else + return (c - 'A' + 10); +} + +unsigned char Lexer::convertHex(ushort c1, ushort c2) +{ + return ((convertHex(c1) << 4) + convertHex(c2)); +} + +QChar Lexer::convertUnicode(ushort c1, ushort c2, + ushort c3, ushort c4) +{ + return QChar((convertHex(c3) << 4) + convertHex(c4), + (convertHex(c1) << 4) + convertHex(c2)); +} + +void Lexer::record8(ushort c) +{ + Q_ASSERT(c <= 0xff); + + // enlarge buffer if full + if (pos8 >= size8 - 1) { + char *tmp = new char[2 * size8]; + memcpy(tmp, buffer8, size8 * sizeof(char)); + delete [] buffer8; + buffer8 = tmp; + size8 *= 2; + } + + buffer8[pos8++] = (char) c; +} + +void Lexer::record16(QChar c) +{ + // enlarge buffer if full + if (pos16 >= size16 - 1) { + QChar *tmp = new QChar[2 * size16]; + memcpy(tmp, buffer16, size16 * sizeof(QChar)); + delete [] buffer16; + buffer16 = tmp; + size16 *= 2; + } + + buffer16[pos16++] = c; +} + +void Lexer::recordStartPos() +{ + startpos = pos; + startlineno = yylineno; + startcolumn = yycolumn; +} + +bool Lexer::scanRegExp(RegExpBodyPrefix prefix) +{ + pos16 = 0; + bool lastWasEscape = false; + + if (prefix == EqualPrefix) + record16(QLatin1Char('=')); + + while (1) { + if (isLineTerminator() || current == 0) { + errmsg = QLatin1String("Unterminated regular expression literal"); + return false; + } + else if (current != '/' || lastWasEscape == true) + { + record16(current); + lastWasEscape = !lastWasEscape && (current == '\\'); + } + else { + if (driver) + pattern = driver->intern(buffer16, pos16); + else + pattern = 0; + pos16 = 0; + shift(1); + break; + } + shift(1); + } + + flags = 0; + while (isIdentLetter(current)) { + int flag = Ecma::RegExp::flagFromChar(current); + if (flag == 0) { + errmsg = QString::fromLatin1("Invalid regular expression flag '%0'") + .arg(QChar(current)); + return false; + } + flags |= flag; + record16(current); + shift(1); + } + + return true; +} + +void Lexer::syncProhibitAutomaticSemicolon() +{ + if (parenthesesState == BalancedParentheses) { + // we have seen something like "if (foo)", which means we should + // never insert an automatic semicolon at this point, since it would + // then be expanded into an empty statement (ECMA-262 7.9.1) + prohibitAutomaticSemicolon = true; + parenthesesState = IgnoreParentheses; + } else { + prohibitAutomaticSemicolon = false; + } +} + +QT_QML_END_NAMESPACE + + diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer_p.h new file mode 100644 index 0000000000..1be466c3e6 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljslexer_p.h @@ -0,0 +1,237 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLJSLEXER_P_H +#define QMLJSLEXER_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QString> + +#include "qmljsglobal_p.h" + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { + +class Engine; +class NameId; + +class Lexer +{ +public: + Lexer(Engine *eng, bool tokenizeComments = false); + ~Lexer(); + + void setCode(const QString &c, int lineno); + int lex(); + + int currentLineNo() const { return yylineno; } + int currentColumnNo() const { return yycolumn; } + + int tokenOffset() const { return startpos; } + int tokenLength() const { return pos - startpos; } + + int startLineNo() const { return startlineno; } + int startColumnNo() const { return startcolumn; } + + int endLineNo() const { return currentLineNo(); } + int endColumnNo() const + { int col = currentColumnNo(); return (col > 0) ? col - 1 : col; } + + bool prevTerminator() const { return terminator; } + + enum State { Start, + Identifier, + InIdentifier, + InSingleLineComment, + InMultiLineComment, + InNum, + InNum0, + InHex, + InOctal, + InDecimal, + InExponentIndicator, + InExponent, + Hex, + Octal, + Number, + String, + Eof, + InString, + InEscapeSequence, + InHexEscape, + InUnicodeEscape, + Other, + Bad }; + + enum Error { + NoError, + IllegalCharacter, + UnclosedStringLiteral, + IllegalEscapeSequence, + IllegalUnicodeEscapeSequence, + UnclosedComment, + IllegalExponentIndicator, + IllegalIdentifier + }; + + enum ParenthesesState { + IgnoreParentheses, + CountParentheses, + BalancedParentheses + }; + + enum RegExpBodyPrefix { + NoPrefix, + EqualPrefix + }; + + bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix); + + NameId *pattern; + int flags; + + State lexerState() const + { return state; } + + QString errorMessage() const + { return errmsg; } + void setErrorMessage(const QString &err) + { errmsg = err; } + void setErrorMessage(const char *err) + { setErrorMessage(QString::fromLatin1(err)); } + + Error error() const + { return err; } + void clearError() + { err = NoError; } + +private: + Engine *driver; + int yylineno; + bool done; + char *buffer8; + QChar *buffer16; + uint size8, size16; + uint pos8, pos16; + bool terminator; + bool restrKeyword; + // encountered delimiter like "'" and "}" on last run + bool delimited; + int stackToken; + + State state; + void setDone(State s); + uint pos; + void shift(uint p); + int lookupKeyword(const char *); + + bool isWhiteSpace() const; + bool isLineTerminator() const; + bool isHexDigit(ushort c) const; + bool isOctalDigit(ushort c) const; + + int matchPunctuator(ushort c1, ushort c2, + ushort c3, ushort c4); + ushort singleEscape(ushort c) const; + ushort convertOctal(ushort c1, ushort c2, + ushort c3) const; +public: + static unsigned char convertHex(ushort c1); + static unsigned char convertHex(ushort c1, ushort c2); + static QChar convertUnicode(ushort c1, ushort c2, + ushort c3, ushort c4); + static bool isIdentLetter(ushort c); + static bool isDecimalDigit(ushort c); + + inline int ival() const { return qsyylval.ival; } + inline double dval() const { return qsyylval.dval; } + inline NameId *ustr() const { return qsyylval.ustr; } + + const QChar *characterBuffer() const { return buffer16; } + int characterCount() const { return pos16; } + +private: + void record8(ushort c); + void record16(QChar c); + void recordStartPos(); + + int findReservedWord(const QChar *buffer, int size) const; + + void syncProhibitAutomaticSemicolon(); + + const QChar *code; + uint length; + int yycolumn; + int startpos; + int startlineno; + int startcolumn; + int bol; // begin of line + + union { + int ival; + double dval; + NameId *ustr; + } qsyylval; + + // current and following unicode characters + ushort current, next1, next2, next3; + + struct keyword { + const char *name; + int token; + }; + + QString errmsg; + Error err; + + bool wantRx; + bool check_reserved; + + ParenthesesState parenthesesState; + int parenthesesCount; + bool prohibitAutomaticSemicolon; + bool tokenizeComments; +}; + +} // namespace QmlJS + +QT_QML_END_NAMESPACE + +#endif diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsmemorypool_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsmemorypool_p.h new file mode 100644 index 0000000000..4b79f174fb --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsmemorypool_p.h @@ -0,0 +1,120 @@ +/**************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLJSMEMORYPOOL_P_H +#define QMLJSMEMORYPOOL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/qglobal.h> +#include <QtCore/qshareddata.h> +#include <string.h> + +#include "qmljsglobal_p.h" + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { + +class MemoryPool : public QSharedData +{ +public: + enum { maxBlockCount = -1 }; + enum { defaultBlockSize = 1 << 12 }; + + MemoryPool() { + m_blockIndex = maxBlockCount; + m_currentIndex = 0; + m_storage = 0; + m_currentBlock = 0; + m_currentBlockSize = 0; + } + + virtual ~MemoryPool() { + for (int index = 0; index < m_blockIndex + 1; ++index) + qFree(m_storage[index]); + + qFree(m_storage); + } + + char *allocate(int bytes) { + bytes += (8 - bytes) & 7; // ensure multiple of 8 bytes (maintain alignment) + if (m_currentBlock == 0 || m_currentBlockSize < m_currentIndex + bytes) { + ++m_blockIndex; + m_currentBlockSize = defaultBlockSize << m_blockIndex; + + m_storage = reinterpret_cast<char**>(qRealloc(m_storage, sizeof(char*) * (1 + m_blockIndex))); + m_currentBlock = m_storage[m_blockIndex] = reinterpret_cast<char*>(qMalloc(m_currentBlockSize)); + ::memset(m_currentBlock, 0, m_currentBlockSize); + + m_currentIndex = (8 - quintptr(m_currentBlock)) & 7; // ensure first chunk is 64-bit aligned + Q_ASSERT(m_currentIndex + bytes <= m_currentBlockSize); + } + + char *p = reinterpret_cast<char *> + (m_currentBlock + m_currentIndex); + + m_currentIndex += bytes; + + return p; + } + + int bytesAllocated() const { + int bytes = 0; + for (int index = 0; index < m_blockIndex; ++index) + bytes += (defaultBlockSize << index); + bytes += m_currentIndex; + return bytes; + } + +private: + int m_blockIndex; + int m_currentIndex; + char *m_currentBlock; + int m_currentBlockSize; + char **m_storage; + +private: + Q_DISABLE_COPY(MemoryPool) +}; + +} // namespace QmlJS + +QT_QML_END_NAMESPACE + +#endif diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsnodepool_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsnodepool_p.h new file mode 100644 index 0000000000..ba0c3678ef --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsnodepool_p.h @@ -0,0 +1,127 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLJSNODEPOOL_P_H +#define QMLJSNODEPOOL_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +#include <QtCore/QHash> +#include <QtCore/QString> + +#include "qmljsglobal_p.h" +#include "qmljsmemorypool_p.h" + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { + +namespace AST { +class Node; +} // namespace AST + +class Code; +class CompilationUnit; +class Engine; + +template <typename NodeType> +inline NodeType *makeAstNode(MemoryPool *storage) +{ + NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(); + return node; +} + +template <typename NodeType, typename Arg1> +inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1) +{ + NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1); + return node; +} + +template <typename NodeType, typename Arg1, typename Arg2> +inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2) +{ + NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2); + return node; +} + +template <typename NodeType, typename Arg1, typename Arg2, typename Arg3> +inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3) +{ + NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3); + return node; +} + +template <typename NodeType, typename Arg1, typename Arg2, typename Arg3, typename Arg4> +inline NodeType *makeAstNode(MemoryPool *storage, Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4) +{ + NodeType *node = new (storage->allocate(sizeof(NodeType))) NodeType(arg1, arg2, arg3, arg4); + return node; +} + +class NodePool : public MemoryPool +{ +public: + NodePool(const QString &fileName, Engine *engine); + virtual ~NodePool(); + + Code *createCompiledCode(AST::Node *node, CompilationUnit &compilation); + + inline QString fileName() const { return m_fileName; } + inline Engine *engine() const { return m_engine; } +#ifndef J_SCRIPT_NO_EVENT_NOTIFY + inline qint64 id() const { return m_id; } +#endif + +private: + QHash<AST::Node*, Code*> m_codeCache; + QString m_fileName; + Engine *m_engine; +#ifndef J_SCRIPT_NO_EVENT_NOTIFY + qint64 m_id; +#endif + +private: + Q_DISABLE_COPY(NodePool) +}; + +} // namespace QmlJS + +QT_QML_END_NAMESPACE + +#endif diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser.cpp b/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser.cpp new file mode 100644 index 0000000000..f5fab00f4c --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser.cpp @@ -0,0 +1,1812 @@ +// This file was generated by qlalr - DO NOT EDIT! + +/**************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <QtCore/QtDebug> + +#include <string.h> + +#include "qmljsengine_p.h" +#include "qmljslexer_p.h" +#include "qmljsast_p.h" +#include "qmljsnodepool_p.h" + + + +#include "qmljsparser_p.h" +#include <QVarLengthArray> + +// +// This file is automatically generated from qmljs.g. +// Changes will be lost. +// + +using namespace QmlJS; + +QT_QML_BEGIN_NAMESPACE + +void Parser::reallocateStack() +{ + if (! stack_size) + stack_size = 128; + else + stack_size <<= 1; + + sym_stack = reinterpret_cast<Value*> (qRealloc(sym_stack, stack_size * sizeof(Value))); + state_stack = reinterpret_cast<int*> (qRealloc(state_stack, stack_size * sizeof(int))); + location_stack = reinterpret_cast<AST::SourceLocation*> (qRealloc(location_stack, stack_size * sizeof(AST::SourceLocation))); +} + +inline static bool automatic(Engine *driver, int token) +{ + return token == QmlJSGrammar::T_RBRACE + || token == 0 + || driver->lexer()->prevTerminator(); +} + + +Parser::Parser(Engine *engine): + driver(engine), + tos(0), + stack_size(0), + sym_stack(0), + state_stack(0), + location_stack(0), + first_token(0), + last_token(0) +{ +} + +Parser::~Parser() +{ + if (stack_size) { + qFree(sym_stack); + qFree(state_stack); + qFree(location_stack); + } +} + +static inline AST::SourceLocation location(Lexer *lexer) +{ + AST::SourceLocation loc; + loc.offset = lexer->tokenOffset(); + loc.length = lexer->tokenLength(); + loc.startLine = lexer->startLineNo(); + loc.startColumn = lexer->startColumnNo(); + return loc; +} + +AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) +{ + QVarLengthArray<NameId *, 4> nameIds; + QVarLengthArray<AST::SourceLocation, 4> locations; + + AST::ExpressionNode *it = expr; + while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) { + nameIds.append(m->name); + locations.append(m->identifierToken); + it = m->base; + } + + if (AST::IdentifierExpression *idExpr = AST::cast<AST::IdentifierExpression *>(it)) { + AST::UiQualifiedId *q = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), idExpr->name); + q->identifierToken = idExpr->identifierToken; + + AST::UiQualifiedId *currentId = q; + for (int i = nameIds.size() - 1; i != -1; --i) { + currentId = makeAstNode<AST::UiQualifiedId>(driver->nodePool(), currentId, nameIds[i]); + currentId->identifierToken = locations[i]; + } + + return currentId->finish(); + } + + return 0; +} + +bool Parser::parse(int startToken) +{ + Lexer *lexer = driver->lexer(); + bool hadErrors = false; + int yytoken = -1; + int action = 0; + + token_buffer[0].token = startToken; + first_token = &token_buffer[0]; + last_token = &token_buffer[1]; + + tos = -1; + program = 0; + + do { + if (++tos == stack_size) + reallocateStack(); + + state_stack[tos] = action; + + _Lcheck_token: + if (yytoken == -1 && -TERMINAL_COUNT != action_index[action]) { + yyprevlloc = yylloc; + + if (first_token == last_token) { + yytoken = lexer->lex(); + yylval = lexer->dval(); + yylloc = location(lexer); + } else { + yytoken = first_token->token; + yylval = first_token->dval; + yylloc = first_token->loc; + ++first_token; + } + } + + action = t_action(action, yytoken); + if (action > 0) { + if (action != ACCEPT_STATE) { + yytoken = -1; + sym(1).dval = yylval; + loc(1) = yylloc; + } else { + --tos; + return ! hadErrors; + } + } else if (action < 0) { + const int r = -action - 1; + tos -= rhs[r]; + + switch (r) { + +case 0: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; + +case 1: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; + +case 2: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; + +case 3: { + sym(1).Node = sym(2).Node; + program = sym(1).Node; +} break; + +case 4: { + sym(1).UiProgram = makeAstNode<AST::UiProgram> (driver->nodePool(), sym(1).UiImportList, + sym(2).UiObjectMemberList->finish()); +} break; + +case 6: { + sym(1).Node = sym(1).UiImportList->finish(); +} break; + +case 7: { + sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), sym(1).UiImport); +} break; + +case 8: { + sym(1).Node = makeAstNode<AST::UiImportList> (driver->nodePool(), + sym(1).UiImportList, sym(2).UiImport); +} break; + +case 11: { + sym(1).UiImport->semicolonToken = loc(2); +} break; + +case 13: { + sym(1).UiImport->versionToken = loc(2); + sym(1).UiImport->semicolonToken = loc(3); +} break; + +case 15: { + sym(1).UiImport->versionToken = loc(2); + sym(1).UiImport->asToken = loc(3); + sym(1).UiImport->importIdToken = loc(4); + sym(1).UiImport->importId = sym(4).sval; + sym(1).UiImport->semicolonToken = loc(5); +} break; + +case 17: { + sym(1).UiImport->asToken = loc(2); + sym(1).UiImport->importIdToken = loc(3); + sym(1).UiImport->importId = sym(3).sval; + sym(1).UiImport->semicolonToken = loc(4); +} break; + +case 18: { + AST::UiImport *node = 0; + + if (AST::StringLiteral *importIdLiteral = AST::cast<AST::StringLiteral *>(sym(2).Expression)) { + node = makeAstNode<AST::UiImport>(driver->nodePool(), importIdLiteral->value); + node->fileNameToken = loc(2); + } else if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(2).Expression)) { + QString text; + for (AST::UiQualifiedId *q = qualifiedId; q; q = q->next) { + text += q->name->asString(); + if (q->next) text += QLatin1String("."); + } + node = makeAstNode<AST::UiImport>(driver->nodePool(), qualifiedId); + node->fileNameToken = loc(2); + } + + sym(1).Node = node; + + if (! node) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), + QLatin1String("Expected a qualified name id or a string literal"))); + + return false; // ### remove me + } +} break; + +case 19: { + sym(1).Node = 0; +} break; + +case 20: { + sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember); +} break; + +case 21: { + sym(1).Node = makeAstNode<AST::UiObjectMemberList> (driver->nodePool(), sym(1).UiObjectMember); +} break; + +case 22: { + AST::UiObjectMemberList *node = makeAstNode<AST:: UiObjectMemberList> (driver->nodePool(), + sym(1).UiObjectMemberList, sym(2).UiObjectMember); + sym(1).Node = node; +} break; + +case 23: { + sym(1).Node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), sym(1).UiObjectMember); +} break; + +case 24: { + AST::UiArrayMemberList *node = makeAstNode<AST::UiArrayMemberList> (driver->nodePool(), + sym(1).UiArrayMemberList, sym(3).UiObjectMember); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 25: { + AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), (AST::UiObjectMemberList*)0); + node->lbraceToken = loc(1); + node->rbraceToken = loc(2); + sym(1).Node = node; +} break; + +case 26: { + AST::UiObjectInitializer *node = makeAstNode<AST::UiObjectInitializer> (driver->nodePool(), sym(2).UiObjectMemberList->finish()); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; + +case 27: { + AST::UiObjectDefinition *node = makeAstNode<AST::UiObjectDefinition> (driver->nodePool(), sym(1).UiQualifiedId, + sym(2).UiObjectInitializer); + sym(1).Node = node; +} break; + +case 29: { + AST::UiArrayBinding *node = makeAstNode<AST::UiArrayBinding> (driver->nodePool(), + sym(1).UiQualifiedId, sym(4).UiArrayMemberList->finish()); + node->colonToken = loc(2); + node->lbracketToken = loc(3); + node->rbracketToken = loc(5); + sym(1).Node = node; +} break; + +case 30: { + AST::UiObjectBinding *node = makeAstNode<AST::UiObjectBinding> (driver->nodePool(), + sym(1).UiQualifiedId, sym(3).UiQualifiedId, sym(4).UiObjectInitializer); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +case 31:case 32:case 33:case 34: +{ + AST::UiScriptBinding *node = makeAstNode<AST::UiScriptBinding> (driver->nodePool(), + sym(1).UiQualifiedId, sym(3).Statement); + node->colonToken = loc(2); + sym(1).Node = node; +} break; + +case 35: + +case 36: { + sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); + break; +} + +case 38: { + sym(1).Node = 0; +} break; + +case 39: { + sym(1).Node = sym(1).UiParameterList->finish (); +} break; + +case 40: { + AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).sval, sym(2).sval); + node->identifierToken = loc(2); + sym(1).Node = node; +} break; + +case 41: { + AST::UiParameterList *node = makeAstNode<AST::UiParameterList> (driver->nodePool(), sym(1).UiParameterList, sym(3).sval, sym(4).sval); + node->commaToken = loc(2); + node->identifierToken = loc(4); + sym(1).Node = node; +} break; + +case 43: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); + node->type = AST::UiPublicMember::Signal; + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(2); + node->parameters = sym(4).UiParameterList; + node->semicolonToken = loc(6); + sym(1).Node = node; +} break; + +case 45: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), (NameId *)0, sym(2).sval); + node->type = AST::UiPublicMember::Signal; + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 47: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(4).sval, sym(6).sval); + node->typeModifier = sym(2).sval; + node->propertyToken = loc(1); + node->typeModifierToken = loc(2); + node->typeToken = loc(4); + node->identifierToken = loc(6); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; + +case 49: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->semicolonToken = loc(4); + sym(1).Node = node; +} break; + +case 51: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->semicolonToken = loc(5); + sym(1).Node = node; +} break; + +case 53: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(2).sval, sym(3).sval, + sym(5).Expression); + node->propertyToken = loc(1); + node->typeToken = loc(2); + node->identifierToken = loc(3); + node->colonToken = loc(4); + node->semicolonToken = loc(6); + sym(1).Node = node; +} break; + +case 55: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, + sym(6).Expression); + node->isReadonlyMember = true; + node->readonlyToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->colonToken = loc(5); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; + +case 57: { + AST::UiPublicMember *node = makeAstNode<AST::UiPublicMember> (driver->nodePool(), sym(3).sval, sym(4).sval, + sym(6).Expression); + node->isDefaultMember = true; + node->defaultToken = loc(1); + node->propertyToken = loc(2); + node->typeToken = loc(3); + node->identifierToken = loc(4); + node->colonToken = loc(5); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; + +case 58: { + sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); +} break; + +case 59: { + sym(1).Node = makeAstNode<AST::UiSourceElement>(driver->nodePool(), sym(1).Node); +} break; + +case 61: { + QString s = QLatin1String(QmlJSGrammar::spell[T_PROPERTY]); + sym(1).sval = driver->intern(s.constData(), s.length()); + break; +} + +case 62: { + QString s = QLatin1String(QmlJSGrammar::spell[T_SIGNAL]); + sym(1).sval = driver->intern(s.constData(), s.length()); + break; +} + +case 63: { + QString s = QLatin1String(QmlJSGrammar::spell[T_READONLY]); + sym(1).sval = driver->intern(s.constData(), s.length()); + break; +} + +case 64: { + AST::ThisExpression *node = makeAstNode<AST::ThisExpression> (driver->nodePool()); + node->thisToken = loc(1); + sym(1).Node = node; +} break; + +case 65: { + AST::IdentifierExpression *node = makeAstNode<AST::IdentifierExpression> (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 66: { + AST::NullExpression *node = makeAstNode<AST::NullExpression> (driver->nodePool()); + node->nullToken = loc(1); + sym(1).Node = node; +} break; + +case 67: { + AST::TrueLiteral *node = makeAstNode<AST::TrueLiteral> (driver->nodePool()); + node->trueToken = loc(1); + sym(1).Node = node; +} break; + +case 68: { + AST::FalseLiteral *node = makeAstNode<AST::FalseLiteral> (driver->nodePool()); + node->falseToken = loc(1); + sym(1).Node = node; +} break; + +case 69: { + AST::NumericLiteral *node = makeAstNode<AST::NumericLiteral> (driver->nodePool(), sym(1).dval); + node->literalToken = loc(1); + sym(1).Node = node; +} break; +case 70: +case 71: { + AST::StringLiteral *node = makeAstNode<AST::StringLiteral> (driver->nodePool(), sym(1).sval); + node->literalToken = loc(1); + sym(1).Node = node; +} break; + +case 72: { + bool rx = lexer->scanRegExp(Lexer::NoPrefix); + if (!rx) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); + return false; // ### remove me + } + AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags); + node->literalToken = loc(1); + sym(1).Node = node; +} break; + +case 73: { + bool rx = lexer->scanRegExp(Lexer::EqualPrefix); + if (!rx) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, location(lexer), lexer->errorMessage())); + return false; + } + AST::RegExpLiteral *node = makeAstNode<AST::RegExpLiteral> (driver->nodePool(), lexer->pattern, lexer->flags); + node->literalToken = loc(1); + sym(1).Node = node; +} break; + +case 74: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->rbracketToken = loc(2); + sym(1).Node = node; +} break; + +case 75: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).Elision->finish()); + node->lbracketToken = loc(1); + node->rbracketToken = loc(3); + sym(1).Node = node; +} break; + +case 76: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish ()); + node->lbracketToken = loc(1); + node->rbracketToken = loc(3); + sym(1).Node = node; +} break; + +case 77: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + (AST::Elision *) 0); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; + +case 78: { + AST::ArrayLiteral *node = makeAstNode<AST::ArrayLiteral> (driver->nodePool(), sym(2).ElementList->finish (), + sym(4).Elision->finish()); + node->lbracketToken = loc(1); + node->commaToken = loc(3); + node->rbracketToken = loc(5); + sym(1).Node = node; +} break; + +case 79: { + AST::ObjectLiteral *node = 0; + if (sym(2).Node) + node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), + sym(2).PropertyNameAndValueList->finish ()); + else + node = makeAstNode<AST::ObjectLiteral> (driver->nodePool()); + node->lbraceToken = loc(1); + node->lbraceToken = loc(3); + sym(1).Node = node; +} break; + +case 80: { + AST::ObjectLiteral *node = makeAstNode<AST::ObjectLiteral> (driver->nodePool(), + sym(2).PropertyNameAndValueList->finish ()); + node->lbraceToken = loc(1); + node->lbraceToken = loc(4); + sym(1).Node = node; +} break; + +case 81: { + AST::NestedExpression *node = makeAstNode<AST::NestedExpression>(driver->nodePool(), sym(2).Expression); + node->lparenToken = loc(1); + node->rparenToken = loc(3); + sym(1).Node = node; +} break; + +case 82: { + if (AST::ArrayMemberExpression *mem = AST::cast<AST::ArrayMemberExpression *>(sym(1).Expression)) { + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, mem->lbracketToken, + QLatin1String("Ignored annotation"))); + + sym(1).Expression = mem->base; + } + + if (AST::UiQualifiedId *qualifiedId = reparseAsQualifiedId(sym(1).Expression)) { + sym(1).UiQualifiedId = qualifiedId; + } else { + sym(1).UiQualifiedId = 0; + + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, loc(1), + QLatin1String("Expected a qualified name id"))); + + return false; // ### recover + } +} break; + +case 83: { + sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), (AST::Elision *) 0, sym(1).Expression); +} break; + +case 84: { + sym(1).Node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).Elision->finish(), sym(2).Expression); +} break; + +case 85: { + AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, + (AST::Elision *) 0, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 86: { + AST::ElementList *node = makeAstNode<AST::ElementList> (driver->nodePool(), sym(1).ElementList, sym(3).Elision->finish(), + sym(4).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 87: { + AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool()); + node->commaToken = loc(1); + sym(1).Node = node; +} break; + +case 88: { + AST::Elision *node = makeAstNode<AST::Elision> (driver->nodePool(), sym(1).Elision); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 89: { + AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), + sym(1).PropertyName, sym(3).Expression); + node->colonToken = loc(2); + sym(1).Node = node; +} break; + +case 90: { + AST::PropertyNameAndValueList *node = makeAstNode<AST::PropertyNameAndValueList> (driver->nodePool(), + sym(1).PropertyNameAndValueList, sym(3).PropertyName, sym(5).Expression); + node->commaToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; + +case 91: { + AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; +case 92: +case 93: { + AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount())); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; + +case 94: { + AST::StringLiteralPropertyName *node = makeAstNode<AST::StringLiteralPropertyName> (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; + +case 95: { + AST::NumericLiteralPropertyName *node = makeAstNode<AST::NumericLiteralPropertyName> (driver->nodePool(), sym(1).dval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; + +case 96: { + AST::IdentifierPropertyName *node = makeAstNode<AST::IdentifierPropertyName> (driver->nodePool(), sym(1).sval); + node->propertyNameToken = loc(1); + sym(1).Node = node; +} break; + +case 97: + +case 98: + +case 99: + +case 100: + +case 101: + +case 102: + +case 103: + +case 104: + +case 105: + +case 106: + +case 107: + +case 108: + +case 109: + +case 110: + +case 111: + +case 112: + +case 113: + +case 114: + +case 115: + +case 116: + +case 117: + +case 118: + +case 119: + +case 120: + +case 121: + +case 122: + +case 123: + +case 124: + +case 125: + +case 126: + +case 127: +{ + sym(1).sval = driver->intern(lexer->characterBuffer(), lexer->characterCount()); +} break; + +case 132: { + AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->lbracketToken = loc(2); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; + +case 133: { + AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; + +case 134: { + AST::NewMemberExpression *node = makeAstNode<AST::NewMemberExpression> (driver->nodePool(), sym(2).Expression, sym(4).ArgumentList); + node->newToken = loc(1); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + sym(1).Node = node; +} break; + +case 136: { + AST::NewExpression *node = makeAstNode<AST::NewExpression> (driver->nodePool(), sym(2).Expression); + node->newToken = loc(1); + sym(1).Node = node; +} break; + +case 137: { + AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 138: { + AST::CallExpression *node = makeAstNode<AST::CallExpression> (driver->nodePool(), sym(1).Expression, sym(3).ArgumentList); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 139: { + AST::ArrayMemberExpression *node = makeAstNode<AST::ArrayMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->lbracketToken = loc(2); + node->rbracketToken = loc(4); + sym(1).Node = node; +} break; + +case 140: { + AST::FieldMemberExpression *node = makeAstNode<AST::FieldMemberExpression> (driver->nodePool(), sym(1).Expression, sym(3).sval); + node->dotToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; + +case 141: { + sym(1).Node = 0; +} break; + +case 142: { + sym(1).Node = sym(1).ArgumentList->finish(); +} break; + +case 143: { + sym(1).Node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).Expression); +} break; + +case 144: { + AST::ArgumentList *node = makeAstNode<AST::ArgumentList> (driver->nodePool(), sym(1).ArgumentList, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 148: { + AST::PostIncrementExpression *node = makeAstNode<AST::PostIncrementExpression> (driver->nodePool(), sym(1).Expression); + node->incrementToken = loc(2); + sym(1).Node = node; +} break; + +case 149: { + AST::PostDecrementExpression *node = makeAstNode<AST::PostDecrementExpression> (driver->nodePool(), sym(1).Expression); + node->decrementToken = loc(2); + sym(1).Node = node; +} break; + +case 151: { + AST::DeleteExpression *node = makeAstNode<AST::DeleteExpression> (driver->nodePool(), sym(2).Expression); + node->deleteToken = loc(1); + sym(1).Node = node; +} break; + +case 152: { + AST::VoidExpression *node = makeAstNode<AST::VoidExpression> (driver->nodePool(), sym(2).Expression); + node->voidToken = loc(1); + sym(1).Node = node; +} break; + +case 153: { + AST::TypeOfExpression *node = makeAstNode<AST::TypeOfExpression> (driver->nodePool(), sym(2).Expression); + node->typeofToken = loc(1); + sym(1).Node = node; +} break; + +case 154: { + AST::PreIncrementExpression *node = makeAstNode<AST::PreIncrementExpression> (driver->nodePool(), sym(2).Expression); + node->incrementToken = loc(1); + sym(1).Node = node; +} break; + +case 155: { + AST::PreDecrementExpression *node = makeAstNode<AST::PreDecrementExpression> (driver->nodePool(), sym(2).Expression); + node->decrementToken = loc(1); + sym(1).Node = node; +} break; + +case 156: { + AST::UnaryPlusExpression *node = makeAstNode<AST::UnaryPlusExpression> (driver->nodePool(), sym(2).Expression); + node->plusToken = loc(1); + sym(1).Node = node; +} break; + +case 157: { + AST::UnaryMinusExpression *node = makeAstNode<AST::UnaryMinusExpression> (driver->nodePool(), sym(2).Expression); + node->minusToken = loc(1); + sym(1).Node = node; +} break; + +case 158: { + AST::TildeExpression *node = makeAstNode<AST::TildeExpression> (driver->nodePool(), sym(2).Expression); + node->tildeToken = loc(1); + sym(1).Node = node; +} break; + +case 159: { + AST::NotExpression *node = makeAstNode<AST::NotExpression> (driver->nodePool(), sym(2).Expression); + node->notToken = loc(1); + sym(1).Node = node; +} break; + +case 161: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Mul, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 162: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Div, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 163: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Mod, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 165: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Add, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 166: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Sub, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 168: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::LShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 169: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::RShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 170: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::URShift, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 172: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Lt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 173: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Gt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 174: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Le, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 175: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Ge, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 176: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::InstanceOf, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 177: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::In, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 179: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Lt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 180: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Gt, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 181: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Le, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 182: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Ge, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 183: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::InstanceOf, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 185: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Equal, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 186: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::NotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 187: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::StrictEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 188: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::StrictNotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 190: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Equal, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 191: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::NotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 192: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::StrictEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 193: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::StrictNotEqual, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 195: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitAnd, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 197: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitAnd, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 199: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitXor, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 201: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitXor, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 203: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 205: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::BitOr, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 207: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 209: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::And, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 211: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 213: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + QSOperator::Or, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 215: { + AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, + sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; + +case 217: { + AST::ConditionalExpression *node = makeAstNode<AST::ConditionalExpression> (driver->nodePool(), sym(1).Expression, + sym(3).Expression, sym(5).Expression); + node->questionToken = loc(2); + node->colonToken = loc(4); + sym(1).Node = node; +} break; + +case 219: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 221: { + AST::BinaryExpression *node = makeAstNode<AST::BinaryExpression> (driver->nodePool(), sym(1).Expression, + sym(2).ival, sym(3).Expression); + node->operatorToken = loc(2); + sym(1).Node = node; +} break; + +case 222: { + sym(1).ival = QSOperator::Assign; +} break; + +case 223: { + sym(1).ival = QSOperator::InplaceMul; +} break; + +case 224: { + sym(1).ival = QSOperator::InplaceDiv; +} break; + +case 225: { + sym(1).ival = QSOperator::InplaceMod; +} break; + +case 226: { + sym(1).ival = QSOperator::InplaceAdd; +} break; + +case 227: { + sym(1).ival = QSOperator::InplaceSub; +} break; + +case 228: { + sym(1).ival = QSOperator::InplaceLeftShift; +} break; + +case 229: { + sym(1).ival = QSOperator::InplaceRightShift; +} break; + +case 230: { + sym(1).ival = QSOperator::InplaceURightShift; +} break; + +case 231: { + sym(1).ival = QSOperator::InplaceAnd; +} break; + +case 232: { + sym(1).ival = QSOperator::InplaceXor; +} break; + +case 233: { + sym(1).ival = QSOperator::InplaceOr; +} break; + +case 235: { + AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 236: { + sym(1).Node = 0; +} break; + +case 239: { + AST::Expression *node = makeAstNode<AST::Expression> (driver->nodePool(), sym(1).Expression, sym(3).Expression); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 240: { + sym(1).Node = 0; +} break; + +case 257: { + AST::Block *node = makeAstNode<AST::Block> (driver->nodePool(), sym(2).StatementList); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; + +case 258: { + sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).Statement); +} break; + +case 259: { + sym(1).Node = makeAstNode<AST::StatementList> (driver->nodePool(), sym(1).StatementList, sym(2).Statement); +} break; + +case 260: { + sym(1).Node = 0; +} break; + +case 261: { + sym(1).Node = sym(1).StatementList->finish (); +} break; + +case 263: { + AST::VariableStatement *node = makeAstNode<AST::VariableStatement> (driver->nodePool(), + sym(2).VariableDeclarationList->finish (/*readOnly=*/sym(1).ival == T_CONST)); + node->declarationKindToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 264: { + sym(1).ival = T_CONST; +} break; + +case 265: { + sym(1).ival = T_VAR; +} break; + +case 266: { + sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); +} break; + +case 267: { + AST::VariableDeclarationList *node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), + sym(1).VariableDeclarationList, sym(3).VariableDeclaration); + node->commaToken = loc(2); + sym(1).Node = node; +} break; + +case 268: { + sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclaration); +} break; + +case 269: { + sym(1).Node = makeAstNode<AST::VariableDeclarationList> (driver->nodePool(), sym(1).VariableDeclarationList, sym(3).VariableDeclaration); +} break; + +case 270: { + AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 271: { + AST::VariableDeclaration *node = makeAstNode<AST::VariableDeclaration> (driver->nodePool(), sym(1).sval, sym(2).Expression); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 272: { + // ### TODO: AST for initializer + sym(1) = sym(2); +} break; + +case 273: { + sym(1).Node = 0; +} break; + +case 275: { + // ### TODO: AST for initializer + sym(1) = sym(2); +} break; + +case 276: { + sym(1).Node = 0; +} break; + +case 278: { + AST::EmptyStatement *node = makeAstNode<AST::EmptyStatement> (driver->nodePool()); + node->semicolonToken = loc(1); + sym(1).Node = node; +} break; + +case 280: { + AST::ExpressionStatement *node = makeAstNode<AST::ExpressionStatement> (driver->nodePool(), sym(1).Expression); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; + +case 281: { + AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement, sym(7).Statement); + node->ifToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + node->elseToken = loc(5); + sym(1).Node = node; +} break; + +case 282: { + AST::IfStatement *node = makeAstNode<AST::IfStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->ifToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 284: { + AST::DoWhileStatement *node = makeAstNode<AST::DoWhileStatement> (driver->nodePool(), sym(2).Statement, sym(5).Expression); + node->doToken = loc(1); + node->whileToken = loc(3); + node->lparenToken = loc(4); + node->rparenToken = loc(6); + node->semicolonToken = loc(7); + sym(1).Node = node; +} break; + +case 285: { + AST::WhileStatement *node = makeAstNode<AST::WhileStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->whileToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 286: { + AST::ForStatement *node = makeAstNode<AST::ForStatement> (driver->nodePool(), sym(3).Expression, + sym(5).Expression, sym(7).Expression, sym(9).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->firstSemicolonToken = loc(4); + node->secondSemicolonToken = loc(6); + node->rparenToken = loc(8); + sym(1).Node = node; +} break; + +case 287: { + AST::LocalForStatement *node = makeAstNode<AST::LocalForStatement> (driver->nodePool(), + sym(4).VariableDeclarationList->finish (/*readOnly=*/false), sym(6).Expression, + sym(8).Expression, sym(10).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->varToken = loc(3); + node->firstSemicolonToken = loc(5); + node->secondSemicolonToken = loc(7); + node->rparenToken = loc(9); + sym(1).Node = node; +} break; + +case 288: { + AST:: ForEachStatement *node = makeAstNode<AST::ForEachStatement> (driver->nodePool(), sym(3).Expression, + sym(5).Expression, sym(7).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->inToken = loc(4); + node->rparenToken = loc(6); + sym(1).Node = node; +} break; + +case 289: { + AST::LocalForEachStatement *node = makeAstNode<AST::LocalForEachStatement> (driver->nodePool(), + sym(4).VariableDeclaration, sym(6).Expression, sym(8).Statement); + node->forToken = loc(1); + node->lparenToken = loc(2); + node->varToken = loc(3); + node->inToken = loc(5); + node->rparenToken = loc(7); + sym(1).Node = node; +} break; + +case 291: { + AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool()); + node->continueToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; + +case 293: { + AST::ContinueStatement *node = makeAstNode<AST::ContinueStatement> (driver->nodePool(), sym(2).sval); + node->continueToken = loc(1); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 295: { + AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool()); + node->breakToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; + +case 297: { + AST::BreakStatement *node = makeAstNode<AST::BreakStatement> (driver->nodePool(), sym(2).sval); + node->breakToken = loc(1); + node->identifierToken = loc(2); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 299: { + AST::ReturnStatement *node = makeAstNode<AST::ReturnStatement> (driver->nodePool(), sym(2).Expression); + node->returnToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 300: { + AST::WithStatement *node = makeAstNode<AST::WithStatement> (driver->nodePool(), sym(3).Expression, sym(5).Statement); + node->withToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 301: { + AST::SwitchStatement *node = makeAstNode<AST::SwitchStatement> (driver->nodePool(), sym(3).Expression, sym(5).CaseBlock); + node->switchToken = loc(1); + node->lparenToken = loc(2); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 302: { + AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses); + node->lbraceToken = loc(1); + node->rbraceToken = loc(3); + sym(1).Node = node; +} break; + +case 303: { + AST::CaseBlock *node = makeAstNode<AST::CaseBlock> (driver->nodePool(), sym(2).CaseClauses, sym(3).DefaultClause, sym(4).CaseClauses); + node->lbraceToken = loc(1); + node->rbraceToken = loc(5); + sym(1).Node = node; +} break; + +case 304: { + sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClause); +} break; + +case 305: { + sym(1).Node = makeAstNode<AST::CaseClauses> (driver->nodePool(), sym(1).CaseClauses, sym(2).CaseClause); +} break; + +case 306: { + sym(1).Node = 0; +} break; + +case 307: { + sym(1).Node = sym(1).CaseClauses->finish (); +} break; + +case 308: { + AST::CaseClause *node = makeAstNode<AST::CaseClause> (driver->nodePool(), sym(2).Expression, sym(4).StatementList); + node->caseToken = loc(1); + node->colonToken = loc(3); + sym(1).Node = node; +} break; + +case 309: { + AST::DefaultClause *node = makeAstNode<AST::DefaultClause> (driver->nodePool(), sym(3).StatementList); + node->defaultToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; +case 310: +case 311: { + AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), driver->intern(lexer->characterBuffer(), lexer->characterCount()), sym(3).Statement); + node->identifierToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; + +case 312: { + AST::LabelledStatement *node = makeAstNode<AST::LabelledStatement> (driver->nodePool(), sym(1).sval, sym(3).Statement); + node->identifierToken = loc(1); + node->colonToken = loc(2); + sym(1).Node = node; +} break; + +case 314: { + AST::ThrowStatement *node = makeAstNode<AST::ThrowStatement> (driver->nodePool(), sym(2).Expression); + node->throwToken = loc(1); + node->semicolonToken = loc(3); + sym(1).Node = node; +} break; + +case 315: { + AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch); + node->tryToken = loc(1); + sym(1).Node = node; +} break; + +case 316: { + AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Finally); + node->tryToken = loc(1); + sym(1).Node = node; +} break; + +case 317: { + AST::TryStatement *node = makeAstNode<AST::TryStatement> (driver->nodePool(), sym(2).Statement, sym(3).Catch, sym(4).Finally); + node->tryToken = loc(1); + sym(1).Node = node; +} break; + +case 318: { + AST::Catch *node = makeAstNode<AST::Catch> (driver->nodePool(), sym(3).sval, sym(5).Block); + node->catchToken = loc(1); + node->lparenToken = loc(2); + node->identifierToken = loc(3); + node->rparenToken = loc(4); + sym(1).Node = node; +} break; + +case 319: { + AST::Finally *node = makeAstNode<AST::Finally> (driver->nodePool(), sym(2).Block); + node->finallyToken = loc(1); + sym(1).Node = node; +} break; + +case 321: { + AST::DebuggerStatement *node = makeAstNode<AST::DebuggerStatement> (driver->nodePool()); + node->debuggerToken = loc(1); + node->semicolonToken = loc(2); + sym(1).Node = node; +} break; + +case 322: { + AST::FunctionDeclaration *node = makeAstNode<AST::FunctionDeclaration> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + node->functionToken = loc(1); + node->identifierToken = loc(2); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; +} break; + +case 323: { + AST::FunctionExpression *node = makeAstNode<AST::FunctionExpression> (driver->nodePool(), sym(2).sval, sym(4).FormalParameterList, sym(7).FunctionBody); + node->functionToken = loc(1); + if (sym(2).sval) + node->identifierToken = loc(2); + node->lparenToken = loc(3); + node->rparenToken = loc(5); + node->lbraceToken = loc(6); + node->rbraceToken = loc(8); + sym(1).Node = node; +} break; + +case 324: { + AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).sval); + node->identifierToken = loc(1); + sym(1).Node = node; +} break; + +case 325: { + AST::FormalParameterList *node = makeAstNode<AST::FormalParameterList> (driver->nodePool(), sym(1).FormalParameterList, sym(3).sval); + node->commaToken = loc(2); + node->identifierToken = loc(3); + sym(1).Node = node; +} break; + +case 326: { + sym(1).Node = 0; +} break; + +case 327: { + sym(1).Node = sym(1).FormalParameterList->finish (); +} break; + +case 328: { + sym(1).Node = 0; +} break; + +case 330: { + sym(1).Node = makeAstNode<AST::FunctionBody> (driver->nodePool(), sym(1).SourceElements->finish ()); +} break; + +case 331: { + sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElement); +} break; + +case 332: { + sym(1).Node = makeAstNode<AST::SourceElements> (driver->nodePool(), sym(1).SourceElements, sym(2).SourceElement); +} break; + +case 333: { + sym(1).Node = makeAstNode<AST::StatementSourceElement> (driver->nodePool(), sym(1).Statement); +} break; + +case 334: { + sym(1).Node = makeAstNode<AST::FunctionSourceElement> (driver->nodePool(), sym(1).FunctionDeclaration); +} break; + +case 335: { + sym(1).sval = 0; +} break; + +case 337: { + sym(1).Node = 0; +} break; + + } // switch + action = nt_action(state_stack[tos], lhs[r] - TERMINAL_COUNT); + } // if + } while (action != 0); + + if (first_token == last_token) { + const int errorState = state_stack[tos]; + + // automatic insertion of `;' + if (t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) { + SavedToken &tk = token_buffer[0]; + tk.token = yytoken; + tk.dval = yylval; + tk.loc = yylloc; + + yylloc = yyprevlloc; + yylloc.offset += yylloc.length; + yylloc.startColumn += yylloc.length; + yylloc.length = 0; + + //const QString msg = QString::fromUtf8("Missing `;'"); + //diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Warning, yylloc, msg)); + + first_token = &token_buffer[0]; + last_token = &token_buffer[1]; + + yytoken = T_SEMICOLON; + yylval = 0; + + action = errorState; + + goto _Lcheck_token; + } + + hadErrors = true; + + token_buffer[0].token = yytoken; + token_buffer[0].dval = yylval; + token_buffer[0].loc = yylloc; + + token_buffer[1].token = yytoken = lexer->lex(); + token_buffer[1].dval = yylval = lexer->dval(); + token_buffer[1].loc = yylloc = location(lexer); + + if (t_action(errorState, yytoken)) { + const QString msg = QString::fromUtf8("Unexpected token `%1'").arg(QLatin1String(spell[token_buffer[0].token])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + action = errorState; + goto _Lcheck_token; + } + + static int tokens[] = { + T_PLUS, + T_EQ, + + T_COMMA, + T_COLON, + T_SEMICOLON, + + T_RPAREN, T_RBRACKET, T_RBRACE, + + T_NUMERIC_LITERAL, + T_IDENTIFIER, + + T_LPAREN, T_LBRACKET, T_LBRACE, + + EOF_SYMBOL + }; + + for (int *tk = tokens; *tk != EOF_SYMBOL; ++tk) { + int a = t_action(errorState, *tk); + if (a > 0 && t_action(a, yytoken)) { + const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[*tk])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + yytoken = *tk; + yylval = 0; + yylloc = token_buffer[0].loc; + yylloc.length = 0; + + first_token = &token_buffer[0]; + last_token = &token_buffer[2]; + + action = errorState; + goto _Lcheck_token; + } + } + + for (int tk = 1; tk < TERMINAL_COUNT; ++tk) { + if (tk == T_AUTOMATIC_SEMICOLON || tk == T_FEED_UI_PROGRAM || + tk == T_FEED_JS_STATEMENT || tk == T_FEED_JS_EXPRESSION) + continue; + + int a = t_action(errorState, tk); + if (a > 0 && t_action(a, yytoken)) { + const QString msg = QString::fromUtf8("Expected token `%1'").arg(QLatin1String(spell[tk])); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + + yytoken = tk; + yylval = 0; + yylloc = token_buffer[0].loc; + yylloc.length = 0; + + action = errorState; + goto _Lcheck_token; + } + } + + const QString msg = QString::fromUtf8("Syntax error"); + diagnostic_messages.append(DiagnosticMessage(DiagnosticMessage::Error, token_buffer[0].loc, msg)); + } + + return false; +} + +QT_QML_END_NAMESPACE + + diff --git a/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser_p.h b/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser_p.h new file mode 100644 index 0000000000..7ee69a57d5 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/parser/qmljsparser_p.h @@ -0,0 +1,230 @@ +// This file was generated by qlalr - DO NOT EDIT! + +/**************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +// +// This file is automatically generated from qmljs.g. +// Changes will be lost. +// + +#ifndef QMLJSPARSER_P_H +#define QMLJSPARSER_P_H + +#include "qmljsglobal_p.h" +#include "qmljsgrammar_p.h" +#include "qmljsast_p.h" +#include "qmljsengine_p.h" + +#include <QtCore/QList> +#include <QtCore/QString> + +QT_QML_BEGIN_NAMESPACE + +namespace QmlJS { + +class Engine; +class NameId; + +class Parser: protected QmlJSGrammar +{ +public: + union Value { + int ival; + double dval; + NameId *sval; + AST::ArgumentList *ArgumentList; + AST::CaseBlock *CaseBlock; + AST::CaseClause *CaseClause; + AST::CaseClauses *CaseClauses; + AST::Catch *Catch; + AST::DefaultClause *DefaultClause; + AST::ElementList *ElementList; + AST::Elision *Elision; + AST::ExpressionNode *Expression; + AST::Finally *Finally; + AST::FormalParameterList *FormalParameterList; + AST::FunctionBody *FunctionBody; + AST::FunctionDeclaration *FunctionDeclaration; + AST::Node *Node; + AST::PropertyName *PropertyName; + AST::PropertyNameAndValueList *PropertyNameAndValueList; + AST::SourceElement *SourceElement; + AST::SourceElements *SourceElements; + AST::Statement *Statement; + AST::StatementList *StatementList; + AST::Block *Block; + AST::VariableDeclaration *VariableDeclaration; + AST::VariableDeclarationList *VariableDeclarationList; + + AST::UiProgram *UiProgram; + AST::UiImportList *UiImportList; + AST::UiImport *UiImport; + AST::UiParameterList *UiParameterList; + AST::UiPublicMember *UiPublicMember; + AST::UiObjectDefinition *UiObjectDefinition; + AST::UiObjectInitializer *UiObjectInitializer; + AST::UiObjectBinding *UiObjectBinding; + AST::UiScriptBinding *UiScriptBinding; + AST::UiArrayBinding *UiArrayBinding; + AST::UiObjectMember *UiObjectMember; + AST::UiObjectMemberList *UiObjectMemberList; + AST::UiArrayMemberList *UiArrayMemberList; + AST::UiQualifiedId *UiQualifiedId; + AST::UiSignature *UiSignature; + AST::UiFormalList *UiFormalList; + AST::UiFormal *UiFormal; + }; + +public: + Parser(Engine *engine); + ~Parser(); + + // parse a UI program + bool parse() { return parse(T_FEED_UI_PROGRAM); } + bool parseStatement() { return parse(T_FEED_JS_STATEMENT); } + bool parseExpression() { return parse(T_FEED_JS_EXPRESSION); } + bool parseUiObjectMember() { return parse(T_FEED_UI_OBJECT_MEMBER); } + + AST::UiProgram *ast() const + { return AST::cast<AST::UiProgram *>(program); } + + AST::Statement *statement() const + { + if (! program) + return 0; + + return program->statementCast(); + } + + AST::ExpressionNode *expression() const + { + if (! program) + return 0; + + return program->expressionCast(); + } + + AST::UiObjectMember *uiObjectMember() const + { + if (! program) + return 0; + + return program->uiObjectMemberCast(); + } + + QList<DiagnosticMessage> diagnosticMessages() const + { return diagnostic_messages; } + + inline DiagnosticMessage diagnosticMessage() const + { + foreach (const DiagnosticMessage &d, diagnostic_messages) { + if (! d.kind == DiagnosticMessage::Warning) + return d; + } + + return DiagnosticMessage(); + } + + inline QString errorMessage() const + { return diagnosticMessage().message; } + + inline int errorLineNumber() const + { return diagnosticMessage().loc.startLine; } + + inline int errorColumnNumber() const + { return diagnosticMessage().loc.startColumn; } + +protected: + bool parse(int startToken); + + void reallocateStack(); + + inline Value &sym(int index) + { return sym_stack [tos + index - 1]; } + + inline AST::SourceLocation &loc(int index) + { return location_stack [tos + index - 1]; } + + AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); + +protected: + Engine *driver; + int tos; + int stack_size; + Value *sym_stack; + int *state_stack; + AST::SourceLocation *location_stack; + + AST::Node *program; + + // error recovery + enum { TOKEN_BUFFER_SIZE = 3 }; + + struct SavedToken { + int token; + double dval; + AST::SourceLocation loc; + }; + + double yylval; + AST::SourceLocation yylloc; + AST::SourceLocation yyprevlloc; + + SavedToken token_buffer[TOKEN_BUFFER_SIZE]; + SavedToken *first_token; + SavedToken *last_token; + + QList<DiagnosticMessage> diagnostic_messages; +}; + +} // end of namespace QmlJS + + + +#define J_SCRIPT_REGEXPLITERAL_RULE1 72 + +#define J_SCRIPT_REGEXPLITERAL_RULE2 73 + +QT_QML_END_NAMESPACE + + + +#endif // QMLJSPARSER_P_H diff --git a/src/plugins/qmldesigner/core/filemanager/qmldocument.cpp b/src/plugins/qmldesigner/core/filemanager/qmldocument.cpp new file mode 100644 index 0000000000..d89e69609f --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/qmldocument.cpp @@ -0,0 +1,165 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "idcollector.h" +#include "qmldocument.h" +#include "qmljsast_p.h" +#include "qmljslexer_p.h" +#include "qmljsparser_p.h" +#include "qmljsengine_p.h" +#include "qmljsnodepool_p.h" + +using namespace QmlEditor; +using namespace QmlJS; + +QmlDocument::QmlDocument(const QString &fileName) + : _engine(0) + , _pool(0) + , _program(0) + , _fileName(fileName) + , _parsedCorrectly(false) +{ + const int slashIdx = fileName.lastIndexOf('/'); + if (slashIdx != -1) + _path = fileName.left(slashIdx); + + if (fileName.toLower().endsWith(".qml")) + _componentName = fileName.mid(slashIdx + 1, fileName.size() - (slashIdx + 1) - 4); +} + +QmlDocument::~QmlDocument() +{ + if (_engine) + delete _engine; + + if (_pool) + delete _pool; + + qDeleteAll(_ids.values()); +} + +QmlDocument::Ptr QmlDocument::create(const QString &fileName) +{ + QmlDocument::Ptr doc(new QmlDocument(fileName)); + return doc; +} + +AST::UiProgram *QmlDocument::program() const +{ + return _program; +} + +QList<DiagnosticMessage> QmlDocument::diagnosticMessages() const +{ + return _diagnosticMessages; +} + +QString QmlDocument::source() const +{ + return _source; +} + +void QmlDocument::setSource(const QString &source) +{ + _source = source; +} + +bool QmlDocument::parse() +{ + Q_ASSERT(! _engine); + Q_ASSERT(! _pool); + Q_ASSERT(! _program); + + _engine = new Engine(); + _pool = new NodePool(_fileName, _engine); + _ids.clear(); + + Lexer lexer(_engine); + Parser parser(_engine); + + lexer.setCode(_source, /*line = */ 1); + + _parsedCorrectly = parser.parse(); + _program = parser.ast(); + _diagnosticMessages = parser.diagnosticMessages(); + + if (_parsedCorrectly && _program) { + Internal::IdCollector collect; + _ids = collect(_fileName, _program); + } + + return _parsedCorrectly; +} + +Snapshot::Snapshot() +{ +} + +Snapshot::~Snapshot() +{ +} + +void Snapshot::insert(const QmlDocument::Ptr &document) +{ + QMap<QString, QmlDocument::Ptr>::insert(document->fileName(), document); +} + +QmlDocument::PtrList Snapshot::importedDocuments(const QmlDocument::Ptr &doc, const QString &importPath) const +{ + QmlDocument::PtrList result; + + const QString docPath = doc->path() + '/' + importPath; + + foreach (QmlDocument::Ptr candidate, *this) { + if (candidate == doc) + continue; + + if (candidate->path() == doc->path() || candidate->path() == docPath) + result.append(candidate); + } + + return result; +} + +QMap<QString, QmlDocument::Ptr> Snapshot::componentsDefinedByImportedDocuments(const QmlDocument::Ptr &doc, const QString &importPath) const +{ + QMap<QString, QmlDocument::Ptr> result; + + const QString docPath = doc->path() + '/' + importPath; + + foreach (QmlDocument::Ptr candidate, *this) { + if (candidate == doc) + continue; + + if (candidate->path() == doc->path() || candidate->path() == docPath) + result.insert(candidate->componentName(), candidate); + } + + return result; +} diff --git a/src/plugins/qmldesigner/core/filemanager/qmldocument.h b/src/plugins/qmldesigner/core/filemanager/qmldocument.h new file mode 100644 index 0000000000..4e712d8327 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/qmldocument.h @@ -0,0 +1,109 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ +#ifndef QMLDOCUMENT_H +#define QMLDOCUMENT_H + +#include <corelib_global.h> + +#include <QtCore/QList> +#include <QtCore/QMap> +#include <QtCore/QPair> +#include <QtCore/QSharedPointer> +#include <QtCore/QString> + +#include "qmleditor_global.h" +#include "qmljsengine_p.h" +#include "qmljsastfwd_p.h" +#include "qmlsymbol.h" + +namespace QmlEditor { + +class CORESHARED_EXPORT QmlDocument +{ +public: + typedef QSharedPointer<QmlDocument> Ptr; + typedef QList<QmlDocument::Ptr> PtrList; + typedef QMap<QString, QmlIdSymbol*> IdTable; + +protected: + QmlDocument(const QString &fileName); + +public: + ~QmlDocument(); + + static QmlDocument::Ptr create(const QString &fileName); + + QmlJS::AST::UiProgram *program() const; + QList<QmlJS::DiagnosticMessage> diagnosticMessages() const; + + QString source() const; + void setSource(const QString &source); + + bool parse(); + + bool isParsedCorrectly() const + { return _parsedCorrectly; } + + IdTable ids() const { return _ids; } + + QString fileName() const { return _fileName; } + QString path() const { return _path; } + QString componentName() const { return _componentName; } + +private: + QmlJS::Engine *_engine; + QmlJS::NodePool *_pool; + QmlJS::AST::UiProgram *_program; + QList<QmlJS::DiagnosticMessage> _diagnosticMessages; + QString _fileName; + QString _path; + QString _componentName; + QString _source; + bool _parsedCorrectly; + IdTable _ids; +}; + +class CORESHARED_EXPORT Snapshot: public QMap<QString, QmlDocument::Ptr> +{ +public: + Snapshot(); + ~Snapshot(); + + void insert(const QmlDocument::Ptr &document); + + QmlDocument::Ptr document(const QString &fileName) const + { return value(fileName); } + + QmlDocument::PtrList importedDocuments(const QmlDocument::Ptr &doc, const QString &importPath) const; + QMap<QString, QmlDocument::Ptr> componentsDefinedByImportedDocuments(const QmlDocument::Ptr &doc, const QString &importPath) const; +}; + +} // emd of namespace QmlEditor + +#endif // QMLDOCUMENT_H diff --git a/src/plugins/qmldesigner/core/filemanager/qmleditor_global.h b/src/plugins/qmldesigner/core/filemanager/qmleditor_global.h new file mode 100644 index 0000000000..81eacd75b4 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/qmleditor_global.h @@ -0,0 +1,41 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLEDITOR_GLOBAL_H +#define QMLEDITOR_GLOBAL_H + +#include <QtGlobal> + +#if defined(QMLEDITOR_LIBRARY) +# define QMLEDITOR_EXPORT Q_DECL_EXPORT +#else +# define QMLEDITOR_EXPORT Q_DECL_IMPORT +#endif + +#endif // QMLEDITOR_GLOBAL_H diff --git a/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp new file mode 100644 index 0000000000..530c1a9ebc --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.cpp @@ -0,0 +1,160 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <QDebug> + +#include "addarraymembervisitor.h" +#include "addobjectvisitor.h" +#include "addpropertyvisitor.h" +#include "changeobjecttypevisitor.h" +#include "changepropertyvisitor.h" +#include "moveobjectvisitor.h" +#include "moveobjectbeforeobjectvisitor.h" +#include "qmlrefactoring.h" +#include "removepropertyvisitor.h" +#include "removeuiobjectmembervisitor.h" + +using namespace QmlEditor; +using namespace QmlEditor::Internal; + +QmlRefactoring::QmlRefactoring(const QmlDocument::Ptr &doc, QmlDesigner::TextModifier &modifier, const QStringList &propertyOrder): + qmlDocument(doc), + textModifier(&modifier), + m_propertyOrder(propertyOrder) +{ +} + +bool QmlRefactoring::reparseDocument() +{ + const QString newSource = textModifier->text(); + +// qDebug() << "QmlRefactoring::reparseDocument() new QML source:" << newSource; + + QmlEditor::QmlDocument::Ptr tmpDocument(QmlEditor::QmlDocument::create("<ModelToTextMerger>")); + tmpDocument->setSource(newSource); + + if (tmpDocument->parse()) { + qmlDocument = tmpDocument; + return true; + } else { + qWarning() << "*** Possible problem: QML file wasn't parsed correctly."; + qDebug() << "*** QML text:" << textModifier->text(); + return false; + } +} + +bool QmlRefactoring::changeImports(const QSet<QmlDesigner::Import> &/*addedImports*/, const QSet<QmlDesigner::Import> &/*removedImports*/) +{ +// ChangeImportsVisitor visit(*textModifier, addedImports, removedImports, qmlDocument->source()); +// visit(qmlDocument->program()); + return false; +} + +bool QmlRefactoring::addToArrayMemberList(int parentLocation, const QString &propertyName, const QString &content) +{ + Q_ASSERT(parentLocation >= 0); + + AddArrayMemberVisitor visit(*textModifier, (quint32) parentLocation, propertyName, content); + visit.setConvertObjectBindingIntoArrayBinding(true); + return visit(qmlDocument->program()); +} + +bool QmlRefactoring::addToObjectMemberList(int parentLocation, const QString &content) +{ + Q_ASSERT(parentLocation >= 0); + + AddObjectVisitor visit(*textModifier, (quint32) parentLocation, content, m_propertyOrder); + return visit(qmlDocument->program()); +} + +bool QmlRefactoring::addProperty(int parentLocation, const QString &name, const QString &value, PropertyType propertyType) +{ + Q_ASSERT(parentLocation >= 0); + + AddPropertyVisitor visit(*textModifier, (quint32) parentLocation, name, value, propertyType, m_propertyOrder); + return visit(qmlDocument->program()); +} + +bool QmlRefactoring::changeProperty(int parentLocation, const QString &name, const QString &value, PropertyType propertyType) +{ + Q_ASSERT(parentLocation >= 0); + + ChangePropertyVisitor visit(*textModifier, (quint32) parentLocation, name, value, propertyType); + return visit(qmlDocument->program()); +} + +bool QmlRefactoring::changeObjectType(int nodeLocation, const QString &newType) +{ + Q_ASSERT(nodeLocation >= 0); + Q_ASSERT(!newType.isEmpty()); + + ChangeObjectTypeVisitor visit(*textModifier, (quint32) nodeLocation, newType); + return visit(qmlDocument->program()); +} + +bool QmlRefactoring::moveObject(int objectLocation, const QString &targetPropertyName, bool targetIsArrayBinding, int targetParentObjectLocation) +{ + Q_ASSERT(objectLocation >= 0); + Q_ASSERT(targetParentObjectLocation >= 0); + + MoveObjectVisitor visit(*textModifier, (quint32) objectLocation, targetPropertyName, targetIsArrayBinding, (quint32) targetParentObjectLocation, m_propertyOrder); + return visit(qmlDocument->program()); +} + +bool QmlRefactoring::moveObjectBeforeObject(int movingObjectLocation, int beforeObjectLocation) +{ + Q_ASSERT(movingObjectLocation >= 0); + Q_ASSERT(beforeObjectLocation >= -1); + + if (beforeObjectLocation == -1) { + MoveObjectBeforeObjectVisitor visit(*textModifier, movingObjectLocation); + return visit(qmlDocument->program()); + } else { + MoveObjectBeforeObjectVisitor visit(*textModifier, movingObjectLocation, beforeObjectLocation); + return visit(qmlDocument->program()); + } + return false; +} + +bool QmlRefactoring::removeObject(int nodeLocation) +{ + Q_ASSERT(nodeLocation >= 0); + + RemoveUIObjectMemberVisitor visit(*textModifier, (quint32) nodeLocation); + return visit(qmlDocument->program()); +} + +bool QmlRefactoring::removeProperty(int parentLocation, const QString &name) +{ + Q_ASSERT(parentLocation >= 0); + Q_ASSERT(!name.isEmpty()); + + RemovePropertyVisitor visit(*textModifier, (quint32) parentLocation, name); + return visit(qmlDocument->program()); +} diff --git a/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h new file mode 100644 index 0000000000..9739230aa3 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/qmlrefactoring.h @@ -0,0 +1,80 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLREFACTORING_H +#define QMLREFACTORING_H + +#include <import.h> +#include <textmodifier.h> +#include <filemanager/qmldocument.h> +#include <QSet> +#include <QString> + +namespace QmlEditor { + +class QmlRefactoring +{ + QmlRefactoring(const QmlRefactoring &); + QmlRefactoring &operator=(const QmlRefactoring &); + +public: + enum PropertyType { + ArrayBinding = 1, + ObjectBinding = 2, + ScriptBinding = 3 + }; + +public: + QmlRefactoring(const QmlDocument::Ptr &doc, QmlDesigner::TextModifier &modifier, const QStringList &propertyOrder); + + bool reparseDocument(); + + bool changeImports(const QSet<QmlDesigner::Import> &addedImports, const QSet<QmlDesigner::Import> &removedImports); + + bool addToArrayMemberList(int parentLocation, const QString &propertyName, const QString &content); + bool addToObjectMemberList(int parentLocation, const QString &content); + bool addProperty(int parentLocation, const QString &name, const QString &value, PropertyType propertyType); + bool changeProperty(int parentLocation, const QString &name, const QString &value, PropertyType propertyType); + bool changeObjectType(int nodeLocation, const QString &newType); + + bool moveObject(int objectLocation, const QString &targetPropertyName, bool targetIsArray, int targetParentObjectLocation); + bool moveObjectBeforeObject(int movingObjectLocation, int beforeObjectLocation); + + bool removeObject(int nodeLocation); + bool removeProperty(int parentLocation, const QString &name); + +private: + QmlDocument::Ptr qmlDocument; + QmlDesigner::TextModifier *textModifier; + QStringList m_propertyOrder; +}; + +} // namespace QmlEditor + +#endif // QMLREFACTORING_H diff --git a/src/plugins/qmldesigner/core/filemanager/qmlrewriter.cpp b/src/plugins/qmldesigner/core/filemanager/qmlrewriter.cpp new file mode 100644 index 0000000000..3d10930685 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/qmlrewriter.cpp @@ -0,0 +1,317 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <QDebug> +#include <QTextBlock> + +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +#include "qmlrewriter.h" + +#include <typeinfo> + +using namespace QmlJS; +using namespace QmlJS::AST; +using namespace QmlEditor::Internal; + +QMLRewriter::QMLRewriter(QmlDesigner::TextModifier &textModifier): + m_textModifier(&textModifier), + m_didRewriting(false) +{ +} + +bool QMLRewriter::operator()(QmlJS::AST::UiProgram *ast) +{ + setDidRewriting(false); + + Node::accept(ast, this); + + return didRewriting(); +} + +void QMLRewriter::replace(int offset, int length, const QString &text) +{ + m_textModifier->replace(offset, length, text); +} + +void QMLRewriter::move(const QmlDesigner::TextModifier::MoveInfo &moveInfo) +{ + m_textModifier->move(moveInfo); +} + +QString QMLRewriter::textBetween(int startPosition, int endPosition) const +{ + return m_textModifier->text().mid(startPosition, endPosition - startPosition); +} + +QString QMLRewriter::textAt(const QmlJS::AST::SourceLocation &location) const +{ + return m_textModifier->text().mid(location.offset, location.length); +} + +unsigned QMLRewriter::calculateIndentDepth(const SourceLocation &position) const +{ + QTextDocument *doc = m_textModifier->textDocument(); + QTextCursor tc(doc); + tc.setPosition(position.offset); + const int lineOffset = tc.block().position(); + unsigned indentDepth = 0; + + forever { + const QChar ch = doc->characterAt(lineOffset + indentDepth); + + if (ch.isNull() || !ch.isSpace()) + break; + else + ++indentDepth; + } + + return indentDepth; +} + +QString QMLRewriter::addIndentation(const QString &text, unsigned depth) +{ + const QString indentation(depth, QLatin1Char(' ')); + + if (text.isEmpty()) + return indentation; + + const QLatin1Char lineSep('\n'); + const QStringList lines = text.split(lineSep); + QString result; + + for (int i = 0; i < lines.size(); ++i) { + if (i > 0) + result += lineSep; + const QString &line = lines.at(i); + if (!line.isEmpty()) { + result += indentation; + result += line; + } + } + + return result; +} + +QString QMLRewriter::removeIndentationFromLine(const QString &text, int depth) +{ + int charsToRemove = 0; + for (int i = 0; i < depth && i < text.length(); ++i) { + if (text.at(i).isSpace()) + charsToRemove++; + else + break; + } + + if (charsToRemove == 0) + return text; + else + return text.mid(charsToRemove); +} + +QString QMLRewriter::removeIndentation(const QString &text, unsigned depth) +{ + const QLatin1Char lineSep('\n'); + const QStringList lines = text.split(lineSep); + QString result; + + for (int i = 0; i < lines.size(); ++i) { + if (i > 0) + result += lineSep; + result += removeIndentationFromLine(lines.at(i), depth); + } + + return result; +} + +QmlJS::AST::SourceLocation QMLRewriter::calculateLocation(QmlJS::AST::UiQualifiedId *id) +{ + Q_ASSERT(id != 0); + + const SourceLocation startLocation = id->identifierToken; + + UiQualifiedId *nextId = id; + while (nextId->next) { + nextId = nextId->next; + } + + const SourceLocation endLocation = nextId->identifierToken; + + return SourceLocation(startLocation.offset, endLocation.end() - startLocation.offset); +} + +bool QMLRewriter::isMissingSemicolon(QmlJS::AST::UiObjectMember *member) +{ + UiScriptBinding *binding = AST::cast<UiScriptBinding *>(member); + if (binding) + return isMissingSemicolon(binding->statement); + else + return false; +} + +bool QMLRewriter::isMissingSemicolon(QmlJS::AST::Statement *stmt) +{ + if (ExpressionStatement *eStmt = AST::cast<ExpressionStatement *>(stmt)) { + return !eStmt->semicolonToken.isValid(); + } else if (IfStatement *iStmt = AST::cast<IfStatement *>(stmt)) { + if (iStmt->elseToken.isValid()) + return isMissingSemicolon(iStmt->ko); + else + return isMissingSemicolon(iStmt->ok); + } else if (DebuggerStatement *dStmt = AST::cast<DebuggerStatement *>(stmt)) { + return !dStmt->semicolonToken.isValid(); + } else { + return false; + } +} + +QString QMLRewriter::flatten(UiQualifiedId *first) +{ + QString flatId; + + for (UiQualifiedId* current = first; current; current = current->next) { + if (current != first) + flatId += '.'; + + flatId += current->name->asString(); + } + + return flatId; +} + +bool QMLRewriter::includeSurroundingWhitespace(int &start, int &end) const +{ + QTextDocument *doc = m_textModifier->textDocument(); + bool includeStartingWhitespace = true; + bool paragraphFound = false; + + if (end >= 0) { + QChar c = doc->characterAt(end); + while (c.isSpace()) { + ++end; + + if (c == QChar::ParagraphSeparator) { + paragraphFound = true; + break; + } else if (end == doc->characterCount()) { + break; + } + + c = doc->characterAt(end); + } + + includeStartingWhitespace = paragraphFound; + } + + if (includeStartingWhitespace) { + while (start > 0) { + const QChar c = doc->characterAt(start - 1); + + if (!c.isSpace()) + break; + else if (c == QChar::ParagraphSeparator) + break; + + --start; + } + } + + return paragraphFound; +} + +void QMLRewriter::includeLeadingEmptyLine(int &start) const +{ + QTextDocument *doc = textModifier()->textDocument(); + + if (start == 0) + return; + + if (doc->characterAt(start - 1) != QChar::ParagraphSeparator) + return; + + QTextCursor tc(doc); + tc.setPosition(start); + const int blockNr = tc.blockNumber(); + if (blockNr == 0) + return; + + const QTextBlock prevBlock = tc.block().previous(); + const QString trimmedPrevBlockText = prevBlock.text().trimmed(); + if (!trimmedPrevBlockText.isEmpty()) + return; + + start = prevBlock.position(); +} + +UiObjectMemberList *QMLRewriter::searchMemberToInsertAfter(UiObjectMemberList *members, const QString &propertyName, const QStringList &propertyOrder) +{ + if (!members) + return 0; // empty members + + QHash<QString, UiObjectMemberList *> orderedMembers; + + for (UiObjectMemberList *iter = members; iter; iter = iter->next) { + UiObjectMember *member = iter->member; + + if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(member)) + orderedMembers[flatten(arrayBinding->qualifiedId)] = iter; + else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(member)) + orderedMembers[flatten(objectBinding->qualifiedId)] = iter; + else if (cast<UiObjectDefinition*>(member)) + orderedMembers[QString::null] = iter; + else if (UiScriptBinding *scriptBinding = cast<UiScriptBinding*>(member)) + orderedMembers[flatten(scriptBinding->qualifiedId)] = iter; + else if (cast<UiPublicMember*>(member)) + orderedMembers[QLatin1String("property")] = iter; + } + + int idx = propertyOrder.indexOf(propertyName); + if (idx == -1) + idx = propertyOrder.indexOf(QString::null); + if (idx == -1) + idx = propertyOrder.size() - 1; + + for (; idx >= 0; --idx) { + const QString prop = propertyOrder.at(idx); + UiObjectMemberList *candidate = orderedMembers[prop]; + if (candidate != 0) + return candidate; + } + + return 0; +} + +void QMLRewriter::dump(const ASTPath &path) +{ + qDebug() << "AST path with" << path.size() << "node(s):"; + for (int i = 0; i < path.size(); ++i) { + qDebug() << qPrintable(QString(i + 1, QLatin1Char('-'))) << typeid(*path.at(i)).name(); + } +} diff --git a/src/plugins/qmldesigner/core/filemanager/qmlrewriter.h b/src/plugins/qmldesigner/core/filemanager/qmlrewriter.h new file mode 100644 index 0000000000..ab58a07770 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/qmlrewriter.h @@ -0,0 +1,97 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLREWRITER_H +#define QMLREWRITER_H + +#include <QtCore/QStack> +#include <QtCore/QString> + +#include <qmljsastvisitor_p.h> + +#include "textmodifier.h" + +namespace QmlEditor { +namespace Internal { + +class QMLRewriter: protected QmlJS::AST::Visitor +{ +public: + typedef QStack<QmlJS::AST::Node *> ASTPath; + +public: + QMLRewriter(QmlDesigner::TextModifier &textModifier); + + virtual bool operator()(QmlJS::AST::UiProgram *ast); + + static void dump(const ASTPath &path); + +protected: + using QmlJS::AST::Visitor::visit; + + virtual void replace(int offset, int length, const QString &text); + virtual void move(const QmlDesigner::TextModifier::MoveInfo &moveInfo); + + QString textBetween(int startPosition, int endPosition) const; + QString textAt(const QmlJS::AST::SourceLocation &location) const; + + unsigned calculateIndentDepth(const QmlJS::AST::SourceLocation &position) const; + static QString addIndentation(const QString &text, unsigned depth); + static QString removeIndentation(const QString &text, unsigned depth); + static QString removeIndentationFromLine(const QString &text, int depth); + + static QmlJS::AST::SourceLocation calculateLocation(QmlJS::AST::UiQualifiedId *id); + static bool isMissingSemicolon(QmlJS::AST::UiObjectMember *member); + static bool isMissingSemicolon(QmlJS::AST::Statement *stmt); + static QString flatten(QmlJS::AST::UiQualifiedId *first); + + QmlDesigner::TextModifier *textModifier() const + { return m_textModifier; } + + bool includeSurroundingWhitespace(int &start, int &end) const; + void includeLeadingEmptyLine(int &start) const; + + static QmlJS::AST::UiObjectMemberList *searchMemberToInsertAfter(QmlJS::AST::UiObjectMemberList *members, const QString &propertyName, const QStringList &propertyOrder); + +protected: + bool didRewriting() const + { return m_didRewriting; } + + void setDidRewriting(bool didRewriting) + { m_didRewriting = didRewriting; } + +private: + QmlDesigner::TextModifier *m_textModifier; + bool m_didRewriting; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // QMLREWRITER_H diff --git a/src/plugins/qmldesigner/core/filemanager/qmlsymbol.cpp b/src/plugins/qmldesigner/core/filemanager/qmlsymbol.cpp new file mode 100644 index 0000000000..baa1c1195a --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/qmlsymbol.cpp @@ -0,0 +1,116 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include "qmljsast_p.h" +#include "qmlsymbol.h" + +using namespace QmlEditor; +using namespace QmlJS; +using namespace QmlJS::AST; + +QmlSymbol::~QmlSymbol() +{ +} + +bool QmlSymbol::isBuildInSymbol() const +{ return asBuildInSymbol() != 0; } + +bool QmlSymbol::isSymbolFromFile() const +{ return asSymbolFromFile() != 0; } + +bool QmlSymbol::isIdSymbol() const +{ return asIdSymbol() != 0; } + +QmlBuildInSymbol const *QmlSymbol::asBuildInSymbol() const +{ return 0; } + +QmlSymbolFromFile const *QmlSymbol::asSymbolFromFile() const +{ return 0; } + +QmlIdSymbol const *QmlSymbol::asIdSymbol() const +{ return 0; } + +QmlBuildInSymbol::~QmlBuildInSymbol() +{} + +QmlBuildInSymbol const* QmlBuildInSymbol::asBuildInSymbol() const +{ return this; } + +QmlSymbolFromFile::QmlSymbolFromFile(const QString &fileName, QmlJS::AST::UiObjectMember *node): + _fileName(fileName), + _node(node) +{} + +QmlSymbolFromFile::~QmlSymbolFromFile() +{} + +const QmlSymbolFromFile *QmlSymbolFromFile::asSymbolFromFile() const +{ return this; } + +int QmlSymbolFromFile::line() const +{ return _node->firstSourceLocation().startLine; } + +int QmlSymbolFromFile::column() const +{ return _node->firstSourceLocation().startColumn; } + +QmlIdSymbol::QmlIdSymbol(const QString &fileName, QmlJS::AST::UiScriptBinding *idNode, const QmlSymbolFromFile &parentNode): + QmlSymbolFromFile(fileName, idNode), + _parentNode(parentNode) +{} + +QmlIdSymbol::~QmlIdSymbol() +{} + +QmlIdSymbol const *QmlIdSymbol::asIdSymbol() const +{ return this; } + +int QmlIdSymbol::line() const +{ return idNode()->statement->firstSourceLocation().startLine; } + +int QmlIdSymbol::column() const +{ return idNode()->statement->firstSourceLocation().startColumn; } + +QmlJS::AST::UiScriptBinding *QmlIdSymbol::idNode() const +{ return cast<UiScriptBinding*>(node()); } + +QmlPropertyDefinitionSymbol::QmlPropertyDefinitionSymbol(const QString &fileName, QmlJS::AST::UiPublicMember *propertyNode): + QmlSymbolFromFile(fileName, propertyNode) +{} + +QmlPropertyDefinitionSymbol::~QmlPropertyDefinitionSymbol() +{} + +int QmlPropertyDefinitionSymbol::line() const +{ return propertyNode()->identifierToken.startLine; } + +int QmlPropertyDefinitionSymbol::column() const +{ return propertyNode()->identifierToken.startColumn; } + +QmlJS::AST::UiPublicMember *QmlPropertyDefinitionSymbol::propertyNode() const +{ return cast<UiPublicMember*>(node()); } diff --git a/src/plugins/qmldesigner/core/filemanager/qmlsymbol.h b/src/plugins/qmldesigner/core/filemanager/qmlsymbol.h new file mode 100644 index 0000000000..1c1aa21192 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/qmlsymbol.h @@ -0,0 +1,121 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef QMLSYMBOL_H +#define QMLSYMBOL_H + +#include <QString> + +#include "qmljsastfwd_p.h" + +namespace QmlEditor { + +class QmlSymbol +{ +public: + virtual ~QmlSymbol() = 0; + + bool isBuildInSymbol() const; + bool isSymbolFromFile() const; + bool isIdSymbol() const; + + virtual class QmlBuildInSymbol const *asBuildInSymbol() const; + virtual class QmlSymbolFromFile const *asSymbolFromFile() const; + virtual class QmlIdSymbol const *asIdSymbol() const; +}; + +class QmlBuildInSymbol: public QmlSymbol +{ +public: + virtual ~QmlBuildInSymbol(); + + virtual QmlBuildInSymbol const *asBuildInSymbol() const; + +private: +}; + +class QmlSymbolFromFile: public QmlSymbol +{ +public: + QmlSymbolFromFile(const QString &fileName, QmlJS::AST::UiObjectMember *node); + virtual ~QmlSymbolFromFile(); + + virtual QmlSymbolFromFile const *asSymbolFromFile() const; + + QString fileName() const + { return _fileName; } + + virtual int line() const; + virtual int column() const; + + QmlJS::AST::UiObjectMember *node() const + { return _node; } + +private: + QString _fileName; + QmlJS::AST::UiObjectMember *_node; +}; + +class QmlIdSymbol: public QmlSymbolFromFile +{ +public: + QmlIdSymbol(const QString &fileName, QmlJS::AST::UiScriptBinding *idNode, const QmlSymbolFromFile &parentNode); + virtual ~QmlIdSymbol(); + + QmlIdSymbol const *asIdSymbol() const; + + virtual int line() const; + virtual int column() const; + + QmlSymbolFromFile const *parentNode() const + { return &_parentNode; } + +private: + QmlJS::AST::UiScriptBinding *idNode() const; + +private: + QmlSymbolFromFile _parentNode; +}; + +class QmlPropertyDefinitionSymbol: public QmlSymbolFromFile +{ +public: + QmlPropertyDefinitionSymbol(const QString &fileName, QmlJS::AST::UiPublicMember *propertyNode); + virtual ~QmlPropertyDefinitionSymbol(); + + virtual int line() const; + virtual int column() const; + +private: + QmlJS::AST::UiPublicMember *propertyNode() const; +}; + +} // namespace QmlEditor + +#endif // QMLSYMBOL_H diff --git a/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp new file mode 100644 index 0000000000..5c38e7f4cd --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.cpp @@ -0,0 +1,108 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +#include "removepropertyvisitor.h" + +using namespace QmlEditor::Internal; +using namespace QmlJS; +using namespace QmlJS::AST; + +RemovePropertyVisitor::RemovePropertyVisitor(QmlDesigner::TextModifier &modifier, + quint32 parentLocation, + const QString &propertyName): + QMLRewriter(modifier), + parentLocation(parentLocation), + propertyName(propertyName) +{ +} + +bool RemovePropertyVisitor::visit(QmlJS::AST::UiObjectBinding *ast) +{ + if (ast->firstSourceLocation().offset == parentLocation) { + removeFrom(ast->initializer); + } + + return !didRewriting(); +} + +bool RemovePropertyVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) +{ + if (ast->firstSourceLocation().offset == parentLocation) { + removeFrom(ast->initializer); + } + + return !didRewriting(); +} + +void RemovePropertyVisitor::removeFrom(QmlJS::AST::UiObjectInitializer *ast) +{ + UiObjectMember *previousMember = 0, *wantedMember = 0, *nextMember = 0; + + for (UiObjectMemberList *it = ast->members; it; it = it->next) { + if (memberNameMatchesPropertyName(it->member)) { + wantedMember = it->member; + + if (it->next) + nextMember = it->next->member; + + break; + } + + previousMember = it->member; + } + + if (!wantedMember) + return; + + int start = wantedMember->firstSourceLocation().offset; + int end = wantedMember->lastSourceLocation().end(); + + includeSurroundingWhitespace(start, end); + + replace(start, end - start, QLatin1String("")); + + setDidRewriting(true); +} + +bool RemovePropertyVisitor::memberNameMatchesPropertyName(QmlJS::AST::UiObjectMember *ast) const +{ + if (UiPublicMember *publicMember = cast<UiPublicMember*>(ast)) + return publicMember->name->asString() == propertyName; + else if (UiObjectBinding *objectBinding = cast<UiObjectBinding*>(ast)) + return flatten(objectBinding->qualifiedId) == propertyName; + else if (UiScriptBinding *scriptBinding = cast<UiScriptBinding*>(ast)) + return flatten(scriptBinding->qualifiedId) == propertyName; + else if (UiArrayBinding *arrayBinding = cast<UiArrayBinding*>(ast)) + return flatten(arrayBinding->qualifiedId) == propertyName; + else + return false; +} diff --git a/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h new file mode 100644 index 0000000000..a396b8bac0 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/removepropertyvisitor.h @@ -0,0 +1,63 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef REMOVEPROPERTYVISITOR_H +#define REMOVEPROPERTYVISITOR_H + +#include <QString> + +#include "qmlrewriter.h" + +namespace QmlEditor { +namespace Internal { + +class RemovePropertyVisitor: public QMLRewriter +{ +public: + RemovePropertyVisitor(QmlDesigner::TextModifier &modifier, + quint32 parentLocation, + const QString &name); + +protected: + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + +private: + void removeFrom(QmlJS::AST::UiObjectInitializer *ast); + bool memberNameMatchesPropertyName(QmlJS::AST::UiObjectMember *ast) const; + +private: + quint32 parentLocation; + QString propertyName; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // REMOVEPROPERTYVISITOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.cpp b/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.cpp new file mode 100644 index 0000000000..bf0bcfb5ef --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.cpp @@ -0,0 +1,139 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#include <QDebug> +#include <qmljsast_p.h> +#include <qmljsengine_p.h> + +#include "removeuiobjectmembervisitor.h" + +using namespace QmlEditor; +using namespace QmlEditor::Internal; +using namespace QmlJS; +using namespace QmlJS::AST; + +RemoveUIObjectMemberVisitor::RemoveUIObjectMemberVisitor(QmlDesigner::TextModifier &modifier, + quint32 objectLocation): + QMLRewriter(modifier), + objectLocation(objectLocation) +{ +} + +bool RemoveUIObjectMemberVisitor::preVisit(Node *ast) +{ + parents.push(ast); + + return true; +} + +void RemoveUIObjectMemberVisitor::postVisit(Node *) +{ + parents.pop(); +} + +bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiPublicMember *ast) { return visitObjectMember(ast); } +bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiObjectDefinition *ast) { return visitObjectMember(ast); } +bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiSourceElement *ast) { return visitObjectMember(ast); } +bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiObjectBinding *ast) { return visitObjectMember(ast); } +bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiScriptBinding *ast) { return visitObjectMember(ast); } +bool RemoveUIObjectMemberVisitor::visit(QmlJS::AST::UiArrayBinding *ast) { return visitObjectMember(ast); } + +bool RemoveUIObjectMemberVisitor::visitObjectMember(QmlJS::AST::UiObjectMember *ast) +{ + const quint32 memberStart = ast->firstSourceLocation().offset; + + if (memberStart == objectLocation) { + // found it + int start = objectLocation; + int end = ast->lastSourceLocation().end(); + + if (UiArrayBinding *parentArray = containingArray()) { + extendToLeadingOrTrailingComma(parentArray, ast, start, end); + } else { + includeSurroundingWhitespace(start, end); + } + + includeLeadingEmptyLine(start); + replace(start, end - start, QLatin1String("")); + + setDidRewriting(true); + + return false; + } else if (ast->lastSourceLocation().end() <= objectLocation) { + // optimization: if the location of the object-to-be-removed is not inside the current member, skip any children + return false; + } else { + // only visit children if the rewriting isn't done yet. + return !didRewriting(); + } +} + +UiArrayBinding *RemoveUIObjectMemberVisitor::containingArray() const +{ + if (parents.size() > 2) { + if (cast<UiArrayMemberList*>(parents[parents.size() - 2])) { + return cast<UiArrayBinding*>(parents[parents.size() - 3]); + } + } + + return 0; +} + +void RemoveUIObjectMemberVisitor::extendToLeadingOrTrailingComma(QmlJS::AST::UiArrayBinding *parentArray, + QmlJS::AST::UiObjectMember *ast, + int &start, + int &end) const +{ + UiArrayMemberList *currentMember = 0; + for (UiArrayMemberList *it = parentArray->members; it; it = it->next) { + if (it->member == ast) { + currentMember = it; + break; + } + } + + if (!currentMember) + return; + + if (currentMember->commaToken.isValid()) { + // leading comma + start = currentMember->commaToken.offset; + if (includeSurroundingWhitespace(start, end)) + --end; + } else if (currentMember->next && currentMember->next->commaToken.isValid()) { + // trailing comma + end = currentMember->next->commaToken.end(); + includeSurroundingWhitespace(start, end); + } else { + // array with 1 element, so remove the complete binding + start = parentArray->firstSourceLocation().offset; + end = parentArray->lastSourceLocation().end(); + includeSurroundingWhitespace(start, end); + } +} diff --git a/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.h b/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.h new file mode 100644 index 0000000000..85816f197a --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/removeuiobjectmembervisitor.h @@ -0,0 +1,75 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef REMOVEUIOBJECTMEMBERVISITOR_H +#define REMOVEUIOBJECTMEMBERVISITOR_H + +#include <QStack> + +#include "qmlrewriter.h" + +namespace QmlEditor { +namespace Internal { + +class RemoveUIObjectMemberVisitor: public QMLRewriter +{ +public: + RemoveUIObjectMemberVisitor(QmlDesigner::TextModifier &modifier, + quint32 objectLocation); + +protected: + virtual bool preVisit(QmlJS::AST::Node *ast); + virtual void postVisit(QmlJS::AST::Node *); + + virtual bool visit(QmlJS::AST::UiPublicMember *ast); + virtual bool visit(QmlJS::AST::UiObjectDefinition *ast); + virtual bool visit(QmlJS::AST::UiSourceElement *ast); + virtual bool visit(QmlJS::AST::UiObjectBinding *ast); + virtual bool visit(QmlJS::AST::UiScriptBinding *ast); + virtual bool visit(QmlJS::AST::UiArrayBinding *ast); + +private: + bool visitObjectMember(QmlJS::AST::UiObjectMember *ast); + + QmlJS::AST::UiArrayBinding *containingArray() const; + + void extendToLeadingOrTrailingComma(QmlJS::AST::UiArrayBinding *parentArray, + QmlJS::AST::UiObjectMember *ast, + int &start, + int &end) const; + +private: + quint32 objectLocation; + QStack<QmlJS::AST::Node*> parents; +}; + +} // namespace Internal +} // namespace QmlEditor + +#endif // REMOVEUIOBJECTMEMBERVISITOR_H diff --git a/src/plugins/qmldesigner/core/filemanager/utils_global.h b/src/plugins/qmldesigner/core/filemanager/utils_global.h new file mode 100644 index 0000000000..a97322e5c9 --- /dev/null +++ b/src/plugins/qmldesigner/core/filemanager/utils_global.h @@ -0,0 +1,37 @@ +/************************************************************************** +** +** This file is part of Qt Creator +** +** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). +** +** Contact: Nokia Corporation (qt-info@nokia.com) +** +** Commercial Usage +** +** Licensees holding valid Qt Commercial licenses may use this file in +** accordance with the Qt Commercial License Agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and Nokia. +** +** GNU Lesser General Public License Usage +** +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 2.1 requirements +** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** If you are unsure which license is appropriate for your use, please +** contact the sales department at http://qt.nokia.com/contact. +** +**************************************************************************/ + +#ifndef UTILS_GLOBAL_H +#define UTILS_GLOBAL_H + +#include <QtCore/qglobal.h> + +#define QTCREATOR_UTILS_EXPORT + +#endif // UTILS_GLOBAL_H |