Add support for QML/JS pragma directives.
authorRoberto Raggi <roberto.raggi@nokia.com>
Thu, 15 Sep 2011 14:54:33 +0000 (16:54 +0200)
committerQt by Nokia <qt-info@nokia.com>
Mon, 19 Sep 2011 10:07:46 +0000 (12:07 +0200)
The lexer can now recognize the following pragma directives:

  .pragma library
  .import <URI> <Version> as <Identifier>
  .import <file.js> as <Identifier>

Change-Id: I2c44140818f356419640266a46b5e172474819ee
Reviewed-on: http://codereview.qt-project.org/4897
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>

src/declarative/qml/parser/qdeclarativejslexer.cpp
src/declarative/qml/parser/qdeclarativejslexer_p.h

index dd74ffa..238ea8f 100644 (file)
@@ -1062,4 +1062,100 @@ bool Lexer::canInsertAutomaticSemicolon(int token) const
             || _followsClosingBrace;
 }
 
+bool Lexer::scanDirectives(Directives *directives)
+{
+    if (_qmlMode) {
+        // the directives are a Javascript-only extension.
+        return false;
+    }
+
+    lex(); // fetch the first token
+
+    if (_tokenKind != T_DOT)
+        return true;
+
+    do {
+        lex(); // skip T_DOT
+
+        const int lineNumber = tokenStartLine();
+
+        if (! (_tokenKind == T_IDENTIFIER || _tokenKind == T_RESERVED_WORD))
+            return false; // expected a valid QML/JS directive
+
+        const QString directiveName = tokenText();
+
+        if (! (directiveName == QLatin1String("pragma") ||
+               directiveName == QLatin1String("import")))
+            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")))
+                return false; // expected `library
+
+            // we found a .pragma library directive
+            directives->pragmaLibrary();
+
+        } else {
+            Q_ASSERT(directiveName == QLatin1String("import"));
+            lex(); // skip .import
+
+            QString pathOrUri;
+            QString version;
+            bool fileImport = false; // file or uri import
+
+            if (_tokenKind == T_STRING_LITERAL) {
+                // .import T_STRING_LITERAL as T_IDENTIFIER
+
+                fileImport = true;
+                pathOrUri = tokenText();
+
+            } 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)
+                        return false;
+
+                    pathOrUri += QLatin1Char('.');
+                    pathOrUri += tokenText();
+                }
+
+                if (_tokenKind != T_NUMERIC_LITERAL)
+                    return false; // expected the module version number
+
+                version = tokenText();
+            }
+
+            //
+            // recognize the mandatory `as' followed by the module name
+            //
+            if (! (lex() == T_RESERVED_WORD && tokenText() == QLatin1String("as")))
+                return false; // expected `as'
+
+            if (lex() != T_IDENTIFIER)
+                return false; // expected module name
+
+            const QString module = tokenText();
+
+            if (fileImport)
+                directives->importFile(pathOrUri, module);
+            else
+                directives->importModule(pathOrUri, version, module);
+        }
+
+        if (tokenStartLine() != lineNumber)
+            return false; // the directives cannot span over multiple lines
+
+        // fetch the first token after the .pragma/.import directive
+        lex();
+    } while (_tokenKind == T_DOT);
+
+    return true;
+}
+
 #include "qdeclarativejskeywords_p.h"
index 6d32786..e20490c 100644 (file)
@@ -63,6 +63,28 @@ namespace QDeclarativeJS {
 
 class Engine;
 
+class QML_PARSER_EXPORT Directives {
+public:
+    virtual ~Directives() {}
+
+    virtual void pragmaLibrary()
+    {
+    }
+
+    virtual void importFile(const QString &jsfile, const QString &module)
+    {
+        Q_UNUSED(jsfile);
+        Q_UNUSED(module);
+    }
+
+    virtual void importModule(const QString &uri, const QString &version, const QString &module)
+    {
+        Q_UNUSED(uri);
+        Q_UNUSED(version);
+        Q_UNUSED(module);
+    }
+};
+
 class QML_PARSER_EXPORT Lexer: public QDeclarativeJSGrammar
 {
 public:
@@ -123,6 +145,7 @@ public:
     int lex();
 
     bool scanRegExp(RegExpBodyPrefix prefix = NoPrefix);
+    bool scanDirectives(Directives *directives);
 
     int regExpFlags() const { return _patternFlags; }
     QString regExpPattern() const { return _tokenText; }