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>
This commit is contained in:
parent
35e570eb09
commit
d2937bfff2
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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()
|
||||||
|
|
Loading…
Reference in New Issue