Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
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 <qt_sanity_bot@ovi.com>
Reviewed-by: Kent Hansen <kent.hansen@nokia.com>
  • Loading branch information
Roberto Raggi authored and Qt by Nokia committed Sep 19, 2011
1 parent 4a5ad69 commit e4b8baf
Show file tree
Hide file tree
Showing 6 changed files with 43 additions and 18 deletions.
10 changes: 1 addition & 9 deletions src/declarative/qml/parser/qdeclarativejs.g
Expand Up @@ -407,14 +407,6 @@ void Parser::reallocateStack()
string_stack = reinterpret_cast<QStringRef*> (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()),
Expand Down Expand Up @@ -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;
Expand Down
18 changes: 18 additions & 0 deletions src/declarative/qml/parser/qdeclarativejslexer.cpp
Expand Up @@ -111,6 +111,7 @@ Lexer::Lexer(Engine *engine)
, _prohibitAutomaticSemicolon(false)
, _restrictedKeyword(false)
, _terminator(false)
, _followsClosingBrace(false)
, _delimited(false)
, _qmlMode(true)
{
Expand Down Expand Up @@ -160,6 +161,7 @@ void Lexer::setCode(const QString &code, int lineno, bool qmlMode)
_prohibitAutomaticSemicolon = false;
_restrictedKeyword = false;
_terminator = false;
_followsClosingBrace = false;
_delimited = false;
}

Expand All @@ -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) {
Expand Down Expand Up @@ -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"
3 changes: 3 additions & 0 deletions src/declarative/qml/parser/qdeclarativejslexer_p.h
Expand Up @@ -144,6 +144,8 @@ class QML_PARSER_EXPORT Lexer: public QDeclarativeJSGrammar
QString errorMessage() const;

bool prevTerminator() const;
bool followsClosingBrace() const;
bool canInsertAutomaticSemicolon(int token) const;

enum ParenthesesState {
IgnoreParentheses,
Expand Down Expand Up @@ -201,6 +203,7 @@ class QML_PARSER_EXPORT Lexer: public QDeclarativeJSGrammar
bool _prohibitAutomaticSemicolon;
bool _restrictedKeyword;
bool _terminator;
bool _followsClosingBrace;
bool _delimited;
bool _qmlMode;
};
Expand Down
10 changes: 1 addition & 9 deletions src/declarative/qml/parser/qdeclarativejsparser.cpp
Expand Up @@ -76,14 +76,6 @@ void Parser::reallocateStack()
string_stack = reinterpret_cast<QStringRef*> (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()),
Expand Down Expand Up @@ -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;
Expand Down
@@ -0,0 +1,11 @@

import QtQuick 2.0

QtObject {
function code() {
if (1) {
var a;
function f1(){}a=1;
}
}
}
Expand Up @@ -199,6 +199,8 @@ private slots:
void revisionErrors();
void revision();

void automaticSemicolon();

private:
QDeclarativeEngine engine;
};
Expand Down Expand Up @@ -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"

0 comments on commit e4b8baf

Please sign in to comment.