diff options
author | Jo-Philipp Wich <jo@mein.io> | 2021-05-11 17:08:50 +0200 |
---|---|---|
committer | Jo-Philipp Wich <jo@mein.io> | 2021-05-11 17:34:31 +0200 |
commit | 5c4e1ea8dca744482879dfc15ed21fc24beb2775 (patch) | |
tree | 34e0d206b6db6161b4f169f2e215e3c76129268a | |
parent | fbf3dfad950310a0a7c5ae29f25312733fa9063d (diff) |
lib: implement regexp(), a function to construct regexp instances at runtime
Provide a new ucode function regexp() which allows constructing regular
expression instances from separate source and flag strings.
Signed-off-by: Jo-Philipp Wich <jo@mein.io>
-rw-r--r-- | README.md | 19 | ||||
-rw-r--r-- | lib.c | 58 |
2 files changed, 76 insertions, 1 deletions
@@ -1119,3 +1119,22 @@ is not truish. When `message` is omitted, the default value is `Assertion failed Like `include()` but capture output of included file as string and return it. See `include()` for details on scoping. + +#### 6.58. `regexp(source[, flags])` + +Construct a regular expression instance from the given `source` pattern string +and any flags optionally specified by the `flags` argument. + +Throws a type error exception if `flags` is not a string or if the string in +`flags` contains unrecognized regular expression flag characters. + +Throws a syntax error when the pattern in `source` cannot be compiled into a +valid regular expression by the underlying C runtimes `regcomp(3)` function. + +Returns the compiled regular expression value. + +```javascript +regexp('foo.*bar', 'is'); // equivalent to /foo.*bar/is +regexp('foo.*bar', 'x'); // throws "Type error: Unrecognized flag character 'x'" +regexp('foo.*('); // throws "Syntax error: Unmatched ( or \(" +``` @@ -2470,6 +2470,61 @@ uc_assert(uc_vm *vm, size_t nargs) return ucv_get(cond); } +static uc_value_t * +uc_regexp(uc_vm *vm, size_t nargs) +{ + bool icase = false, newline = false, global = false, freeable; + uc_value_t *source = uc_get_arg(0); + uc_value_t *flags = uc_get_arg(1); + uc_value_t *regex = NULL; + char *p, *err = NULL; + + if (flags) { + if (ucv_type(flags) != UC_STRING) { + uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Given flags argument is not a string"); + + return NULL; + } + + for (p = ucv_string_get(flags); *p; p++) { + switch (*p) { + case 'i': + icase = true; + break; + + case 's': + newline = true; + break; + + case 'g': + global = true; + break; + + default: + uc_vm_raise_exception(vm, EXCEPTION_TYPE, "Unrecognized flag character '%c'", *p); + + return NULL; + } + } + } + + p = uc_cast_string(vm, &source, &freeable); + regex = ucv_regexp_new(p, icase, newline, global, &err); + + if (freeable) + free(p); + + if (err) { + uc_vm_raise_exception(vm, EXCEPTION_SYNTAX, "%s", err); + ucv_put(regex); + free(err); + + return NULL; + } + + return regex; +} + static const uc_cfunction_list functions[] = { { "chr", uc_chr }, { "delete", uc_delete }, @@ -2521,7 +2576,8 @@ static const uc_cfunction_list functions[] = { { "proto", uc_proto }, { "sleep", uc_sleep }, { "assert", uc_assert }, - { "render", uc_render } + { "render", uc_render }, + { "regexp", uc_regexp } }; |