[PATCH v12 0/3] MR10588: vbscript: Add missing compiler error constants, messages, and todo tests.
Add 13 missing VBSE error code definitions (1006, 1007, 1012, 1015, 1016, 1022, 1029, 1030, 1040, 1050, 1051, 1052, 1058) with string resources and test entries. Fix 6 of the 12 tests by adding error productions for mismatched End keywords in blocks (1012, 1015, 1016, 1022, 1029, 1050). The remaining 6 tests (1006, 1007, 1040, 1052, 1058) are todo_wine pending further parser work. -- v12: vbscript: Return specific errors for unclosed parens, multiple defaults, and default on Property Let/Set. vbscript: Return specific errors for mismatched End keywords in blocks. vbscript: Add missing compiler error constants, messages, and tests. https://gitlab.winehq.org/wine/wine/-/merge_requests/10588
From: Francis De Brabandere <francisdb@gmail.com> Add 9 missing VBSE error code definitions (1006, 1012, 1015, 1016, 1022, 1029, 1050, 1052, 1058) with their string resources and test entries. --- dlls/vbscript/tests/run.c | 79 ++++++++++++++++++++++++++++++++++- dlls/vbscript/vbscript.rc | 10 +++++ dlls/vbscript/vbscript_defs.h | 10 +++++ 3 files changed, 97 insertions(+), 2 deletions(-) diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index be71769d6de..f6cde521242 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2742,7 +2742,7 @@ static void test_parse_errors(void) static const struct { const WCHAR *src; - unsigned error_line; + int error_line; int error_char; const WCHAR *source_line; HRESULT source_line_hres; @@ -3122,6 +3122,80 @@ static void test_parse_errors(void) L"\x00e9var = 1\n", 0, 0, NULL, S_OK, 1032 + }, + { + /* Expected ')' - error 1006 */ + L"x = (1 + 2\n", + 0, 10, + NULL, S_OK, -1006 + }, + { + /* Expected 'If' - End With inside If block - error 1012 */ + L"If True Then\n" + " x = 1\n" + "End With\n", + 2, 4, + NULL, S_OK, -1012 + }, + { + /* Expected 'Function' - End Sub inside Function - error 1015 */ + L"Function F()\n" + "End Sub\n", + 1, 4, + NULL, S_OK, -1015 + }, + { + /* Expected 'Sub' - End Function inside Sub - error 1016 */ + L"Sub S()\n" + "End Function\n", + 1, 4, + NULL, S_OK, -1016 + }, + { + /* Expected 'Select' - End If inside Select block - error 1022 */ + L"Select Case 1\n" + " Case 1\n" + "End If\n", + 2, 4, + NULL, S_OK, -1022 + }, + { + /* Expected 'With' - End Sub inside With block - error 1029 */ + L"With CreateObject(\"Scripting.Dictionary\")\n" + "End Sub\n", + 1, 4, + NULL, S_OK, -1029 + }, + { + /* Expected 'Property' - End Sub inside Property Get - error 1050 */ + L"Class C\n" + " Property Get P()\n" + " End Sub\n" + "End Class\n", + 2, 6, + NULL, S_OK, -1050 + }, + { + /* Multiple default members - error 1052 */ + L"Class C\n" + " Public Default Function F()\n" + " F = 1\n" + " End Function\n" + " Public Default Function G()\n" + " G = 2\n" + " End Function\n" + "End Class\n", + -4, -17, + NULL, S_OK, -1052 + }, + { + /* Default only on Property Get - error 1058 */ + L"Class C\n" + " Public Default Property Let P(v)\n" + " End Property\n" + "End Class\n", + -1, -26, + NULL, S_OK, -1058 } }; HRESULT hres; @@ -3139,7 +3213,8 @@ static void test_parse_errors(void) ok(hres == SCRIPT_E_REPORTED, "[%u] script returned: %08lx\n", i, hres); CHECK_CALLED(OnScriptError); - ok(error_line == invalid_scripts[i].error_line, "[%u] error line %lu expected %u\n", + todo_wine_if(invalid_scripts[i].error_line < 0) + ok(error_line == abs(invalid_scripts[i].error_line), "[%u] error line %lu expected %d\n", i, error_line, invalid_scripts[i].error_line); todo_wine_if(invalid_scripts[i].error_char < 0) ok(error_char == abs(invalid_scripts[i].error_char), "[%u] error char %ld expected %d\n", diff --git a/dlls/vbscript/vbscript.rc b/dlls/vbscript/vbscript.rc index 5e3adddc789..87005a8ab3f 100644 --- a/dlls/vbscript/vbscript.rc +++ b/dlls/vbscript/vbscript.rc @@ -64,19 +64,25 @@ STRINGTABLE VBSE_UNQUALIFIED_REFERENCE "Invalid or unqualified reference" VBSE_SYNTAX_ERROR "Syntax error" VBSE_EXPECTED_LPAREN "Expected '('" + VBSE_EXPECTED_RPAREN "Expected ')'" VBSE_EXPECTED_IDENTIFIER "Expected identifier" VBSE_EXPECTED_ASSIGN "Expected '='" + VBSE_EXPECTED_IF "Expected 'If'" VBSE_EXPECTED_TO "Expected 'To'" VBSE_EXPECTED_END "Expected 'End'" + VBSE_EXPECTED_FUNCTION "Expected 'Function'" + VBSE_EXPECTED_SUB "Expected 'Sub'" VBSE_EXPECTED_THEN "Expected 'Then'" VBSE_EXPECTED_WEND "Expected 'Wend'" VBSE_EXPECTED_LOOP "Expected 'Loop'" VBSE_EXPECTED_NEXT "Expected 'Next'" VBSE_EXPECTED_CASE "Expected 'Case'" + VBSE_EXPECTED_SELECT "Expected 'Select'" VBSE_EXPECTED_STATEMENT "Expected statement" VBSE_EXPECTED_END_OF_STATEMENT "Expected end of statement" VBSE_EXPECTED_INTEGER_CONSTANT "Expected integer constant" VBSE_EXPECTED_WHILE_UNTIL_EOS "Expected 'While', 'Until' or end of statement" + VBSE_EXPECTED_WITH "Expected 'With'" VBSE_INVALID_NUMBER "Invalid number" VBSE_INVALID_CHAR "Invalid character" VBSE_UNTERMINATED_STRING "Unterminated string constant" @@ -90,10 +96,14 @@ STRINGTABLE VBSE_EXPECTED_CLASS "Expected 'Class'" VBSE_MUST_BE_INSIDE_CLASS "Must be defined inside a Class" VBSE_EXPECTED_LET_SET_GET "Expected Let or Set or Get in property declaration" + VBSE_EXPECTED_PROPERTY "Expected 'Property'" + VBSE_PROPERTY_ARG_COUNT_MISMATCH "Number of arguments must be consistent across properties specification" + VBSE_MULTIPLE_DEFAULT_MEMBERS "Cannot have multiple default property/method in a Class" VBSE_CLASS_INIT_NO_ARGS "Class initialize or terminate do not have arguments" VBSE_PROPERTY_LET_SET_NEEDS_ARG "Property set or let must have at least one argument" VBSE_UNEXPECTED_NEXT "Unexpected 'Next'" VBSE_DEFAULT_MUST_BE_PUBLIC "'Default' specification must also specify 'Public'" + VBSE_DEFAULT_ONLY_ON_PROPERTY_GET "'Default' specification can only be on Property Get" VBS_COMPILE_ERROR "Microsoft VBScript compilation error" VBS_RUNTIME_ERROR "Microsoft VBScript runtime error" diff --git a/dlls/vbscript/vbscript_defs.h b/dlls/vbscript/vbscript_defs.h index 0dc7b677517..41366f699ca 100644 --- a/dlls/vbscript/vbscript_defs.h +++ b/dlls/vbscript/vbscript_defs.h @@ -275,19 +275,25 @@ #define VBSE_UNQUALIFIED_REFERENCE 505 #define VBSE_SYNTAX_ERROR 1002 #define VBSE_EXPECTED_LPAREN 1005 +#define VBSE_EXPECTED_RPAREN 1006 #define VBSE_EXPECTED_IDENTIFIER 1010 #define VBSE_EXPECTED_ASSIGN 1011 +#define VBSE_EXPECTED_IF 1012 #define VBSE_EXPECTED_TO 1013 #define VBSE_EXPECTED_END 1014 +#define VBSE_EXPECTED_FUNCTION 1015 +#define VBSE_EXPECTED_SUB 1016 #define VBSE_EXPECTED_THEN 1017 #define VBSE_EXPECTED_WEND 1018 #define VBSE_EXPECTED_LOOP 1019 #define VBSE_EXPECTED_NEXT 1020 #define VBSE_EXPECTED_CASE 1021 +#define VBSE_EXPECTED_SELECT 1022 #define VBSE_EXPECTED_STATEMENT 1024 #define VBSE_EXPECTED_END_OF_STATEMENT 1025 #define VBSE_EXPECTED_INTEGER_CONSTANT 1026 #define VBSE_EXPECTED_WHILE_UNTIL_EOS 1028 +#define VBSE_EXPECTED_WITH 1029 #define VBSE_INVALID_NUMBER 1031 #define VBSE_INVALID_CHAR 1032 #define VBSE_UNTERMINATED_STRING 1033 @@ -301,10 +307,14 @@ #define VBSE_EXPECTED_CLASS 1047 #define VBSE_MUST_BE_INSIDE_CLASS 1048 #define VBSE_EXPECTED_LET_SET_GET 1049 +#define VBSE_EXPECTED_PROPERTY 1050 +#define VBSE_PROPERTY_ARG_COUNT_MISMATCH 1051 +#define VBSE_MULTIPLE_DEFAULT_MEMBERS 1052 #define VBSE_CLASS_INIT_NO_ARGS 1053 #define VBSE_PROPERTY_LET_SET_NEEDS_ARG 1054 #define VBSE_UNEXPECTED_NEXT 1055 #define VBSE_DEFAULT_MUST_BE_PUBLIC 1057 +#define VBSE_DEFAULT_ONLY_ON_PROPERTY_GET 1058 #define VBS_COMPILE_ERROR 4096 #define VBS_RUNTIME_ERROR 4097 -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10588
From: Francis De Brabandere <francisdb@gmail.com> Add error productions to detect wrong End keywords inside If, Select, With, Sub, Function, and Property blocks. For example, 'End With' inside an If block now returns error 1012 "Expected 'If'" instead of the generic 1002 "Syntax error". --- dlls/vbscript/parser.y | 20 ++++++++++++++++++++ dlls/vbscript/tests/run.c | 12 ++++++------ 2 files changed, 26 insertions(+), 6 deletions(-) diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index f4b573e2d15..ab4f6250aa1 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -249,8 +249,12 @@ SimpleStatement { $$ = new_foreach_statement(ctx, @$, $3, $5, $7); } | tSELECT tCASE Expression StSep CaseClausules tEND tSELECT { $$ = new_select_statement(ctx, @$, $3, $5); } + | tSELECT tCASE Expression StSep CaseClausules tEND error + { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_SELECT); YYABORT; } | tWITH Expression StSep StatementsNl_opt tEND tWITH { $$ = new_with_statement(ctx, @$, $2, $4); } + | tWITH Expression StSep StatementsNl_opt tEND error + { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_WITH); YYABORT; } MemberExpression : Identifier { $$ = new_member_expression(ctx, NULL, $1); CHECK_ERROR; } @@ -319,6 +323,8 @@ IfStatement { $$ = new_if_statement(ctx, @$, $2, $4, NULL, $6); CHECK_ERROR; } | tIF Expression tTHEN Statement tELSE EndIf_opt { $$ = new_if_statement(ctx, @$, $2, $4, NULL, NULL); CHECK_ERROR; } + | tIF Expression tTHEN tNL StSep_opt StatementsNl_opt ElseIfs_opt Else_opt tEND error + { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_IF); YYABORT; } EndIf_opt : /* empty */ @@ -500,16 +506,30 @@ PropertyDecl { $$ = new_function_decl(ctx, $4, FUNC_PROPLET, @2, $1, $6, $9); CHECK_ERROR; } | Storage_opt tPROPERTY tSET Identifier '(' ArgumentDeclList ')' StSep BodyStatements tEND tPROPERTY { $$ = new_function_decl(ctx, $4, FUNC_PROPSET, @2, $1, $6, $9); CHECK_ERROR; } + | Storage_opt tPROPERTY tGET Identifier ArgumentsDecl_opt StSep BodyStatements tEND error + { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_PROPERTY); YYABORT; } + | Storage_opt tPROPERTY tLET Identifier '(' ArgumentDeclList ')' StSep BodyStatements tEND error + { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_PROPERTY); YYABORT; } + | Storage_opt tPROPERTY tSET Identifier '(' ArgumentDeclList ')' StSep BodyStatements tEND error + { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_PROPERTY); YYABORT; } FunctionDecl : Storage_opt tSUB Identifier StSep BodyStatements tEND tSUB { $$ = new_function_decl(ctx, $3, FUNC_SUB, @2, $1, NULL, $5); CHECK_ERROR; } | Storage_opt tSUB Identifier ArgumentsDecl Nl_opt BodyStatements tEND tSUB { $$ = new_function_decl(ctx, $3, FUNC_SUB, @2, $1, $4, $6); CHECK_ERROR; } + | Storage_opt tSUB Identifier StSep BodyStatements tEND error + { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_SUB); YYABORT; } + | Storage_opt tSUB Identifier ArgumentsDecl Nl_opt BodyStatements tEND error + { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_SUB); YYABORT; } | Storage_opt tFUNCTION Identifier StSep BodyStatements tEND tFUNCTION { $$ = new_function_decl(ctx, $3, FUNC_FUNCTION, @2, $1, NULL, $5); CHECK_ERROR; } | Storage_opt tFUNCTION Identifier ArgumentsDecl Nl_opt BodyStatements tEND tFUNCTION { $$ = new_function_decl(ctx, $3, FUNC_FUNCTION, @2, $1, $4, $6); CHECK_ERROR; } + | Storage_opt tFUNCTION Identifier StSep BodyStatements tEND error + { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_FUNCTION); YYABORT; } + | Storage_opt tFUNCTION Identifier ArgumentsDecl Nl_opt BodyStatements tEND error + { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_FUNCTION); YYABORT; } Storage_opt : /* empty*/ { $$ = 0; } diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index f6cde521242..437ecbeb715 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -3135,21 +3135,21 @@ static void test_parse_errors(void) " x = 1\n" "End With\n", 2, 4, - NULL, S_OK, -1012 + NULL, S_OK, 1012 }, { /* Expected 'Function' - End Sub inside Function - error 1015 */ L"Function F()\n" "End Sub\n", 1, 4, - NULL, S_OK, -1015 + NULL, S_OK, 1015 }, { /* Expected 'Sub' - End Function inside Sub - error 1016 */ L"Sub S()\n" "End Function\n", 1, 4, - NULL, S_OK, -1016 + NULL, S_OK, 1016 }, { /* Expected 'Select' - End If inside Select block - error 1022 */ @@ -3157,14 +3157,14 @@ static void test_parse_errors(void) " Case 1\n" "End If\n", 2, 4, - NULL, S_OK, -1022 + NULL, S_OK, 1022 }, { /* Expected 'With' - End Sub inside With block - error 1029 */ L"With CreateObject(\"Scripting.Dictionary\")\n" "End Sub\n", 1, 4, - NULL, S_OK, -1029 + NULL, S_OK, 1029 }, { /* Expected 'Property' - End Sub inside Property Get - error 1050 */ @@ -3173,7 +3173,7 @@ static void test_parse_errors(void) " End Sub\n" "End Class\n", 2, 6, - NULL, S_OK, -1050 + NULL, S_OK, 1050 }, { /* Multiple default members - error 1052 */ -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10588
From: Francis De Brabandere <francisdb@gmail.com> Return error 1006 "Expected ')'" for unclosed parentheses in expressions, error 1052 for multiple Default members in a class, and error 1058 for Default on Property Let/Set instead of Property Get. Set error locations for 1052 and 1058 to match Windows behavior. --- dlls/vbscript/parser.y | 15 +++++++++++---- dlls/vbscript/tests/run.c | 10 +++++----- 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index ab4f6250aa1..c166ba68790 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -483,6 +483,7 @@ IntegerValue PrimaryExpression : tEXPRLBRACKET Expression ')' { $$ = new_unary_expression(ctx, EXPR_BRACKETS, $2); } + | tEXPRLBRACKET Expression error { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_RPAREN); YYABORT; } | tME { $$ = new_expression(ctx, EXPR_ME, 0); CHECK_ERROR; } ClassDeclaration @@ -503,9 +504,11 @@ PropertyDecl : Storage_opt tPROPERTY tGET Identifier ArgumentsDecl_opt StSep BodyStatements tEND tPROPERTY { $$ = new_function_decl(ctx, $4, FUNC_PROPGET, @2, $1, $5, $7); CHECK_ERROR; } | Storage_opt tPROPERTY tLET Identifier '(' ArgumentDeclList ')' StSep BodyStatements tEND tPROPERTY - { $$ = new_function_decl(ctx, $4, FUNC_PROPLET, @2, $1, $6, $9); CHECK_ERROR; } + { if($1 & STORAGE_IS_DEFAULT) { ctx->error_loc = @3; ctx->hres = MAKE_VBSERROR(VBSE_DEFAULT_ONLY_ON_PROPERTY_GET); YYABORT; } + $$ = new_function_decl(ctx, $4, FUNC_PROPLET, @2, $1, $6, $9); CHECK_ERROR; } | Storage_opt tPROPERTY tSET Identifier '(' ArgumentDeclList ')' StSep BodyStatements tEND tPROPERTY - { $$ = new_function_decl(ctx, $4, FUNC_PROPSET, @2, $1, $6, $9); CHECK_ERROR; } + { if($1 & STORAGE_IS_DEFAULT) { ctx->error_loc = @3; ctx->hres = MAKE_VBSERROR(VBSE_DEFAULT_ONLY_ON_PROPERTY_GET); YYABORT; } + $$ = new_function_decl(ctx, $4, FUNC_PROPSET, @2, $1, $6, $9); CHECK_ERROR; } | Storage_opt tPROPERTY tGET Identifier ArgumentsDecl_opt StSep BodyStatements tEND error { ctx->hres = MAKE_VBSERROR(VBSE_EXPECTED_PROPERTY); YYABORT; } | Storage_opt tPROPERTY tLET Identifier '(' ArgumentDeclList ')' StSep BodyStatements tEND error @@ -1118,8 +1121,7 @@ static function_decl_t *new_function_decl(parser_ctx_t *ctx, const WCHAR *name, if(type == FUNC_PROPGET || type == FUNC_FUNCTION || type == FUNC_SUB) { is_default = TRUE; }else { - FIXME("Invalid default property\n"); - ctx->hres = E_FAIL; + ctx->hres = MAKE_VBSERROR(VBSE_DEFAULT_ONLY_ON_PROPERTY_GET); return NULL; } } @@ -1171,6 +1173,11 @@ static class_decl_t *add_class_function(parser_ctx_t *ctx, class_decl_t *class_d function_decl_t *iter; for(iter = class_decl->funcs; iter; iter = iter->next) { + if(decl->is_default && iter->is_default) { + ctx->error_loc = iter->loc; + ctx->hres = MAKE_VBSERROR(VBSE_MULTIPLE_DEFAULT_MEMBERS); + return NULL; + } if(!wcsicmp(iter->name, decl->name)) { if(decl->type == FUNC_SUB || decl->type == FUNC_FUNCTION) { ctx->hres = MAKE_VBSERROR(VBSE_NAME_REDEFINED); diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 437ecbeb715..df8602523e3 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -3127,7 +3127,7 @@ static void test_parse_errors(void) /* Expected ')' - error 1006 */ L"x = (1 + 2\n", 0, 10, - NULL, S_OK, -1006 + NULL, S_OK, 1006 }, { /* Expected 'If' - End With inside If block - error 1012 */ @@ -3185,8 +3185,8 @@ static void test_parse_errors(void) " G = 2\n" " End Function\n" "End Class\n", - -4, -17, - NULL, S_OK, -1052 + 4, 17, + NULL, S_OK, 1052 }, { /* Default only on Property Get - error 1058 */ @@ -3194,8 +3194,8 @@ static void test_parse_errors(void) " Public Default Property Let P(v)\n" " End Property\n" "End Class\n", - -1, -26, - NULL, S_OK, -1058 + 1, 26, + NULL, S_OK, 1058 } }; HRESULT hres; -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10588
This merge request was approved by Jacek Caban. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10588
participants (3)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb) -
Jacek Caban (@jacek)