vbscript: Allow more keywords to be used as identifiers.

Signed-off-by: Brendan McGrath <brendan@redmandi.com>
Signed-off-by: Jacek Caban <jacek@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
(cherry picked from commit d2937bfff2)
Signed-off-by: Michael Stefaniuc <mstefani@winehq.org>
oldstable
Brendan McGrath 2019-02-15 14:06:15 +01:00 committed by Michael Stefaniuc
parent ec10ad3dbc
commit 2c3ab31c55
3 changed files with 37 additions and 13 deletions

View File

@ -156,7 +156,7 @@ static inline BOOL is_identifier_char(WCHAR c)
return isalnumW(c) || c == '_'; return isalnumW(c) || c == '_';
} }
static int check_keyword(parser_ctx_t *ctx, const WCHAR *word) static int check_keyword(parser_ctx_t *ctx, const WCHAR *word, const WCHAR **lval)
{ {
const WCHAR *p1 = ctx->ptr; const WCHAR *p1 = ctx->ptr;
const WCHAR *p2 = word; const WCHAR *p2 = word;
@ -174,17 +174,18 @@ static int check_keyword(parser_ctx_t *ctx, const WCHAR *word)
return 1; return 1;
ctx->ptr = p1; ctx->ptr = p1;
*lval = word;
return 0; return 0;
} }
static int check_keywords(parser_ctx_t *ctx) static int check_keywords(parser_ctx_t *ctx, const WCHAR **lval)
{ {
int min = 0, max = ARRAY_SIZE(keywords)-1, r, i; int min = 0, max = ARRAY_SIZE(keywords)-1, r, i;
while(min <= max) { while(min <= max) {
i = (min+max)/2; i = (min+max)/2;
r = check_keyword(ctx, keywords[i].word); r = check_keyword(ctx, keywords[i].word, lval);
if(!r) if(!r)
return keywords[i].token; return keywords[i].token;
@ -412,7 +413,7 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx)
return parse_numeric_literal(ctx, lval); return parse_numeric_literal(ctx, lval);
if(isalphaW(c)) { if(isalphaW(c)) {
int ret = check_keywords(ctx); int ret = check_keywords(ctx, lval);
if(!ret) if(!ret)
return parse_identifier(ctx, lval); return parse_identifier(ctx, lval);
if(ret != tREM) if(ret != tREM)

View File

@ -71,8 +71,6 @@ static class_decl_t *add_dim_prop(parser_ctx_t*,class_decl_t*,dim_decl_t*,unsign
static statement_t *link_statements(statement_t*,statement_t*); static statement_t *link_statements(statement_t*,statement_t*);
static const WCHAR propertyW[] = {'p','r','o','p','e','r','t','y',0};
#define STORAGE_IS_PRIVATE 1 #define STORAGE_IS_PRIVATE 1
#define STORAGE_IS_DEFAULT 2 #define STORAGE_IS_DEFAULT 2
@ -108,17 +106,18 @@ static const WCHAR propertyW[] = {'p','r','o','p','e','r','t','y',0};
%token tTRUE tFALSE %token tTRUE tFALSE
%token tNOT tAND tOR tXOR tEQV tIMP tNEQ %token tNOT tAND tOR tXOR tEQV tIMP tNEQ
%token tIS tLTEQ tGTEQ tMOD %token tIS tLTEQ tGTEQ tMOD
%token tCALL tDIM tSUB tFUNCTION tPROPERTY tGET tLET tCONST %token tCALL tDIM tSUB tFUNCTION tGET tLET tCONST
%token tIF tELSE tELSEIF tEND tTHEN tEXIT %token tIF tELSE tELSEIF tEND tTHEN tEXIT
%token tWHILE tWEND tDO tLOOP tUNTIL tFOR tTO tSTEP tEACH tIN %token tWHILE tWEND tDO tLOOP tUNTIL tFOR tTO tEACH tIN
%token tSELECT tCASE %token tSELECT tCASE
%token tBYREF tBYVAL %token tBYREF tBYVAL
%token tOPTION tEXPLICIT %token tOPTION
%token tSTOP %token tSTOP
%token tNOTHING tEMPTY tNULL %token tNOTHING tEMPTY tNULL
%token tCLASS tSET tNEW tPUBLIC tPRIVATE tDEFAULT tME %token tCLASS tSET tNEW tPUBLIC tPRIVATE tME
%token tERROR tNEXT tON tRESUME tGOTO %token tNEXT tON tRESUME tGOTO
%token <string> tIdentifier tString %token <string> tIdentifier tString
%token <string> tDEFAULT tERROR tEXPLICIT tPROPERTY tSTEP
%token <lng> tLong tShort %token <lng> tLong tShort
%token <dbl> tDouble %token <dbl> tDouble
@ -443,10 +442,14 @@ ArgumentDecl
| tBYREF Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, TRUE); } | tBYREF Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, TRUE); }
| tBYVAL Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, FALSE); } | tBYVAL Identifier EmptyBrackets_opt { $$ = new_argument_decl(ctx, $2, FALSE); }
/* 'property' may be both keyword and identifier, depending on context */ /* these keywords may also be an identifier, depending on context */
Identifier Identifier
: tIdentifier { $$ = $1; } : tIdentifier { $$ = $1; }
| tPROPERTY { $$ = propertyW; } | tDEFAULT { $$ = $1; }
| tERROR { $$ = $1; }
| tEXPLICIT { $$ = $1; }
| tPROPERTY { $$ = $1; }
| tSTEP { $$ = $1; }
/* Most statements accept both new line and ':' as separators */ /* Most statements accept both new line and ':' as separators */
StSep StSep

View File

@ -1345,4 +1345,24 @@ end class
set x = new RegExp set x = new RegExp
Call ok(x.Global = false, "x.Global = " & x.Global) Call ok(x.Global = false, "x.Global = " & x.Global)
sub test_identifiers
' test keywords that can also be a declared identifier
Dim default
default = "xx"
Call ok(default = "xx", "default = " & default & " expected ""xx""")
Dim error
error = "xx"
Call ok(error = "xx", "error = " & error & " expected ""xx""")
Dim explicit
explicit = "xx"
Call ok(explicit = "xx", "explicit = " & explicit & " expected ""xx""")
Dim step
step = "xx"
Call ok(step = "xx", "step = " & step & " expected ""xx""")
end sub
call test_identifiers()
reportSuccess() reportSuccess()