summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorJo-Philipp Wich <jo@mein.io>2021-05-11 17:08:50 +0200
committerJo-Philipp Wich <jo@mein.io>2021-05-11 17:34:31 +0200
commit5c4e1ea8dca744482879dfc15ed21fc24beb2775 (patch)
tree34e0d206b6db6161b4f169f2e215e3c76129268a
parentfbf3dfad950310a0a7c5ae29f25312733fa9063d (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.md19
-rw-r--r--lib.c58
2 files changed, 76 insertions, 1 deletions
diff --git a/README.md b/README.md
index 83bfc07..b732b1e 100644
--- a/README.md
+++ b/README.md
@@ -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 \("
+```
diff --git a/lib.c b/lib.c
index 453f976..a24ed23 100644
--- a/lib.c
+++ b/lib.c
@@ -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 }
};