diff options
author | Roberto Raggi <roberto.raggi@nokia.com> | 2011-12-06 14:09:22 +0100 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-12-06 15:29:39 +0100 |
commit | e7d1a74d994445749275e8e5cb88b0a21938bb09 (patch) | |
tree | 6dde884c6079e8a448a4f645b144fd252b4e3d6e /tools | |
parent | e7281e2dc89ca934d3c1e89484d279331a96de71 (diff) |
Improve parsing of escape characters and regexp literals.
That is, in QML/JS you can escape characters in identifiers, e.g.
var c\u0061se = 25
declares a variable called `case' with value 25. In such cases
qmlmin needs to preserve the escape sequence in the declaration.
Also, fix possible errors when pasting keywords after regexp literals.
The minifier needs to preserve the whitespace character after the
regexp delimiter, e.g.
/x/instanceof blah
without the white space after the regexp, the `i' of `instanceof'
is parsed as a regexp flag.
Change-Id: I5f426ac62949e34d092d4fdb0a41243de8ff2236
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
Diffstat (limited to 'tools')
-rw-r--r-- | tools/qmlmin/main.cpp | 47 |
1 files changed, 34 insertions, 13 deletions
diff --git a/tools/qmlmin/main.cpp b/tools/qmlmin/main.cpp index ebfc5851dd..b1aeab6168 100644 --- a/tools/qmlmin/main.cpp +++ b/tools/qmlmin/main.cpp @@ -182,6 +182,13 @@ protected: *restOfRegExp += QLatin1Char('i'); if (flags & Multiline) *restOfRegExp += QLatin1Char('m'); + + if (regExpFlags() == 0) { + // Add an extra space after the regexp literal delimiter (aka '/'). + // This will avoid possible problems when pasting tokens like `instanceof' + // after the regexp literal. + *restOfRegExp += QLatin1Char(' '); + } return true; } }; @@ -201,6 +208,7 @@ public: protected: bool parse(int startToken); + void escape(const QChar &ch, QString *out); }; Minify::Minify() @@ -213,6 +221,20 @@ QString Minify::minifiedCode() const return _minifiedCode; } +void Minify::escape(const QChar &ch, QString *out) +{ + out->append(QLatin1String("\\u")); + const QString hx = QString::number(ch.unicode(), 16); + switch (hx.length()) { + case 1: out->append(QLatin1String("000")); break; + case 2: out->append(QLatin1String("00")); break; + case 3: out->append(QLatin1String("0")); break; + case 4: break; + default: Q_ASSERT(!"unreachable"); + } + out->append(hx); +} + bool Minify::parse(int startToken) { int yyaction = 0; @@ -288,25 +310,24 @@ bool Minify::parse(int startToken) _minifiedCode += QLatin1Char('0'); } else if (yytoken == T_IDENTIFIER) { + QString identifier = yytokentext; + + if (classify(identifier.constData(), identifier.size(), qmlMode()) != T_IDENTIFIER) { + // the unescaped identifier is a keyword. In this case just replace + // the last character of the identifier with it escape sequence. + const QChar ch = identifier.at(identifier.length() - 1); + identifier.chop(1); + escape(ch, &identifier); + } + if (isIdentChar(lastChar)) _minifiedCode += QLatin1Char(' '); - foreach (const QChar &ch, yytokentext) { + foreach (const QChar &ch, identifier) { if (isIdentChar(ch)) _minifiedCode += ch; else { - _minifiedCode += QLatin1String("\\u"); - const QString hx = QString::number(ch.unicode(), 16); - switch (hx.length()) { - case 1: _minifiedCode += QLatin1String("000"); break; - case 2: _minifiedCode += QLatin1String("00"); break; - case 3: _minifiedCode += QLatin1String("0"); break; - case 4: break; - default: - std::cerr << "qmlmin: invalid unicode sequence" << std::endl; - return false; - } - _minifiedCode += hx; + escape(ch, &_minifiedCode); } } |