[PATCH v4 0/1] MR10318: Draft: vbscript: Allow End If on the same line as the preceding statement.
Use BodyStatements instead of StatementsNl_opt for If, ElseIf, and Else blocks so the last statement before End If does not require a trailing newline, matching native behavior. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55196 -- v4: vbscript: Allow trailing End If in Else and ElseIf blocks. https://gitlab.winehq.org/wine/wine/-/merge_requests/10318
From: Francis De Brabandere <francisdb@gmail.com> Use BodyStatements instead of StatementsNl_opt in the Else_opt and ElseIf grammar rules so that the last statement before End If does not require a trailing separator. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55196 --- dlls/vbscript/parser.y | 12 +++++--- dlls/vbscript/tests/lang.vbs | 53 ++++++++++++++++++++++++++++++++++++ dlls/vbscript/tests/run.c | 34 +++++++++++++++++++---- 3 files changed, 89 insertions(+), 10 deletions(-) diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index 20c30eed681..57010a8f238 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -144,7 +144,7 @@ static statement_t *link_statements(statement_t*,statement_t*); %type <expression> ConstExpression NumericLiteralExpression %type <member> MemberExpression %type <expression> Arguments ArgumentList ArgumentList_opt Step_opt ExpressionList -%type <boolean> DoType Preserve_opt +%type <boolean> DoType Preserve_opt ElseSep_opt %type <arg_decl> ArgumentsDecl ArgumentsDecl_opt ArgumentDeclList ArgumentDecl %type <func_decl> FunctionDecl PropertyDecl %type <elseif> ElseIfs_opt ElseIfs ElseIf @@ -325,12 +325,16 @@ ElseIfs | ElseIf ElseIfs { $1->next = $2; $$ = $1; } ElseIf - : tELSEIF Expression tTHEN StSep_opt StatementsNl_opt - { $$ = new_elseif_decl(ctx, @$, $2, $5); } + : tELSEIF Expression tTHEN StSep_opt BodyStatements + { $$ = new_elseif_decl(ctx, @$, $2, $5); } Else_opt : /* empty */ { $$ = NULL; } - | tELSE StSep_opt StatementsNl_opt { $$ = $3; } + | tELSE ElseSep_opt BodyStatements { if(!$2 && !$3) { ctx->error_loc = @1; ctx->hres = E_FAIL; YYABORT; } $$ = $3; } + +ElseSep_opt + : /* empty */ { $$ = FALSE; } + | StSep { $$ = TRUE; } CaseClausules : /* empty */ { $$ = NULL; } diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 0025bfeddcf..d70e065da50 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -359,6 +359,59 @@ ElseIf not False Then End If Call ok(x, "elseif not called?") +' Else with trailing End If on same line +x = 1 +If false Then + x = 2 +Else x = 3 End If +Call ok(x = 3, "Else with trailing End If failed") + +' Else with colon separator before End If +x = 1 +If false Then + x = 2 +Else x = 3:End If +Call ok(x = 3, "Else with colon before End If failed") + +' Else with colon then statement with trailing End If +x = 1 +If false Then + x = 2 +Else:x = 3 End If +Call ok(x = 3, "Else colon then statement with trailing End If failed") + +' Else with multiple statements and trailing End If +x = 1 +y = 1 +If false Then + x = 2 +Else x = 3:y = 4 End If +Call ok(x = 3, "Else multi-statement trailing End If failed for x") +Call ok(y = 4, "Else multi-statement trailing End If failed for y") + +' Else with body statement on next line with trailing End If +x = 1 +If false Then + x = 2 +Else + x = 3 End If +Call ok(x = 3, "Else body statement with trailing End If failed") + +' ElseIf single-line with trailing End If +x = 1 +If false Then + x = 2 +ElseIf true Then x = 3 End If +Call ok(x = 3, "ElseIf single-line with trailing End If failed") + +' Empty Else block with newline +x = 1 +If false Then + x = 2 +Else +End If +Call ok(x = 1, "empty Else block should be accepted") + x = false if 1 then x = true Call ok(x, "if 1 not run?") diff --git a/dlls/vbscript/tests/run.c b/dlls/vbscript/tests/run.c index 8aaafbedf54..953351ee1c5 100644 --- a/dlls/vbscript/tests/run.c +++ b/dlls/vbscript/tests/run.c @@ -2647,6 +2647,7 @@ static void test_parse_errors(void) const WCHAR *src; unsigned error_line; int error_char; + BOOL todo; } invalid_scripts[] = { @@ -2656,6 +2657,21 @@ static void test_parse_errors(void) " x = 0 End If\n", 1, 10 }, + { + /* ElseIf...End If */ + L"If False Then\n" + " x = 0\n" + "ElseIf True Then\n" + " x = 1 End If\n", + 3, 10, TRUE + }, + { + /* Else End If (no separator) */ + L"If False Then\n" + " x = 0\n" + "Else End If\n", + 2, -5 + }, { /* While...End While */ L"While False\n" @@ -2778,14 +2794,20 @@ static void test_parse_errors(void) SET_EXPECT(OnScriptError); hres = parse_script_wr(invalid_scripts[i].src); + todo_wine_if(invalid_scripts[i].todo) ok(hres == SCRIPT_E_REPORTED, "[%u] script returned: %08lx\n", i, hres); - CHECK_CALLED(OnScriptError); + if(hres == SCRIPT_E_REPORTED) + { + CHECK_CALLED(OnScriptError); - ok(error_line == invalid_scripts[i].error_line, "[%u] error line %lu expected %u\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", - i, error_char, invalid_scripts[i].error_char); + ok(error_line == invalid_scripts[i].error_line, "[%u] error line %lu expected %u\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", + i, error_char, invalid_scripts[i].error_char); + } + else + CLEAR_CALLED(OnScriptError); } } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10318
This merge request was closed by Francis De Brabandere. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10318
superseded by !10333 -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10318#note_132282
participants (2)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb)