Add yield as a keyword

It's not a keyword outside of generator functions, so extend the
qmlmode boolean on the lexer to become a more general parsemode that
we can use to also turn the yield keyword on and of.

The parser can then set the flag when it enters the body of a generator
function.

Change-Id: Ibf792d4c7c567d825c6706f7b4997362c87fc575
Reviewed-by: Simon Hausmann <simon.hausmann@qt.io>
This commit is contained in:
Lars Knoll 2018-03-02 10:21:12 +01:00
parent f6754300e2
commit 4e18d38f16
4 changed files with 89 additions and 57 deletions

View File

@ -79,6 +79,7 @@
%token T_COMPATIBILITY_SEMICOLON
%token T_ENUM "enum"
%token T_ELLIPSIS "..."
%token T_YIELD "yield"
--- template strings
%token T_NO_SUBSTITUTION_TEMPLATE
@ -106,7 +107,7 @@
%token T_FEED_JS_PROGRAM
%nonassoc SHIFT_THERE
%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY T_ON T_SET T_GET
%nonassoc T_IDENTIFIER T_COLON T_SIGNAL T_PROPERTY T_READONLY T_ON T_SET T_GET T_YIELD
%nonassoc REDUCE_HERE
%start TopLevel
@ -1282,6 +1283,7 @@ JsIdentifier: T_READONLY ;
JsIdentifier: T_ON ;
JsIdentifier: T_GET ;
JsIdentifier: T_SET ;
JsIdentifier: T_YIELD ;
--------------------------------------------------------------------------------------------------------
-- Expressions

View File

@ -57,10 +57,10 @@ QT_QML_BEGIN_NAMESPACE
namespace QQmlJS {
static inline int classify2(const QChar *s, bool qmlMode) {
static inline int classify2(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'a') {
if (s[1].unicode() == 's') {
return qmlMode ? Lexer::T_AS : Lexer::T_IDENTIFIER;
return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_AS : Lexer::T_IDENTIFIER;
}
}
else if (s[0].unicode() == 'd') {
@ -76,15 +76,15 @@ static inline int classify2(const QChar *s, bool qmlMode) {
return Lexer::T_IN;
}
}
else if (qmlMode && s[0].unicode() == 'o') {
else if ((parseModeFlags & Lexer::QmlMode) && s[0].unicode() == 'o') {
if (s[1].unicode() == 'n') {
return qmlMode ? Lexer::T_ON : Lexer::T_IDENTIFIER;
return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_ON : Lexer::T_IDENTIFIER;
}
}
return Lexer::T_IDENTIFIER;
}
static inline int classify3(const QChar *s, bool qmlMode) {
static inline int classify3(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'f') {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 'r') {
@ -102,7 +102,7 @@ static inline int classify3(const QChar *s, bool qmlMode) {
else if (s[0].unicode() == 'i') {
if (s[1].unicode() == 'n') {
if (s[2].unicode() == 't') {
return qmlMode ? int(Lexer::T_INT) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_INT) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -144,12 +144,12 @@ static inline int classify3(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify4(const QChar *s, bool qmlMode) {
static inline int classify4(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'b') {
if (s[1].unicode() == 'y') {
if (s[2].unicode() == 't') {
if (s[3].unicode() == 'e') {
return qmlMode ? int(Lexer::T_BYTE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_BYTE) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -165,7 +165,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
else if (s[1].unicode() == 'h') {
if (s[2].unicode() == 'a') {
if (s[3].unicode() == 'r') {
return qmlMode ? int(Lexer::T_CHAR) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_CHAR) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -181,7 +181,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
else if (s[1].unicode() == 'n') {
if (s[2].unicode() == 'u') {
if (s[3].unicode() == 'm') {
return qmlMode ? int(Lexer::T_ENUM) : int(Lexer::T_RESERVED_WORD);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_ENUM) : int(Lexer::T_RESERVED_WORD);
}
}
}
@ -190,7 +190,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 't') {
if (s[3].unicode() == 'o') {
return qmlMode ? int(Lexer::T_GOTO) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_GOTO) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -199,7 +199,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 'n') {
if (s[3].unicode() == 'g') {
return qmlMode ? int(Lexer::T_LONG) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_LONG) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -250,7 +250,7 @@ static inline int classify4(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify5(const QChar *s, bool qmlMode) {
static inline int classify5(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'b') {
if (s[1].unicode() == 'r') {
if (s[2].unicode() == 'e') {
@ -305,7 +305,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'n') {
if (s[3].unicode() == 'a') {
if (s[4].unicode() == 'l') {
return qmlMode ? int(Lexer::T_FINAL) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_FINAL) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -314,7 +314,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'o') {
if (s[3].unicode() == 'a') {
if (s[4].unicode() == 't') {
return qmlMode ? int(Lexer::T_FLOAT) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_FLOAT) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -325,7 +325,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'o') {
if (s[3].unicode() == 'r') {
if (s[4].unicode() == 't') {
return qmlMode ? int(Lexer::T_SHORT) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_SHORT) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -334,7 +334,7 @@ static inline int classify5(const QChar *s, bool qmlMode) {
if (s[2].unicode() == 'p') {
if (s[3].unicode() == 'e') {
if (s[4].unicode() == 'r') {
return qmlMode ? int(Lexer::T_SUPER) : int(Lexer::T_RESERVED_WORD);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_SUPER) : int(Lexer::T_RESERVED_WORD);
}
}
}
@ -362,10 +362,21 @@ static inline int classify5(const QChar *s, bool qmlMode) {
}
}
}
else if (s[0].unicode() == 'y') {
if (s[1].unicode() == 'i') {
if (s[2].unicode() == 'e') {
if (s[3].unicode() == 'l') {
if (s[4].unicode() == 'd') {
return (parseModeFlags & Lexer::YieldIsKeyword) ? Lexer::T_YIELD : Lexer::T_IDENTIFIER;
}
}
}
}
}
return Lexer::T_IDENTIFIER;
}
static inline int classify6(const QChar *s, bool qmlMode) {
static inline int classify6(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'd') {
if (s[1].unicode() == 'e') {
if (s[2].unicode() == 'l') {
@ -383,7 +394,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'b') {
if (s[4].unicode() == 'l') {
if (s[5].unicode() == 'e') {
return qmlMode ? int(Lexer::T_DOUBLE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_DOUBLE) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -409,7 +420,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'o') {
if (s[4].unicode() == 'r') {
if (s[5].unicode() == 't') {
return qmlMode ? int(Lexer::T_IMPORT) : int(Lexer::T_RESERVED_WORD);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_IMPORT) : int(Lexer::T_RESERVED_WORD);
}
}
}
@ -422,7 +433,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'i') {
if (s[4].unicode() == 'v') {
if (s[5].unicode() == 'e') {
return qmlMode ? int(Lexer::T_NATIVE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_NATIVE) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -435,7 +446,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'l') {
if (s[4].unicode() == 'i') {
if (s[5].unicode() == 'c') {
return qmlMode ? Lexer::T_PUBLIC : Lexer::T_IDENTIFIER;
return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_PUBLIC : Lexer::T_IDENTIFIER;
}
}
}
@ -446,7 +457,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'g') {
if (s[4].unicode() == 'm') {
if (s[5].unicode() == 'a') {
return qmlMode ? Lexer::T_PRAGMA : Lexer::T_IDENTIFIER;
return (parseModeFlags & Lexer::QmlMode) ? Lexer::T_PRAGMA : Lexer::T_IDENTIFIER;
}
}
}
@ -467,7 +478,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
}
}
else if (s[0].unicode() == 's') {
if (qmlMode && s[1].unicode() == 'i') {
if ((parseModeFlags & Lexer::QmlMode) && s[1].unicode() == 'i') {
if (s[2].unicode() == 'g') {
if (s[3].unicode() == 'n') {
if (s[4].unicode() == 'a') {
@ -483,7 +494,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 't') {
if (s[4].unicode() == 'i') {
if (s[5].unicode() == 'c') {
return qmlMode ? int(Lexer::T_STATIC) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_STATIC) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -507,7 +518,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
if (s[3].unicode() == 'o') {
if (s[4].unicode() == 'w') {
if (s[5].unicode() == 's') {
return qmlMode ? int(Lexer::T_THROWS) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_THROWS) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -528,7 +539,7 @@ static inline int classify6(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify7(const QChar *s, bool qmlMode) {
static inline int classify7(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'b') {
if (s[1].unicode() == 'o') {
if (s[2].unicode() == 'o') {
@ -536,7 +547,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
if (s[4].unicode() == 'e') {
if (s[5].unicode() == 'a') {
if (s[6].unicode() == 'n') {
return qmlMode ? int(Lexer::T_BOOLEAN) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_BOOLEAN) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -596,7 +607,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
if (s[4].unicode() == 'a') {
if (s[5].unicode() == 'g') {
if (s[6].unicode() == 'e') {
return qmlMode ? int(Lexer::T_PACKAGE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PACKAGE) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -609,7 +620,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
if (s[4].unicode() == 'a') {
if (s[5].unicode() == 't') {
if (s[6].unicode() == 'e') {
return qmlMode ? int(Lexer::T_PRIVATE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PRIVATE) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -620,7 +631,7 @@ static inline int classify7(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify8(const QChar *s, bool qmlMode) {
static inline int classify8(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'a') {
if (s[1].unicode() == 'b') {
if (s[2].unicode() == 's') {
@ -629,7 +640,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
if (s[5].unicode() == 'a') {
if (s[6].unicode() == 'c') {
if (s[7].unicode() == 't') {
return qmlMode ? int(Lexer::T_ABSTRACT) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_ABSTRACT) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -689,7 +700,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
}
}
}
else if (qmlMode && s[0].unicode() == 'p') {
else if ((parseModeFlags & Lexer::QmlMode) && s[0].unicode() == 'p') {
if (s[1].unicode() == 'r') {
if (s[2].unicode() == 'o') {
if (s[3].unicode() == 'p') {
@ -706,7 +717,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
}
}
}
else if (qmlMode && s[0].unicode() == 'r') {
else if ((parseModeFlags & Lexer::QmlMode) && s[0].unicode() == 'r') {
if (s[1].unicode() == 'e') {
if (s[2].unicode() == 'a') {
if (s[3].unicode() == 'd') {
@ -731,7 +742,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
if (s[5].unicode() == 'i') {
if (s[6].unicode() == 'l') {
if (s[7].unicode() == 'e') {
return qmlMode ? int(Lexer::T_VOLATILE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_VOLATILE) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -743,7 +754,7 @@ static inline int classify8(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify9(const QChar *s, bool qmlMode) {
static inline int classify9(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'i') {
if (s[1].unicode() == 'n') {
if (s[2].unicode() == 't') {
@ -753,7 +764,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
if (s[6].unicode() == 'a') {
if (s[7].unicode() == 'c') {
if (s[8].unicode() == 'e') {
return qmlMode ? int(Lexer::T_INTERFACE) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_INTERFACE) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -772,7 +783,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
if (s[6].unicode() == 't') {
if (s[7].unicode() == 'e') {
if (s[8].unicode() == 'd') {
return qmlMode ? int(Lexer::T_PROTECTED) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_PROTECTED) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -791,7 +802,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
if (s[6].unicode() == 'e') {
if (s[7].unicode() == 'n') {
if (s[8].unicode() == 't') {
return qmlMode ? int(Lexer::T_TRANSIENT) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_TRANSIENT) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -804,7 +815,7 @@ static inline int classify9(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify10(const QChar *s, bool qmlMode) {
static inline int classify10(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 'i') {
if (s[1].unicode() == 'm') {
if (s[2].unicode() == 'p') {
@ -815,7 +826,7 @@ static inline int classify10(const QChar *s, bool qmlMode) {
if (s[7].unicode() == 'n') {
if (s[8].unicode() == 't') {
if (s[9].unicode() == 's') {
return qmlMode ? int(Lexer::T_IMPLEMENTS) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_IMPLEMENTS) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -848,7 +859,7 @@ static inline int classify10(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
static inline int classify12(const QChar *s, bool qmlMode) {
static inline int classify12(const QChar *s, int parseModeFlags) {
if (s[0].unicode() == 's') {
if (s[1].unicode() == 'y') {
if (s[2].unicode() == 'n') {
@ -861,7 +872,7 @@ static inline int classify12(const QChar *s, bool qmlMode) {
if (s[9].unicode() == 'z') {
if (s[10].unicode() == 'e') {
if (s[11].unicode() == 'd') {
return qmlMode ? int(Lexer::T_SYNCHRONIZED) : int(Lexer::T_IDENTIFIER);
return (parseModeFlags & Lexer::QmlMode) ? int(Lexer::T_SYNCHRONIZED) : int(Lexer::T_IDENTIFIER);
}
}
}
@ -877,18 +888,18 @@ static inline int classify12(const QChar *s, bool qmlMode) {
return Lexer::T_IDENTIFIER;
}
int Lexer::classify(const QChar *s, int n, bool qmlMode) {
int Lexer::classify(const QChar *s, int n, int parseModeFlags) {
switch (n) {
case 2: return classify2(s, qmlMode);
case 3: return classify3(s, qmlMode);
case 4: return classify4(s, qmlMode);
case 5: return classify5(s, qmlMode);
case 6: return classify6(s, qmlMode);
case 7: return classify7(s, qmlMode);
case 8: return classify8(s, qmlMode);
case 9: return classify9(s, qmlMode);
case 10: return classify10(s, qmlMode);
case 12: return classify12(s, qmlMode);
case 2: return classify2(s, parseModeFlags);
case 3: return classify3(s, parseModeFlags);
case 4: return classify4(s, parseModeFlags);
case 5: return classify5(s, parseModeFlags);
case 6: return classify6(s, parseModeFlags);
case 7: return classify7(s, parseModeFlags);
case 8: return classify8(s, parseModeFlags);
case 9: return classify9(s, parseModeFlags);
case 10: return classify10(s, parseModeFlags);
case 12: return classify12(s, parseModeFlags);
default: return Lexer::T_IDENTIFIER;
} // switch
}

View File

@ -784,7 +784,7 @@ again:
int kind = T_IDENTIFIER;
if (!identifierWithEscapeChars)
kind = classify(_tokenStartPtr, _tokenLength, _qmlMode);
kind = classify(_tokenStartPtr, _tokenLength, parseModeFlags());
if (_engine) {
if (kind == T_IDENTIFIER && identifierWithEscapeChars)

View File

@ -121,10 +121,25 @@ public:
RegExp_Multiline = 0x04
};
enum ParseModeFlags {
QmlMode = 0x1,
YieldIsKeyword = 0x2
};
public:
Lexer(Engine *engine);
int parseModeFlags() const {
int flags = 0;
if (qmlMode())
flags |= QmlMode;
if (yieldIsKeyWord())
flags |= YieldIsKeyword;
return flags;
}
bool qmlMode() const;
bool yieldIsKeyWord() const { return _generatorLevel != 0; }
QString code() const;
void setCode(const QString &code, int lineno, bool qmlMode = true);
@ -161,8 +176,11 @@ public:
BalancedParentheses
};
void enterGeneratorBody() { ++_generatorLevel; }
void leaveGeneratorBody() { --_generatorLevel; }
protected:
int classify(const QChar *s, int n, bool qmlMode);
static int classify(const QChar *s, int n, int parseModeFlags);
private:
inline void scanChar();
@ -229,6 +247,7 @@ private:
bool _followsClosingBrace;
bool _delimited;
bool _qmlMode;
int _generatorLevel = 0;
};
} // end of namespace QQmlJS