diff options
author | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-05-11 12:14:50 (GMT) |
---|---|---|
committer | Aaron Kennedy <aaron.kennedy@nokia.com> | 2009-05-11 12:14:50 (GMT) |
commit | 61f8c6f4d6af1a2e73c918b43da8f25871b254b7 (patch) | |
tree | 39e472b03d3d6c642ad6723851717609ce017c3c | |
parent | edadc4df70324d3c4a875795d0032e129206f44b (diff) | |
download | Qt-61f8c6f4d6af1a2e73c918b43da8f25871b254b7.zip Qt-61f8c6f4d6af1a2e73c918b43da8f25871b254b7.tar.gz Qt-61f8c6f4d6af1a2e73c918b43da8f25871b254b7.tar.bz2 |
Remove some XML'isms from the parser/compiler interface
-rw-r--r-- | src/declarative/qml/qmlcompiler.cpp | 43 | ||||
-rw-r--r-- | src/declarative/qml/qmlcompiler_p.h | 1 | ||||
-rw-r--r-- | src/declarative/qml/qmlcustomparser.cpp | 2 | ||||
-rw-r--r-- | src/declarative/qml/qmldom.cpp | 4 | ||||
-rw-r--r-- | src/declarative/qml/qmlparser.cpp | 92 | ||||
-rw-r--r-- | src/declarative/qml/qmlparser_p.h | 44 | ||||
-rw-r--r-- | src/declarative/qml/qmlscriptparser.cpp | 79 |
7 files changed, 183 insertions, 82 deletions
diff --git a/src/declarative/qml/qmlcompiler.cpp b/src/declarative/qml/qmlcompiler.cpp index a40b7c8..c547d31 100644 --- a/src/declarative/qml/qmlcompiler.cpp +++ b/src/declarative/qml/qmlcompiler.cpp @@ -192,16 +192,6 @@ bool QmlCompiler::isValidId(const QString &val) return true; } -/*! - Returns true if \a str is a valid binding string, false otherwise. - - Valid binding strings are those enclosed in braces ({}). -*/ -bool QmlCompiler::isBinding(const QString &str) -{ - return str.startsWith(QLatin1Char('{')) && str.endsWith(QLatin1Char('}')); -} - /*! Returns true if property name \a name refers to an attached property, false otherwise. @@ -671,7 +661,7 @@ bool QmlCompiler::compileComponent(Object *obj, int ctxt) COMPILE_CHECK(compileComponentFromRoot(root, ctxt)); if (idProp && idProp->values.count()) { - QString val = idProp->values.at(0)->primitive; + QString val = idProp->values.at(0)->primitive(); if (!isValidId(val)) COMPILE_EXCEPTION("Invalid id property value"); @@ -766,13 +756,10 @@ bool QmlCompiler::compileSignal(Property *prop, Object *obj) return rv; } else { - QString script = prop->values.at(0)->primitive.trimmed(); + QString script = prop->values.at(0)->value.asScript().trimmed(); if (script.isEmpty()) return true; - if (isBinding(script)) - COMPILE_EXCEPTION("Cannot assign binding to signal property"); - int idx = output->indexForString(script); int pr = output->indexForByteArray(prop->name); @@ -887,7 +874,7 @@ bool QmlCompiler::compileIdProperty(QmlParser::Property *prop, if (prop->values.count() == 1) { if (prop->values.at(0)->object) COMPILE_EXCEPTION("Cannot assign an object as an id"); - QString val = prop->values.at(0)->primitive; + QString val = prop->values.at(0)->primitive(); if (!isValidId(val)) COMPILE_EXCEPTION(val << "is not a valid id"); if (ids.contains(val)) @@ -1031,11 +1018,12 @@ bool QmlCompiler::compileListProperty(QmlParser::Property *prop, assign.assignObject.property = output->indexForByteArray(prop->name); assign.assignObject.castValue = 0; output->bytecode << assign; - } else if (isBinding(v->primitive)) { + } else if (v->value.isScript()) { if (assignedBinding) COMPILE_EXCEPTION("Can only assign one binding to lists"); - compileBinding(v->primitive, prop, ctxt, obj->metaObject(), v->location.start.line); + compileBinding(v->value.asScript(), prop, ctxt, + obj->metaObject(), v->location.start.line); v->type = Value::PropertyBinding; } else { COMPILE_EXCEPTION("Cannot assign primitives to lists"); @@ -1186,9 +1174,10 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, QmlParser::Value *v, int ctxt) { - if (isBinding(v->primitive)) { + if (v->value.isScript()) { - compileBinding(v->primitive, prop, ctxt, obj->metaObject(), v->location.start.line); + compileBinding(v->value.asScript(), prop, ctxt, obj->metaObject(), + v->location.start.line); v->type = Value::PropertyBinding; @@ -1199,8 +1188,9 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, bool doassign = true; if (prop->index != -1) { + QString value = v->primitive(); StoreInstructionResult r = - generateStoreInstruction(*output, assign, obj->metaObject()->property(prop->index), prop->index, -1, &v->primitive); + generateStoreInstruction(*output, assign, obj->metaObject()->property(prop->index), prop->index, -1, &value); if (r == Ok) { doassign = false; @@ -1208,10 +1198,10 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, //### we are restricted to a rather generic message here. If we can find a way to move // the exception into generateStoreInstruction we could potentially have better messages. // (the problem is that both compile and run exceptions can be generated, though) - COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive << "to property" << obj->metaObject()->property(prop->index).name()); + COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive() << "to property" << obj->metaObject()->property(prop->index).name()); doassign = false; } else if (r == ReadOnly) { - COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive << "to the read-only property" << obj->metaObject()->property(prop->index).name()); + COMPILE_EXCEPTION2(v, "Cannot assign value" << v->primitive() << "to the read-only property" << obj->metaObject()->property(prop->index).name()); } else { doassign = true; } @@ -1226,7 +1216,7 @@ bool QmlCompiler::compilePropertyLiteralAssignment(QmlParser::Property *prop, output->indexForByteArray(prop->name); } assign.assignConstant.constant = - output->indexForString(v->primitive); + output->indexForString(v->primitive()); } output->bytecode << assign; @@ -1335,12 +1325,9 @@ bool QmlCompiler::compileDynamicMeta(QmlParser::Object *obj) return true; } -void QmlCompiler::compileBinding(const QString &str, QmlParser::Property *prop, +void QmlCompiler::compileBinding(const QString &bind, QmlParser::Property *prop, int ctxt, const QMetaObject *mo, qint64 line) { - Q_ASSERT(isBinding(str)); - - QString bind = str.mid(1, str.length() - 2).trimmed(); QmlBasicScript bs; bs.compile(bind.toLatin1()); diff --git a/src/declarative/qml/qmlcompiler_p.h b/src/declarative/qml/qmlcompiler_p.h index b885e7b..b122650 100644 --- a/src/declarative/qml/qmlcompiler_p.h +++ b/src/declarative/qml/qmlcompiler_p.h @@ -118,7 +118,6 @@ public: QList<QmlError> errors() const; static bool isValidId(const QString &); - static bool isBinding(const QString &); static bool isAttachedProperty(const QByteArray &); enum StoreInstructionResult { Ok, UnknownType, InvalidData, ReadOnly }; diff --git a/src/declarative/qml/qmlcustomparser.cpp b/src/declarative/qml/qmlcustomparser.cpp index 06035b0..e864df9 100644 --- a/src/declarative/qml/qmlcustomparser.cpp +++ b/src/declarative/qml/qmlcustomparser.cpp @@ -138,7 +138,7 @@ QmlCustomParserNodePrivate::fromProperty(QmlParser::Property *p) QmlCustomParserNode node = fromObject(v->object); prop.d->values << QVariant::fromValue(node); } else { - prop.d->values << QVariant::fromValue(v->primitive); + prop.d->values << QVariant::fromValue(v->primitive()); } } diff --git a/src/declarative/qml/qmldom.cpp b/src/declarative/qml/qmldom.cpp index 4e754a3..09b4a3b 100644 --- a/src/declarative/qml/qmldom.cpp +++ b/src/declarative/qml/qmldom.cpp @@ -809,7 +809,7 @@ Rect { x: 10 } */ QString QmlDomValueLiteral::literal() const { - if (d->value) return d->value->primitive; + if (d->value) return d->value->primitive(); else return QString(); } @@ -878,7 +878,7 @@ Rect { x: Other.x } QString QmlDomValueBinding::binding() const { if (d->value) - return d->value->primitive.mid(1, d->value->primitive.length() - 2); + return d->value->value.asScript(); else return QString(); } diff --git a/src/declarative/qml/qmlparser.cpp b/src/declarative/qml/qmlparser.cpp index 2bd41e2..bafdb02 100644 --- a/src/declarative/qml/qmlparser.cpp +++ b/src/declarative/qml/qmlparser.cpp @@ -233,14 +233,102 @@ void QmlParser::Value::dump(int indent) const case Value::Id: type = "Id"; break; - }; + } + + QByteArray primType; + switch(this->value.type()) { + default: + case Variant::Invalid: + primType = "Invalid"; + break; + case Variant::Boolean: + primType = "Boolean"; + break; + case Variant::Number: + primType = "Number"; + break; + case Variant::String: + primType = "String"; + break; + case Variant::Script: + primType = "Script"; + break; + } QByteArray ba(indent * 4, ' '); if (object) { qWarning() << ba.constData() << "Value (" << type << "):"; object->dump(indent + 1); } else { - qWarning() << ba.constData() << "Value (" << type << "):" << primitive; + qWarning() << ba.constData() << "Value (" << type << "):" << primType.constData() << primitive(); + } +} + +QmlParser::Variant::Variant() +: t(Invalid) {} + +QmlParser::Variant::Variant(const Variant &o) +: t(o.t), d(o.d), s(o.s) +{ +} + +QmlParser::Variant::Variant(bool v) +: t(Boolean), b(v) +{ +} + +QmlParser::Variant::Variant(double v) +: t(Number), d(v) +{ +} + +QmlParser::Variant::Variant(const QString &v, Type type) +: t(type), s(v) +{ + Q_ASSERT(type == String || type == Script); +} + +QmlParser::Variant &QmlParser::Variant::operator=(const Variant &o) +{ + t = o.t; + d = o.d; + s = o.s; + return *this; +} + +QmlParser::Variant::Type QmlParser::Variant::type() const +{ + return t; +} + +bool QmlParser::Variant::asBoolean() const +{ + return b; +} + +QString QmlParser::Variant::asString() const +{ + return s; +} + +double QmlParser::Variant::asNumber() const +{ + return d; +} + +QString QmlParser::Variant::asScript() const +{ + switch(type()) { + default: + case Invalid: + return QString(); + case Boolean: + return b?QLatin1String("true"):QLatin1String("false"); + case Number: + return QString::number(d); + case String: + case Script: + return s; } } diff --git a/src/declarative/qml/qmlparser_p.h b/src/declarative/qml/qmlparser_p.h index 31f8702..d67690b 100644 --- a/src/declarative/qml/qmlparser_p.h +++ b/src/declarative/qml/qmlparser_p.h @@ -152,6 +152,45 @@ namespace QmlParser void dump(int = 0) const; }; + class Variant + { + public: + enum Type { + Invalid, + Boolean, + Number, + String, + Script + }; + + Variant(); + Variant(const Variant &); + Variant(bool); + Variant(double); + Variant(const QString &, Type = String); + Variant &operator=(const Variant &); + + Type type() const; + + bool isBoolean() const { return type() == Boolean; } + bool isNumber() const { return type() == Number; } + bool isString() const { return type() == String; } + bool isScript() const { return type() == Script; } + + bool asBoolean() const; + QString asString() const; + double asNumber() const; + QString asScript() const; + + private: + Type t; + union { + bool b; + double d; + }; + QString s; + }; + class Value : public QmlRefCount { public: @@ -180,8 +219,11 @@ namespace QmlParser }; Type type; + // ### Temporary + QString primitive() const { return value.asScript(); } + // Primitive value - QString primitive; + Variant value; // Object value Object *object; diff --git a/src/declarative/qml/qmlscriptparser.cpp b/src/declarative/qml/qmlscriptparser.cpp index 169e2ea..4de9e40 100644 --- a/src/declarative/qml/qmlscriptparser.cpp +++ b/src/declarative/qml/qmlscriptparser.cpp @@ -74,8 +74,8 @@ protected: AST::SourceLocation typeLocation, LocationSpan location, AST::UiObjectInitializer *initializer = 0); - QString getPrimitive(const QByteArray &propertyName, AST::ExpressionNode *expr); - void defineProperty(const QString &propertyName, const LocationSpan &location, const QString &primitive); + + QmlParser::Variant getVariant(AST::ExpressionNode *expr); LocationSpan location(AST::SourceLocation start, AST::SourceLocation end); LocationSpan location(AST::UiQualifiedId *); @@ -305,15 +305,22 @@ Object *ProcessAST::defineObjectBinding(int line, QString propertyName = asString(scriptBinding->qualifiedId); if (propertyName == QLatin1String("script")) { QString script; + if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(scriptBinding->statement)) { - script = getPrimitive("script", stmt->expression); + script = getVariant(stmt->expression).asScript(); } else { script = asString(scriptBinding->statement); } LocationSpan l = this->location(scriptBinding->statement->firstSourceLocation(), scriptBinding->statement->lastSourceLocation()); - defineProperty(QLatin1String("script"), l, script); + + _stateStack.pushProperty(QLatin1String("script"), l); + Value *value = new Value; + value->value = QmlParser::Variant(script); + value->location = l; + currentProperty()->addValue(value); + _stateStack.pop(); } else { accept(it->member); } @@ -342,16 +349,6 @@ LocationSpan ProcessAST::location(AST::SourceLocation start, AST::SourceLocation return rv; } -void ProcessAST::defineProperty(const QString &propertyName, const LocationSpan &location, const QString &primitive) -{ - _stateStack.pushProperty(propertyName, location); - Value *value = new Value; - value->primitive = primitive; - value->location = location; - currentProperty()->addValue(value); - _stateStack.pop(); -} - // UiProgram: UiImportListOpt UiObjectMemberList ; bool ProcessAST::visit(AST::UiProgram *node) { @@ -436,7 +433,7 @@ bool ProcessAST::visit(AST::UiPublicMember *node) Value *value = new Value; value->location = location(node->expression->firstSourceLocation(), node->expression->lastSourceLocation()); - value->primitive = getPrimitive("value", node->expression); + value->value = getVariant(node->expression); property.defaultValue->values << value; } @@ -480,30 +477,25 @@ bool ProcessAST::visit(AST::UiObjectBinding *node) return false; } -QString ProcessAST::getPrimitive(const QByteArray &propertyName, AST::ExpressionNode *expr) +QmlParser::Variant ProcessAST::getVariant(AST::ExpressionNode *expr) { - QString primitive; + QmlParser::Variant rv; - if (isSignalProperty(propertyName)) { - primitive = asString(expr); - } else if (propertyName == "id" && expr && expr->kind == AST::Node::Kind_IdentifierExpression) { - primitive = asString(expr); - } else if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) { + if (AST::StringLiteral *lit = AST::cast<AST::StringLiteral *>(expr)) { // hack: emulate weird XML feature that string literals are not quoted. //This needs to be fixed in the qmlcompiler once xml goes away. - primitive = lit->value->asString(); - } else if (expr->kind == AST::Node::Kind_TrueLiteral - || expr->kind == AST::Node::Kind_FalseLiteral - || expr->kind == AST::Node::Kind_NumericLiteral - ) { - primitive = asString(expr); + rv = QmlParser::Variant(lit->value->asString()); + } else if (expr->kind == AST::Node::Kind_TrueLiteral) { + rv = QmlParser::Variant(true); + } else if (expr->kind == AST::Node::Kind_FalseLiteral) { + rv = QmlParser::Variant(false); + } else if(AST::NumericLiteral *lit = AST::cast<AST::NumericLiteral *>(expr)) { + rv = QmlParser::Variant(lit->value); } else { - // create a binding - primitive += QLatin1Char('{'); - primitive += asString(expr); - primitive += QLatin1Char('}'); + rv = QmlParser::Variant(asString(expr), QmlParser::Variant::Script); } - return primitive; + + return rv; } @@ -519,25 +511,18 @@ bool ProcessAST::visit(AST::UiScriptBinding *node) } Property *prop = currentProperty(); - QString primitive; + + QmlParser::Variant primitive; if (AST::ExpressionStatement *stmt = AST::cast<AST::ExpressionStatement *>(node->statement)) { - primitive = getPrimitive(prop->name, stmt->expression); - } else if (isSignalProperty(prop->name)) { - if (AST::Block *block = AST::cast<AST::Block *>(node->statement)) { - const int start = block->lbraceToken.offset + block->rbraceToken.length; - primitive += _contents.mid(start, block->rbraceToken.offset - start); - } else { - primitive += asString(node->statement); - } + primitive = getVariant(stmt->expression); } else { // do binding - primitive += QLatin1Char('{'); - primitive += asString(node->statement); - primitive += QLatin1Char('}'); + primitive = QmlParser::Variant(asString(node->statement), + QmlParser::Variant::Script); } Value *v = new Value; - v->primitive = primitive; + v->value = primitive; v->location = location(node->statement->firstSourceLocation(), node->statement->lastSourceLocation()); @@ -616,7 +601,7 @@ bool ProcessAST::visit(AST::UiSourceElement *node) Value *value = new Value; value->location = location(node->firstSourceLocation(), node->lastSourceLocation()); - value->primitive = source; + value->value = QmlParser::Variant(source); obj->getDefaultProperty()->addValue(value); } |