njs_token_t
njs_regexp_literal(njs_vm_t *vm, njs_parser_t *parser, njs_value_t *value)
{
- u_char *p, c;
+ u_char *p;
nxt_str_t text;
njs_lexer_t *lexer;
njs_regexp_flags_t flags;
for (p = lexer->start; p < lexer->end; p++) {
- c = *p;
+ switch (*p) {
+ case '\n':
+ case '\r':
+ goto failed;
+
+ case '[':
+ while (++p < lexer->end && *p != ']') {
+ switch (*p) {
+ case '\n':
+ case '\r':
+ goto failed;
+
+ case '\\':
+ if (++p < lexer->end && (*p == '\n' || *p == '\r')) {
+ goto failed;
+ }
+
+ break;
+ }
+ }
- if (c == '\n' || c == '\r') {
break;
- }
- if (c == '/' && !(p > lexer->start && p[-1] == '\\')) {
+ case '\\':
+ if (++p < lexer->end && (*p == '\n' || *p == '\r')) {
+ goto failed;
+ }
+
+ break;
+
+ case '/':
text.start = lexer->start;
text.length = p - text.start;
p++;
}
}
+failed:
+
njs_parser_syntax_error(vm, parser, "Unterminated RegExp \"%*s\"",
p - (lexer->start - 1), lexer->start - 1);
{ nxt_string("/a\\q/"),
nxt_string("/a\\q/") },
+ { nxt_string("/\\\\/"),
+ nxt_string("/\\\\/") },
+
+ { nxt_string("/\\\\\\/"),
+ nxt_string("SyntaxError: Unterminated RegExp \"/\\\\\\/\" in 1") },
+
+ { nxt_string("/\\\\\\\\/"),
+ nxt_string("/\\\\\\\\/") },
+
+ { nxt_string("/\\\\\\//"),
+ nxt_string("/\\\\\\//") },
+
+ { nxt_string("/[A-Z/]/"),
+ nxt_string("/[A-Z/]/") },
+
+ { nxt_string("/[A-Z\n]/"),
+ nxt_string("SyntaxError: Unterminated RegExp \"/[A-Z\" in 1") },
+
+ { nxt_string("/[A-Z\\\n]/"),
+ nxt_string("SyntaxError: Unterminated RegExp \"/[A-Z\\\" in 1") },
+
+ { nxt_string("/\\\n/"),
+ nxt_string("SyntaxError: Unterminated RegExp \"/\\\" in 1") },
+
+ { nxt_string("/^[A-Za-z0-9+/]{4}$/.test('////')"),
+ nxt_string("true") },
+
+ { nxt_string("'[]!\"#$%&\\'()*+,.\\/:;<=>?@\\^_`{|}-'.split('')"
+ ".every(ch=>/[\\]\\[!\"#$%&'()*+,.\\/:;<=>?@\\^_`{|}-]/.test(ch))"),
+ nxt_string("true") },
+
{ nxt_string("/a\\q/.test('a\\q')"),
nxt_string("true") },