From cf1863ed09d2e2930b873f75c9aa696883a48237 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Mon, 15 Sep 2008 20:38:18 +0200 Subject: [PATCH] jscript: Added parser support for regular expressions. --- dlls/jscript/engine.h | 9 +++++++++ dlls/jscript/jscript.h | 1 + dlls/jscript/lex.c | 46 ++++++++++++++++++++++++++++++++++++++++++ dlls/jscript/parser.y | 8 +++++++- dlls/jscript/regexp.c | 42 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 105 insertions(+), 1 deletion(-) diff --git a/dlls/jscript/engine.h b/dlls/jscript/engine.h index 57a68c2812b..0d75716aaa8 100644 --- a/dlls/jscript/engine.h +++ b/dlls/jscript/engine.h @@ -18,6 +18,11 @@ typedef struct _source_elements_t source_elements_t; +typedef struct _obj_literal_t { + DispatchEx *obj; + struct _obj_literal_t *next; +} obj_literal_t; + typedef struct _parser_ctx_t { LONG ref; @@ -33,6 +38,8 @@ typedef struct _parser_ctx_t { jsheap_t tmp_heap; jsheap_t heap; + obj_literal_t *obj_literals; + struct _parser_ctx_t *next; } parser_ctx_t; @@ -105,6 +112,8 @@ typedef struct { } u; } literal_t; +literal_t *parse_regexp(parser_ctx_t*); + typedef struct _variable_declaration_t { const WCHAR *identifier; expression_t *expr; diff --git a/dlls/jscript/jscript.h b/dlls/jscript/jscript.h index a3c5c0ade85..ec42011942d 100644 --- a/dlls/jscript/jscript.h +++ b/dlls/jscript/jscript.h @@ -116,6 +116,7 @@ HRESULT create_builtin_function(script_ctx_t*,builtin_invoke_t,DWORD,DispatchEx* HRESULT create_object(script_ctx_t*,DispatchEx*,DispatchEx**); HRESULT create_math(script_ctx_t*,DispatchEx**); HRESULT create_array(script_ctx_t*,DWORD,DispatchEx**); +HRESULT create_regexp_str(script_ctx_t*,const WCHAR*,DWORD,const WCHAR*,DWORD,DispatchEx**); HRESULT to_primitive(script_ctx_t*,VARIANT*,jsexcept_t*,VARIANT*); HRESULT to_boolean(VARIANT*,VARIANT_BOOL*); diff --git a/dlls/jscript/lex.c b/dlls/jscript/lex.c index 8ae15d3fc6d..0aea118224a 100644 --- a/dlls/jscript/lex.c +++ b/dlls/jscript/lex.c @@ -684,3 +684,49 @@ int parser_lex(void *lval, parser_ctx_t *ctx) WARN("unexpected char '%c' %d\n", *ctx->ptr, *ctx->ptr); return 0; } + +static void add_object_literal(parser_ctx_t *ctx, DispatchEx *obj) +{ + obj_literal_t *literal = parser_alloc(ctx, sizeof(obj_literal_t)); + + literal->obj = obj; + literal->next = ctx->obj_literals; + ctx->obj_literals = literal; +} + +literal_t *parse_regexp(parser_ctx_t *ctx) +{ + const WCHAR *re, *flags; + DispatchEx *regexp; + literal_t *ret; + DWORD re_len; + HRESULT hres; + + TRACE("\n"); + + re = ctx->ptr; + while(ctx->ptr < ctx->end && (*ctx->ptr != '/' || *(ctx->ptr-1) == '\\')) + ctx->ptr++; + + if(ctx->ptr == ctx->end) { + WARN("unexpected end of file\n"); + return NULL; + } + + re_len = ctx->ptr-re; + + flags = ++ctx->ptr; + while(ctx->ptr < ctx->end && isalnumW(*ctx->ptr)) + ctx->ptr++; + + hres = create_regexp_str(ctx->script, re, re_len, flags, ctx->ptr-flags, ®exp); + if(FAILED(hres)) + return NULL; + + add_object_literal(ctx, regexp); + + ret = parser_alloc(ctx, sizeof(literal_t)); + ret->vt = VT_DISPATCH; + ret->u.disp = (IDispatch*)_IDispatchEx_(regexp); + return ret; +} diff --git a/dlls/jscript/parser.y b/dlls/jscript/parser.y index cc4ee7bbf52..ec5f4bd3b17 100644 --- a/dlls/jscript/parser.y +++ b/dlls/jscript/parser.y @@ -775,7 +775,8 @@ Literal | BooleanLiteral { $$ = $1; } | tNumericLiteral { $$ = $1; } | tStringLiteral { $$ = new_string_literal(ctx, $1); } - | '/' { FIXME("RegExp literal\n"); YYABORT; } + | '/' { $$ = parse_regexp(ctx); + if(!$$) YYABORT; } /* ECMA-262 3rd Edition 7.8.2 */ BooleanLiteral @@ -1509,9 +1510,14 @@ static void program_parsed(parser_ctx_t *ctx, source_elements_t *source) void parser_release(parser_ctx_t *ctx) { + obj_literal_t *iter; + if(--ctx->ref) return; + for(iter = ctx->obj_literals; iter; iter = iter->next) + jsdisp_release(iter->obj); + jsheap_free(&ctx->heap); heap_free(ctx); } diff --git a/dlls/jscript/regexp.c b/dlls/jscript/regexp.c index 88f7c3b3d0b..7c352ef9323 100644 --- a/dlls/jscript/regexp.c +++ b/dlls/jscript/regexp.c @@ -22,6 +22,11 @@ WINE_DEFAULT_DEBUG_CHANNEL(jscript); +#define JSREG_FOLD 0x01 /* fold uppercase to lowercase */ +#define JSREG_GLOB 0x02 /* global exec, creates array of matches */ +#define JSREG_MULTILINE 0x04 /* treat ^ and $ as begin and end of line */ +#define JSREG_STICKY 0x08 /* only match starting at lastIndex */ + typedef struct { DispatchEx dispex; } RegExpInstance; @@ -174,6 +179,12 @@ static HRESULT alloc_regexp(script_ctx_t *ctx, BOOL use_constr, RegExpInstance * return S_OK; } +static HRESULT create_regexp(script_ctx_t *ctx, const WCHAR *exp, int len, DWORD flags, DispatchEx **ret) +{ + FIXME("\n"); + return E_NOTIMPL; +} + static HRESULT RegExpConstr_value(DispatchEx *dispex, LCID lcid, WORD flags, DISPPARAMS *dp, VARIANT *retv, jsexcept_t *ei, IServiceProvider *sp) { @@ -195,3 +206,34 @@ HRESULT create_regexp_constr(script_ctx_t *ctx, DispatchEx **ret) jsdisp_release(®exp->dispex); return hres; } + +HRESULT create_regexp_str(script_ctx_t *ctx, const WCHAR *exp, DWORD exp_len, const WCHAR *opt, + DWORD opt_len, DispatchEx **ret) +{ + const WCHAR *p; + DWORD flags = 0; + + if(opt) { + for (p = opt; p < opt+opt_len; p++) { + switch (*p) { + case 'g': + flags |= JSREG_GLOB; + break; + case 'i': + flags |= JSREG_FOLD; + break; + case 'm': + flags |= JSREG_MULTILINE; + break; + case 'y': + flags |= JSREG_STICKY; + break; + default: + WARN("wrong flag %c\n", *p); + return E_FAIL; + } + } + } + + return create_regexp(ctx, exp, exp_len, flags, ret); +}