QMLJS: update to qmljsparser from Qt 5.6

Change-Id: I29a8e07b0b34aa5e8466021cbb71450687f7e11c
Reviewed-by: Tim Jenssen <tim.jenssen@theqtcompany.com>
This commit is contained in:
Tim Jenssen
2016-04-29 11:00:30 +02:00
parent 5c45e9ec34
commit c90a356be6
18 changed files with 1503 additions and 1279 deletions

View File

@@ -341,7 +341,7 @@ static inline bool isIdentifierStart(QChar ch)
// fast path for ascii
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
(ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
ch == QLatin1Char('$') || ch == QLatin1Char('_'))
ch == '$' || ch == '_')
return true;
switch (ch.category()) {
@@ -364,7 +364,7 @@ static bool isIdentifierPart(QChar ch)
if ((ch.unicode() >= 'a' && ch.unicode() <= 'z') ||
(ch.unicode() >= 'A' && ch.unicode() <= 'Z') ||
(ch.unicode() >= '0' && ch.unicode() <= '9') ||
ch == QLatin1Char('$') || ch == QLatin1Char('_') ||
ch == '$' || ch == '_' ||
ch.unicode() == 0x200c /* ZWNJ */ || ch.unicode() == 0x200d /* ZWJ */)
return true;
@@ -691,7 +691,7 @@ again:
_validTokenText = true;
_tokenText.resize(0);
startCode--;
while (startCode != _codePtr - 1)
while (startCode != _codePtr - 1)
_tokenText += *startCode++;
while (_codePtr <= _endPtr) {
@@ -879,8 +879,7 @@ again:
int Lexer::scanNumber(QChar ch)
{
if (ch != QLatin1Char('0')) {
QByteArray buf;
buf.reserve(64);
QVarLengthArray<char, 64> buf;
buf += ch.toLatin1();
QChar n = _char;
@@ -1217,12 +1216,60 @@ bool Lexer::canInsertAutomaticSemicolon(int token) const
|| _followsClosingBrace;
}
bool Lexer::scanDirectives(Directives *directives)
static const int uriTokens[] = {
QmlJSGrammar::T_IDENTIFIER,
QmlJSGrammar::T_PROPERTY,
QmlJSGrammar::T_SIGNAL,
QmlJSGrammar::T_READONLY,
QmlJSGrammar::T_ON,
QmlJSGrammar::T_BREAK,
QmlJSGrammar::T_CASE,
QmlJSGrammar::T_CATCH,
QmlJSGrammar::T_CONTINUE,
QmlJSGrammar::T_DEFAULT,
QmlJSGrammar::T_DELETE,
QmlJSGrammar::T_DO,
QmlJSGrammar::T_ELSE,
QmlJSGrammar::T_FALSE,
QmlJSGrammar::T_FINALLY,
QmlJSGrammar::T_FOR,
QmlJSGrammar::T_FUNCTION,
QmlJSGrammar::T_IF,
QmlJSGrammar::T_IN,
QmlJSGrammar::T_INSTANCEOF,
QmlJSGrammar::T_NEW,
QmlJSGrammar::T_NULL,
QmlJSGrammar::T_RETURN,
QmlJSGrammar::T_SWITCH,
QmlJSGrammar::T_THIS,
QmlJSGrammar::T_THROW,
QmlJSGrammar::T_TRUE,
QmlJSGrammar::T_TRY,
QmlJSGrammar::T_TYPEOF,
QmlJSGrammar::T_VAR,
QmlJSGrammar::T_VOID,
QmlJSGrammar::T_WHILE,
QmlJSGrammar::T_CONST,
QmlJSGrammar::T_DEBUGGER,
QmlJSGrammar::T_RESERVED_WORD,
QmlJSGrammar::T_WITH,
QmlJSGrammar::EOF_SYMBOL
};
static inline bool isUriToken(int token)
{
if (_qmlMode) {
// the directives are a Javascript-only extension.
return false;
const int *current = uriTokens;
while (*current != QmlJSGrammar::EOF_SYMBOL) {
if (*current == token)
return true;
++current;
}
return false;
}
bool Lexer::scanDirectives(Directives *directives, DiagnosticMessage *error)
{
Q_ASSERT(!_qmlMode);
lex(); // fetch the first token
@@ -1230,24 +1277,33 @@ bool Lexer::scanDirectives(Directives *directives)
return true;
do {
const int lineNumber = tokenStartLine();
const int column = tokenStartColumn();
lex(); // skip T_DOT
const int lineNumber = tokenStartLine();
if (! (_tokenKind == T_IDENTIFIER || _tokenKind == T_RESERVED_WORD))
return false; // expected a valid QML/JS directive
return true; // expected a valid QML/JS directive
const QString directiveName = tokenText();
if (! (directiveName == QLatin1String("pragma") ||
directiveName == QLatin1String("import")))
directiveName == QLatin1String("import"))) {
error->message = QCoreApplication::translate("QmlParser", "Syntax error");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false; // not a valid directive name
}
// it must be a pragma or an import directive.
if (directiveName == QLatin1String("pragma")) {
// .pragma library
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library")))
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("library"))) {
error->message = QCoreApplication::translate("QmlParser", "Syntax error");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false; // expected `library
}
// we found a .pragma library directive
directives->pragmaLibrary();
@@ -1266,22 +1322,53 @@ bool Lexer::scanDirectives(Directives *directives)
fileImport = true;
pathOrUri = tokenText();
if (!pathOrUri.endsWith(QLatin1String("js"))) {
error->message = QCoreApplication::translate("QmlParser","Imported file must be a script");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false;
}
} else if (_tokenKind == T_IDENTIFIER) {
// .import T_IDENTIFIER (. T_IDENTIFIER)* T_NUMERIC_LITERAL as T_IDENTIFIER
pathOrUri = tokenText();
lex(); // skip the first T_IDENTIFIER
for (; _tokenKind == T_DOT; lex()) {
if (lex() != T_IDENTIFIER)
while (true) {
if (!isUriToken(_tokenKind)) {
error->message = QCoreApplication::translate("QmlParser","Invalid module URI");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false;
}
pathOrUri += QLatin1Char('.');
pathOrUri += tokenText();
pathOrUri.append(tokenText());
lex();
if (tokenStartLine() != lineNumber) {
error->message = QCoreApplication::translate("QmlParser","Invalid module URI");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false;
}
if (_tokenKind != QmlJSGrammar::T_DOT)
break;
pathOrUri.append(QLatin1Char('.'));
lex();
if (tokenStartLine() != lineNumber) {
error->message = QCoreApplication::translate("QmlParser","Invalid module URI");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false;
}
}
if (_tokenKind != T_NUMERIC_LITERAL)
if (_tokenKind != T_NUMERIC_LITERAL) {
error->message = QCoreApplication::translate("QmlParser","Module import requires a version");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false; // expected the module version number
}
version = tokenText();
}
@@ -1289,22 +1376,51 @@ bool Lexer::scanDirectives(Directives *directives)
//
// recognize the mandatory `as' followed by the module name
//
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("as")))
if (! (lex() == T_IDENTIFIER && tokenText() == QLatin1String("as") && tokenStartLine() == lineNumber)) {
if (fileImport)
error->message = QCoreApplication::translate("QmlParser", "File import requires a qualifier");
else
error->message = QCoreApplication::translate("QmlParser", "Module import requires a qualifier");
if (tokenStartLine() != lineNumber) {
error->loc.startLine = lineNumber;
error->loc.startColumn = column;
} else {
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
}
return false; // expected `as'
}
if (lex() != T_IDENTIFIER)
if (lex() != T_IDENTIFIER || tokenStartLine() != lineNumber) {
if (fileImport)
error->message = QCoreApplication::translate("QmlParser", "File import requires a qualifier");
else
error->message = QCoreApplication::translate("QmlParser", "Module import requires a qualifier");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false; // expected module name
}
const QString module = tokenText();
if (!module.at(0).isUpper()) {
error->message = QCoreApplication::translate("QmlParser","Invalid import qualifier");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false;
}
if (fileImport)
directives->importFile(pathOrUri, module);
directives->importFile(pathOrUri, module, lineNumber, column);
else
directives->importModule(pathOrUri, version, module);
directives->importModule(pathOrUri, version, module, lineNumber, column);
}
if (tokenStartLine() != lineNumber)
if (tokenStartLine() != lineNumber) {
error->message = QCoreApplication::translate("QmlParser", "Syntax error");
error->loc.startLine = tokenStartLine();
error->loc.startColumn = tokenStartColumn();
return false; // the directives cannot span over multiple lines
}
// fetch the first token after the .pragma/.import directive
lex();