diff options
Diffstat (limited to 'src/qml/parser/qqmljs.g')
-rw-r--r-- | src/qml/parser/qqmljs.g | 138 |
1 files changed, 105 insertions, 33 deletions
diff --git a/src/qml/parser/qqmljs.g b/src/qml/parser/qqmljs.g index 394edf0fed..32b609f5ff 100644 --- a/src/qml/parser/qqmljs.g +++ b/src/qml/parser/qqmljs.g @@ -212,11 +212,11 @@ public: AST::ExportClause *ExportClause; AST::ExportDeclaration *ExportDeclaration; AST::TypeAnnotation *TypeAnnotation; - AST::TypeArgument *TypeArgument; AST::Type *Type; AST::UiProgram *UiProgram; AST::UiHeaderItemList *UiHeaderItemList; + AST::UiPragmaValueList *UiPragmaValueList; AST::UiPragma *UiPragma; AST::UiImport *UiImport; AST::UiParameterList *UiParameterList; @@ -302,6 +302,18 @@ public: inline int errorColumnNumber() const { return diagnosticMessage().loc.startColumn; } + inline bool identifierInsertionEnabled() const + { return m_identifierInsertionEnabled; } + + inline void setIdentifierInsertionEnabled(bool enable) + { m_identifierInsertionEnabled = enable; } + + inline bool incompleteBindingsEnabled() const + { return m_incompleteBindingsEnabled; } + + inline void setIncompleteBindingsEnabled(bool enable) + { m_incompleteBindingsEnabled = enable; } + protected: bool parse(int startToken); @@ -322,6 +334,7 @@ protected: AST::UiQualifiedId *reparseAsQualifiedId(AST::ExpressionNode *expr); void pushToken(int token); + void pushTokenWithEmptyLocation(int token); int lookaheadToken(Lexer *lexer); static DiagnosticMessage compileError(const SourceLocation &location, @@ -373,6 +386,7 @@ protected: QStringView yytokenraw; SourceLocation yylloc; SourceLocation yyprevlloc; + int yyprevtoken = -1; SavedToken token_buffer[TOKEN_BUFFER_SIZE]; SavedToken *first_token = nullptr; @@ -390,6 +404,8 @@ protected: CoverExpressionType coverExpressionType = CE_Invalid; QList<DiagnosticMessage> diagnostic_messages; + bool m_identifierInsertionEnabled = false; + bool m_incompleteBindingsEnabled = false; }; } // end of namespace QQmlJS @@ -465,11 +481,13 @@ AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) { QVarLengthArray<QStringView, 4> nameIds; QVarLengthArray<SourceLocation, 4> locations; + QVarLengthArray<SourceLocation, 4> dotLocations; AST::ExpressionNode *it = expr; while (AST::FieldMemberExpression *m = AST::cast<AST::FieldMemberExpression *>(it)) { nameIds.append(m->name); locations.append(m->identifierToken); + dotLocations.append(m->dotToken); it = m->base; } @@ -481,6 +499,7 @@ AST::UiQualifiedId *Parser::reparseAsQualifiedId(AST::ExpressionNode *expr) for (int i = nameIds.size() - 1; i != -1; --i) { currentId = new (pool) AST::UiQualifiedId(currentId, nameIds[i]); currentId->identifierToken = locations[i]; + currentId->dotToken = dotLocations[i]; } return currentId->finish(); @@ -502,9 +521,19 @@ void Parser::pushToken(int token) yytoken = token; } +void Parser::pushTokenWithEmptyLocation(int token) +{ + pushToken(token); + yylloc = yyprevlloc; + yylloc.offset += yylloc.length; + yylloc.startColumn += yylloc.length; + yylloc.length = 0; +} + int Parser::lookaheadToken(Lexer *lexer) { if (yytoken < 0) { + yyprevtoken = yytoken; yytoken = lexer->lex(); yylval = lexer->tokenValue(); yytokenspell = lexer->tokenSpell(); @@ -600,6 +629,7 @@ bool Parser::parse(int startToken) #endif if (action > 0) { if (action != ACCEPT_STATE) { + yyprevtoken = yytoken; yytoken = -1; sym(1).dval = yylval; stringRef(1) = yytokenspell; @@ -717,25 +747,51 @@ UiHeaderItemList: UiHeaderItemList UiImport; ./ PragmaId: JsIdentifier; +PragmaValue: JsIdentifier + | T_STRING_LITERAL; Semicolon: T_AUTOMATIC_SEMICOLON; Semicolon: T_SEMICOLON; +UiPragmaValueList: PragmaValue; +/. + case $rule_number: { + AST::UiPragmaValueList *list + = new (pool) AST::UiPragmaValueList(stringRef(1)); + list->location = loc(1); + sym(1).Node = list; + } break; +./ + +UiPragmaValueList: UiPragmaValueList T_COMMA PragmaValue; +/. + case $rule_number: { + AST::UiPragmaValueList *list + = new (pool) AST::UiPragmaValueList(sym(1).UiPragmaValueList, stringRef(3)); + list->location = loc(3); + sym(1).Node = list; + } break; +./ + UiPragma: T_PRAGMA PragmaId Semicolon; /. case $rule_number: { AST::UiPragma *pragma = new (pool) AST::UiPragma(stringRef(2)); pragma->pragmaToken = loc(1); + pragma->pragmaIdToken = loc(2); pragma->semicolonToken = loc(3); sym(1).Node = pragma; } break; ./ -UiPragma: T_PRAGMA PragmaId T_COLON JsIdentifier Semicolon; +UiPragma: T_PRAGMA PragmaId T_COLON UiPragmaValueList Semicolon; /. case $rule_number: { - AST::UiPragma *pragma = new (pool) AST::UiPragma(stringRef(2), stringRef(4)); + AST::UiPragma *pragma = new (pool) AST::UiPragma( + stringRef(2), sym(4).UiPragmaValueList->finish()); pragma->pragmaToken = loc(1); + pragma->pragmaIdToken = loc(2); + pragma->colonToken = loc(3); pragma->semicolonToken = loc(5); sym(1).Node = pragma; } break; @@ -1095,6 +1151,20 @@ case $rule_number: } break; ./ +UiObjectMember: UiQualifiedId Semicolon; +/. + case $rule_number: { + if (!m_incompleteBindingsEnabled) { + diagnostic_messages.append(compileError(loc(1), QLatin1String("Incomplete binding, expected token `:` or `{`"))); + return false; + } + AST::EmptyStatement *statement = new (pool) AST::EmptyStatement; + statement->semicolonToken = loc(2); + AST::UiScriptBinding *node = new (pool) AST::UiScriptBinding(sym(1).UiQualifiedId, statement); + sym(1).Node = node; + } break; +./ + UiPropertyType: T_VAR; /. case $rule_number: Q_FALLTHROUGH(); ./ UiPropertyType: T_RESERVED_WORD; @@ -1359,6 +1429,7 @@ UiObjectMemberWithArray: UiPropertyAttributes T_IDENTIFIER T_LT UiPropertyType T node->typeToken = loc(4); node->identifierToken = loc(6); node->semicolonToken = loc(7); // insert a fake ';' before ':' + node->colonToken = loc(7); AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(6)); propertyName->identifierToken = loc(6); @@ -1388,6 +1459,7 @@ UiObjectMemberExpressionStatementLookahead: UiPropertyAttributes UiPropertyType node->typeToken = loc(2); node->identifierToken = loc(3); node->semicolonToken = loc(4); // insert a fake ';' before ':' + node->colonToken = loc(4); AST::UiQualifiedId *propertyName = new (pool) AST::UiQualifiedId(stringRef(3)); propertyName->identifierToken = loc(3); @@ -1472,6 +1544,7 @@ UiObjectMember: T_COMPONENT T_IDENTIFIER T_COLON UiObjectDefinition; } auto inlineComponent = new (pool) AST::UiInlineComponent(stringRef(2), sym(4).UiObjectDefinition); inlineComponent->componentToken = loc(1); + inlineComponent->identifierToken = loc(2); sym(1).Node = inlineComponent; } break; ./ @@ -1983,7 +2056,6 @@ PropertyDefinition: IdentifierReference; AST::IdentifierExpression *expr = new (pool) AST::IdentifierExpression(stringRef(1)); expr->identifierToken = loc(1); AST::PatternProperty *node = new (pool) AST::PatternProperty(name, expr); - node->colonToken = loc(2); sym(1).Node = node; } break; ./ @@ -2006,7 +2078,6 @@ CoverInitializedName: IdentifierReference Initializer_In; AST::BinaryExpression *assignment = new (pool) AST::BinaryExpression(left, QSOperator::Assign, sym(2).Expression); assignment->operatorToken = loc(2); AST::PatternProperty *node = new (pool) AST::PatternProperty(name, assignment); - node->colonToken = loc(1); sym(1).Node = node; } break; @@ -2119,7 +2190,9 @@ Initializer: T_EQ AssignmentExpression; Initializer_In: T_EQ AssignmentExpression_In; /. case $rule_number: { - sym(1) = sym(2); + auto node = new (pool) AST::InitializerExpression(sym(2).Expression); + node->equalToken = loc(1); + sym(1).Expression = node; } break; ./ @@ -3309,14 +3382,15 @@ BindingElisionElement: ElisionOpt BindingElement; BindingProperty: BindingIdentifier InitializerOpt_In; /. case $rule_number: { - AST::StringLiteralPropertyName *name = new (pool) AST::StringLiteralPropertyName(stringRef(1)); + AST::IdentifierPropertyName *name = new (pool) AST::IdentifierPropertyName(stringRef(1)); name->propertyNameToken = loc(1); // if initializer is an anonymous function expression, we need to assign identifierref as it's name if (auto *f = asAnonymousFunctionDefinition(sym(2).Expression)) f->name = stringRef(1); if (auto *c = asAnonymousClassDefinition(sym(2).Expression)) c->name = stringRef(1); - sym(1).Node = new (pool) AST::PatternProperty(name, stringRef(1), sym(2).Expression); + AST::PatternProperty *node = new (pool) AST::PatternProperty(name, stringRef(1), sym(2).Expression); + sym(1).Node = node; } break; ./ @@ -3324,6 +3398,8 @@ BindingProperty: PropertyName T_COLON BindingIdentifier InitializerOpt_In; /. case $rule_number: { AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, stringRef(3), sym(4).Expression); + node->colonToken = loc(2); + node->identifierToken = loc(3); sym(1).Node = node; } break; ./ @@ -3332,6 +3408,7 @@ BindingProperty: PropertyName T_COLON BindingPattern InitializerOpt_In; /. case $rule_number: { AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(1).PropertyName, sym(3).Pattern, sym(4).Expression); + node->colonToken = loc(2); sym(1).Node = node; } break; ./ @@ -3491,6 +3568,11 @@ IterationStatement: T_FOR T_LPAREN LexicalDeclaration T_SEMICOLON ExpressionOpt_ AST::ForStatement *node = new (pool) AST::ForStatement( static_cast<AST::VariableStatement *>(sym(3).Node)->declarations, sym(5).Expression, sym(7).Expression, sym(9).Statement); + if (node->declarations) { + AST::PatternElement *pe = node->declarations->declaration; + pe->isForDeclaration = true; + pe->declarationKindToken = loc(3); + } node->forToken = loc(1); node->lparenToken = loc(2); node->firstSemicolonToken = loc(4); @@ -3562,6 +3644,7 @@ ForDeclaration: Var BindingIdentifier TypeAnnotationOpt; node->identifierToken = loc(2); node->scope = sym(1).scope; node->isForDeclaration = true; + node->declarationKindToken = loc(1); sym(1).Node = node; } break; ./ @@ -3574,6 +3657,7 @@ ForDeclaration: Var BindingPattern; auto *node = new (pool) AST::PatternElement(sym(2).Pattern, nullptr); node->scope = sym(1).scope; node->isForDeclaration = true; + node->declarationKindToken = loc(1); sym(1).Node = node; } break; ./ @@ -4090,7 +4174,6 @@ MethodDefinition: T_STAR PropertyName GeneratorLParen StrictFormalParameters T_R f->rbraceToken = loc(9); f->isGenerator = true; AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Method); - node->colonToken = loc(2); sym(1).Node = node; } break; ./ @@ -4108,7 +4191,6 @@ MethodDefinition: T_GET PropertyName T_LPAREN T_RPAREN TypeAnnotationOpt Functio f->lbraceToken = loc(6); f->rbraceToken = loc(8); AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Getter); - node->colonToken = loc(2); sym(1).Node = node; } break; ./ @@ -4125,7 +4207,6 @@ MethodDefinition: T_SET PropertyName T_LPAREN PropertySetParameterList T_RPAREN f->lbraceToken = loc(7); f->rbraceToken = loc(9); AST::PatternProperty *node = new (pool) AST::PatternProperty(sym(2).PropertyName, f, AST::PatternProperty::Setter); - node->colonToken = loc(2); sym(1).Node = node; } break; ./ @@ -4755,35 +4836,26 @@ ExportSpecifier: IdentifierName T_AS IdentifierName; if (first_token == last_token) { const int errorState = state_stack[tos]; + // automatic insertion of missing identifiers after dots + if (yytoken != -1 && m_identifierInsertionEnabled && t_action(errorState, T_IDENTIFIER) && yyprevtoken == T_DOT) { +#ifdef PARSER_DEBUG + qDebug() << "Inserting missing identifier between" << spell[yyprevtoken] << "and" + << spell[yytoken]; +#endif + pushTokenWithEmptyLocation(T_IDENTIFIER); + action = errorState; + goto _Lcheck_token; + } + + // automatic insertion of `;' if (yytoken != -1 && ((t_action(errorState, T_AUTOMATIC_SEMICOLON) && lexer->canInsertAutomaticSemicolon(yytoken)) || t_action(errorState, T_COMPATIBILITY_SEMICOLON))) { #ifdef PARSER_DEBUG qDebug() << "Inserting automatic semicolon."; #endif - SavedToken &tk = token_buffer[0]; - tk.token = yytoken; - tk.dval = yylval; - tk.spell = yytokenspell; - tk.raw = yytokenraw; - tk.loc = yylloc; - - yylloc = yyprevlloc; - yylloc.offset += yylloc.length; - yylloc.startColumn += yylloc.length; - yylloc.length = 0; - - //const QString msg = QCoreApplication::translate("QQmlParser", "Missing `;'"); - //diagnostic_messages.append(compileError(yyloc, msg, QtWarningMsg)); - - first_token = &token_buffer[0]; - last_token = &token_buffer[1]; - - yytoken = T_SEMICOLON; - yylval = 0; - + pushTokenWithEmptyLocation(T_SEMICOLON); action = errorState; - goto _Lcheck_token; } |