From e4b8bafa3be9d5c20b220349d2ffa39a3085b947 Mon Sep 17 00:00:00 2001 From: Roberto Raggi Date: Wed, 14 Sep 2011 14:50:24 +0200 Subject: [PATCH] Fix automatic semicolon insertion. The parser should insert a T_SEMICOLON token when it reaches an error state and the lookahead token is following a closing brace. Change-Id: Ib849e7fbfe50c2a3e679ae0794f5780cc0b94de5 Reviewed-on: http://codereview.qt-project.org/4896 Reviewed-by: Qt Sanity Bot Reviewed-by: Kent Hansen --- src/declarative/qml/parser/qdeclarativejs.g | 10 +--------- src/declarative/qml/parser/qdeclarativejslexer.cpp | 18 ++++++++++++++++++ src/declarative/qml/parser/qdeclarativejslexer_p.h | 3 +++ .../qml/parser/qdeclarativejsparser.cpp | 10 +--------- .../data/automaticSemicolon.qml | 11 +++++++++++ .../tst_qdeclarativeecmascript.cpp | 9 +++++++++ 6 files changed, 43 insertions(+), 18 deletions(-) create mode 100644 tests/auto/declarative/qdeclarativeecmascript/data/automaticSemicolon.qml diff --git a/src/declarative/qml/parser/qdeclarativejs.g b/src/declarative/qml/parser/qdeclarativejs.g index d30c697..7f8e0b6 100644 --- a/src/declarative/qml/parser/qdeclarativejs.g +++ b/src/declarative/qml/parser/qdeclarativejs.g @@ -407,14 +407,6 @@ void Parser::reallocateStack() string_stack = reinterpret_cast (qRealloc(string_stack, stack_size * sizeof(QStringRef))); } -inline static bool automatic(Engine *driver, int token) -{ - return token == $table::T_RBRACE - || token == 0 - || driver->lexer()->prevTerminator(); -} - - Parser::Parser(Engine *engine): driver(engine), pool(engine->pool()), @@ -2890,7 +2882,7 @@ PropertyNameAndValueListOpt: PropertyNameAndValueList ; const int errorState = state_stack[tos]; // automatic insertion of `;' - if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) { + if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken)) { SavedToken &tk = token_buffer[0]; tk.token = yytoken; tk.dval = yylval; diff --git a/src/declarative/qml/parser/qdeclarativejslexer.cpp b/src/declarative/qml/parser/qdeclarativejslexer.cpp index def027c..dd74ffa 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer.cpp +++ b/src/declarative/qml/parser/qdeclarativejslexer.cpp @@ -111,6 +111,7 @@ Lexer::Lexer(Engine *engine) , _prohibitAutomaticSemicolon(false) , _restrictedKeyword(false) , _terminator(false) + , _followsClosingBrace(false) , _delimited(false) , _qmlMode(true) { @@ -160,6 +161,7 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode) _prohibitAutomaticSemicolon = false; _restrictedKeyword = false; _terminator = false; + _followsClosingBrace = false; _delimited = false; } @@ -175,12 +177,15 @@ void Lexer::scanChar() int Lexer::lex() { + const int previousTokenKind = _tokenKind; + _tokenSpell = QStringRef(); _tokenKind = scanToken(); _tokenLength = _codePtr - _tokenStartPtr - 1; _delimited = false; _restrictedKeyword = false; + _followsClosingBrace = (previousTokenKind == T_RBRACE); // update the flags switch (_tokenKind) { @@ -1044,4 +1049,17 @@ bool Lexer::prevTerminator() const return _terminator; } +bool Lexer::followsClosingBrace() const +{ + return _followsClosingBrace; +} + +bool Lexer::canInsertAutomaticSemicolon(int token) const +{ + return token == T_RBRACE + || token == EOF_SYMBOL + || _terminator + || _followsClosingBrace; +} + #include "qdeclarativejskeywords_p.h" diff --git a/src/declarative/qml/parser/qdeclarativejslexer_p.h b/src/declarative/qml/parser/qdeclarativejslexer_p.h index 34cd987..6d32786 100644 --- a/src/declarative/qml/parser/qdeclarativejslexer_p.h +++ b/src/declarative/qml/parser/qdeclarativejslexer_p.h @@ -144,6 +144,8 @@ public: QString errorMessage() const; bool prevTerminator() const; + bool followsClosingBrace() const; + bool canInsertAutomaticSemicolon(int token) const; enum ParenthesesState { IgnoreParentheses, @@ -201,6 +203,7 @@ private: bool _prohibitAutomaticSemicolon; bool _restrictedKeyword; bool _terminator; + bool _followsClosingBrace; bool _delimited; bool _qmlMode; }; diff --git a/src/declarative/qml/parser/qdeclarativejsparser.cpp b/src/declarative/qml/parser/qdeclarativejsparser.cpp index 5c82359..b6cb1fa 100644 --- a/src/declarative/qml/parser/qdeclarativejsparser.cpp +++ b/src/declarative/qml/parser/qdeclarativejsparser.cpp @@ -76,14 +76,6 @@ void Parser::reallocateStack() string_stack = reinterpret_cast (qRealloc(string_stack, stack_size * sizeof(QStringRef))); } -inline static bool automatic(Engine *driver, int token) -{ - return token == QDeclarativeJSGrammar::T_RBRACE - || token == 0 - || driver->lexer()->prevTerminator(); -} - - Parser::Parser(Engine *engine): driver(engine), pool(engine->pool()), @@ -1696,7 +1688,7 @@ case 342: { const int errorState = state_stack[tos]; // automatic insertion of `;' - if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && automatic(driver, yytoken)) { + if (yytoken != -1 && t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken)) { SavedToken &tk = token_buffer[0]; tk.token = yytoken; tk.dval = yylval; diff --git a/tests/auto/declarative/qdeclarativeecmascript/data/automaticSemicolon.qml b/tests/auto/declarative/qdeclarativeecmascript/data/automaticSemicolon.qml new file mode 100644 index 0000000..6db68f2 --- /dev/null +++ b/tests/auto/declarative/qdeclarativeecmascript/data/automaticSemicolon.qml @@ -0,0 +1,11 @@ + +import QtQuick 2.0 + +QtObject { + function code() { + if (1) { + var a; + function f1(){}a=1; + } + } +} diff --git a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp index dc3f053..36941af 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp +++ b/tests/auto/declarative/qdeclarativeecmascript/tst_qdeclarativeecmascript.cpp @@ -199,6 +199,8 @@ private slots: void revisionErrors(); void revision(); + void automaticSemicolon(); + private: QDeclarativeEngine engine; }; @@ -4199,6 +4201,13 @@ void tst_qdeclarativeecmascript::dynamicString() QString::fromLatin1("string:Hello World false:0 true:1 uint32:100 int32:-100 double:3.14159 date:2011-02-11 05::30:50!")); } +void tst_qdeclarativeecmascript::automaticSemicolon() +{ + QDeclarativeComponent component(&engine, TEST_FILE("automaticSemicolon.qml")); + QObject *object = component.create(); + QVERIFY(object != 0); +} + QTEST_MAIN(tst_qdeclarativeecmascript) #include "tst_qdeclarativeecmascript.moc" -- 1.7.2.5