Module: wine Branch: master Commit: 74ab018763337e27e785ffcec7e4cab0e0e80ddb URL: https://source.winehq.org/git/wine.git/?a=commit;h=74ab018763337e27e785ffcec...
Author: Jacek Caban jacek@codeweavers.com Date: Tue Oct 29 19:01:14 2019 +0100
vbscript: Add support for parsing with statement.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/vbscript/lex.c | 11 ++++++++++- dlls/vbscript/parse.h | 8 ++++++++ dlls/vbscript/parser.y | 22 ++++++++++++++++++++-- 3 files changed, 38 insertions(+), 3 deletions(-)
diff --git a/dlls/vbscript/lex.c b/dlls/vbscript/lex.c index 6b20d1979d..d8c5ed3004 100644 --- a/dlls/vbscript/lex.c +++ b/dlls/vbscript/lex.c @@ -88,6 +88,7 @@ static const struct { {L"until", tUNTIL}, {L"wend", tWEND}, {L"while", tWHILE}, + {L"with", tWITH}, {L"xor", tXOR} };
@@ -379,9 +380,17 @@ static int parse_next_token(void *lval, parser_ctx_t *ctx) case '/': case '^': case '\': - case '.': case '_': return *ctx->ptr++; + case '.': + /* + * We need to distinguish between '.' used as part of a member expression and + * a beginning of a dot expression (a member expression accessing with statement + * expression). + */ + c = ctx->ptr > ctx->code ? ctx->ptr[-1] : '\n'; + ctx->ptr++; + return is_identifier_char(c) || c == ')' ? '.' : tDOT; case '-': if(ctx->is_html && ctx->ptr[1] == '-' && ctx->ptr[2] == '>') return comment_line(ctx); diff --git a/dlls/vbscript/parse.h b/dlls/vbscript/parse.h index 7c333be30e..f4f8a5e5e2 100644 --- a/dlls/vbscript/parse.h +++ b/dlls/vbscript/parse.h @@ -24,6 +24,7 @@ typedef enum { EXPR_CALL, EXPR_CONCAT, EXPR_DIV, + EXPR_DOT, EXPR_DOUBLE, EXPR_EMPTY, EXPR_EQUAL, @@ -125,6 +126,7 @@ typedef enum { STAT_UNTIL, STAT_WHILE, STAT_WHILELOOP, + STAT_WITH, STAT_RETVAL } statement_type_t;
@@ -255,6 +257,12 @@ typedef struct { case_clausule_t *case_clausules; } select_statement_t;
+typedef struct { + statement_t stat; + expression_t *expr; + statement_t *body; +} with_statement_t; + typedef struct { statement_t stat; expression_t *expr; diff --git a/dlls/vbscript/parser.y b/dlls/vbscript/parser.y index b577c2146e..ffa12b2c4e 100644 --- a/dlls/vbscript/parser.y +++ b/dlls/vbscript/parser.y @@ -59,6 +59,7 @@ static statement_t *new_function_statement(parser_ctx_t*,function_decl_t*); static statement_t *new_onerror_statement(parser_ctx_t*,BOOL); static statement_t *new_const_statement(parser_ctx_t*,const_decl_t*); static statement_t *new_select_statement(parser_ctx_t*,expression_t*,case_clausule_t*); +static statement_t *new_with_statement(parser_ctx_t*,expression_t*,statement_t*);
static dim_decl_t *new_dim_decl(parser_ctx_t*,const WCHAR*,BOOL,dim_list_t*); static dim_list_t *new_dim(parser_ctx_t*,unsigned,dim_list_t*); @@ -107,14 +108,14 @@ static statement_t *link_statements(statement_t*,statement_t*);
%token tEXPRESSION tEOF tNL tEMPTYBRACKETS %token tLTEQ tGTEQ tNEQ -%token tSTOP tME tREM +%token tSTOP tME tREM tDOT %token <string> tTRUE tFALSE %token <string> tNOT tAND tOR tXOR tEQV tIMP %token <string> tIS tMOD %token <string> tCALL tDIM tSUB tFUNCTION tGET tLET tCONST %token <string> tIF tELSE tELSEIF tEND tTHEN tEXIT %token <string> tWHILE tWEND tDO tLOOP tUNTIL tFOR tTO tEACH tIN -%token <string> tSELECT tCASE +%token <string> tSELECT tCASE tWITH %token <string> tBYREF tBYVAL %token <string> tOPTION %token <string> tNOTHING tEMPTY tNULL @@ -221,10 +222,14 @@ SimpleStatement { $$ = new_foreach_statement(ctx, $3, $5, $7); } | tSELECT tCASE Expression StSep CaseClausules tEND tSELECT { $$ = new_select_statement(ctx, $3, $5); } + | tWITH Expression StSep StatementsNl_opt tEND tWITH + { $$ = new_with_statement(ctx, $2, $4); }
MemberExpression : Identifier { $$ = new_member_expression(ctx, NULL, $1); CHECK_ERROR; } | CallExpression '.' DotIdentifier { $$ = new_member_expression(ctx, $1, $3); CHECK_ERROR; } + | tDOT DotIdentifier { expression_t *dot_expr = new_expression(ctx, EXPR_DOT, sizeof(*dot_expr)); CHECK_ERROR; + $$ = new_member_expression(ctx, dot_expr, $2); CHECK_ERROR; }
DimDeclList : DimDecl { $$ = $1; } @@ -946,6 +951,19 @@ static statement_t *new_select_statement(parser_ctx_t *ctx, expression_t *expr, return &stat->stat; }
+static statement_t *new_with_statement(parser_ctx_t *ctx, expression_t *expr, statement_t *body) +{ + with_statement_t *stat; + + stat = new_statement(ctx, STAT_WITH, sizeof(*stat)); + if(!stat) + return NULL; + + stat->expr = expr; + stat->body = body; + return &stat->stat; +} + static case_clausule_t *new_case_clausule(parser_ctx_t *ctx, expression_t *expr, statement_t *stat, case_clausule_t *next) { case_clausule_t *ret;