[PATCH v5 0/1] MR10317: vbscript: Allow Not operator as operand of comparison expressions.
vbscript: Allow Not operator as operand of comparison expressions. The Not operator was only reachable from the NotExpression grammar rule, which sat above EqualityExpression in the precedence chain. This meant expressions like "a <> Not b" caused a syntax error because the right-hand side of a comparison could not contain Not. Fold Not directly into EqualityExpression as a unary prefix and use bison precedence declarations to resolve the resulting ambiguity: %right tNOT at lower precedence than %left comparison operators ensures "Not 1 = 2" parses as "Not(1 = 2)" while "a <> Not b = c" correctly lets Not capture the comparison on its right. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55093 -- v5: vbscript: Allow Not operator as operand of comparison expressions. https://gitlab.winehq.org/wine/wine/-/merge_requests/10317
From: Francis De Brabandere <francisdb@gmail.com> The Not operator was only reachable from the NotExpression grammar rule, which sat above EqualityExpression in the precedence chain. This meant expressions like "a <> Not b" caused a syntax error because the right-hand side of a comparison could not contain Not. Fold Not directly into EqualityExpression as a unary prefix and use bison precedence declarations to resolve the resulting ambiguity: %right tNOT at lower precedence than %left comparison operators ensures "Not 1 = 2" parses as "Not(1 = 2)" while "a <> Not b = c" correctly lets Not capture the comparison on its right. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55093 --- dlls/vbscript/parser.y | 30 +++++++++++++++--------------- dlls/vbscript/tests/lang.vbs | 12 ++++++++++++ 2 files changed, 27 insertions(+), 15 deletions(-) diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index 42df9afaf8f..b499df747e2 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -136,11 +136,14 @@ static statement_t *link_statements(statement_t*,statement_t*); %token <dbl> tDouble %token <date> tDate +%right tNOT +%left '=' tNEQ '>' '<' tGTEQ tLTEQ tIS + %type <statement> Statement SimpleStatement StatementNl StatementsNl StatementsNl_opt BodyStatements IfStatement Else_opt %type <statement> GlobalDimDeclaration StatementsBody StatementsBody_opt %type <expression> Expression LiteralExpression PrimaryExpression EqualityExpression CallExpression ExpressionNl_opt %type <expression> ConcatExpression AdditiveExpression ModExpression IntdivExpression MultiplicativeExpression ExpExpression -%type <expression> NotExpression UnaryExpression AndExpression OrExpression XorExpression EqvExpression SignExpression +%type <expression> UnaryExpression AndExpression OrExpression XorExpression EqvExpression SignExpression %type <expression> ConstExpression NumericLiteralExpression %type <member> MemberExpression %type <expression> Arguments ArgumentList ArgumentList_opt Step_opt ExpressionList @@ -391,22 +394,19 @@ OrExpression | OrExpression tOR AndExpression { $$ = new_binary_expression(ctx, EXPR_OR, $1, $3); CHECK_ERROR; } AndExpression - : NotExpression { $$ = $1; } - | AndExpression tAND NotExpression { $$ = new_binary_expression(ctx, EXPR_AND, $1, $3); CHECK_ERROR; } - -NotExpression - : EqualityExpression { $$ = $1; } - | tNOT NotExpression { $$ = new_unary_expression(ctx, EXPR_NOT, $2); CHECK_ERROR; } + : EqualityExpression { $$ = $1; } + | AndExpression tAND EqualityExpression { $$ = new_binary_expression(ctx, EXPR_AND, $1, $3); CHECK_ERROR; } EqualityExpression - : ConcatExpression { $$ = $1; } - | EqualityExpression '=' ConcatExpression { $$ = new_binary_expression(ctx, EXPR_EQUAL, $1, $3); CHECK_ERROR; } - | EqualityExpression tNEQ ConcatExpression { $$ = new_binary_expression(ctx, EXPR_NEQUAL, $1, $3); CHECK_ERROR; } - | EqualityExpression '>' ConcatExpression { $$ = new_binary_expression(ctx, EXPR_GT, $1, $3); CHECK_ERROR; } - | EqualityExpression '<' ConcatExpression { $$ = new_binary_expression(ctx, EXPR_LT, $1, $3); CHECK_ERROR; } - | EqualityExpression tGTEQ ConcatExpression { $$ = new_binary_expression(ctx, EXPR_GTEQ, $1, $3); CHECK_ERROR; } - | EqualityExpression tLTEQ ConcatExpression { $$ = new_binary_expression(ctx, EXPR_LTEQ, $1, $3); CHECK_ERROR; } - | EqualityExpression tIS ConcatExpression { $$ = new_binary_expression(ctx, EXPR_IS, $1, $3); CHECK_ERROR; } + : ConcatExpression { $$ = $1; } + | tNOT EqualityExpression { $$ = new_unary_expression(ctx, EXPR_NOT, $2); CHECK_ERROR; } + | EqualityExpression '=' EqualityExpression { $$ = new_binary_expression(ctx, EXPR_EQUAL, $1, $3); CHECK_ERROR; } + | EqualityExpression tNEQ EqualityExpression { $$ = new_binary_expression(ctx, EXPR_NEQUAL, $1, $3); CHECK_ERROR; } + | EqualityExpression '>' EqualityExpression { $$ = new_binary_expression(ctx, EXPR_GT, $1, $3); CHECK_ERROR; } + | EqualityExpression '<' EqualityExpression { $$ = new_binary_expression(ctx, EXPR_LT, $1, $3); CHECK_ERROR; } + | EqualityExpression tGTEQ EqualityExpression { $$ = new_binary_expression(ctx, EXPR_GTEQ, $1, $3); CHECK_ERROR; } + | EqualityExpression tLTEQ EqualityExpression { $$ = new_binary_expression(ctx, EXPR_LTEQ, $1, $3); CHECK_ERROR; } + | EqualityExpression tIS EqualityExpression { $$ = new_binary_expression(ctx, EXPR_IS, $1, $3); CHECK_ERROR; } ConcatExpression : AdditiveExpression { $$ = $1; } diff --git a/dlls/vbscript/tests/lang.vbs b/dlls/vbscript/tests/lang.vbs index 4374d7b1f25..84dafe61f7a 100644 --- a/dlls/vbscript/tests/lang.vbs +++ b/dlls/vbscript/tests/lang.vbs @@ -92,6 +92,18 @@ Call ok(not(false = true = ""), "false = true = """" is true") Call ok(not (false = false <> false = false), "false = false <> false = false is true") Call ok(not ("" <> false = false), """"" <> false = false is true") +Call ok(true <> Not true, "true <> Not true should be true") +Call ok(false <> Not false, "false <> Not false should be true") +Call ok(true = Not false, "true = Not false should be true") +Call ok(Not false = true, "Not false = true should be true") +Call ok(Not true <> true, "Not true <> true should be true") +Call ok(Not true = false, "Not true = false should be true") +Call ok(Not 1 > 2, "Not 1 > 2 should be true") +Call ok(1 <> Not 0 = 0, "1 <> Not 0 = 0 should be true") +Call ok(0 = Not 1 = 1, "0 = Not 1 = 1 should be true") +Call ok(1 > Not 5 > 3, "1 > Not 5 > 3 should be true") +Call ok(Not false And false = false, "Not false And false should be false") + Call ok(getVT(false) = "VT_BOOL", "getVT(false) is not VT_BOOL") Call ok(getVT(true) = "VT_BOOL", "getVT(true) is not VT_BOOL") Call ok(getVT("") = "VT_BSTR", "getVT("""") is not VT_BSTR") -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10317
@jacek what are your thoughts on this solution? Added even more tests to cover all cases. No extra conflicts. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10317#note_133119
participants (2)
-
Francis De Brabandere -
Francis De Brabandere (@francisdb)