diff --git a/feature/regex.js b/feature/regex.js index 74c97c6..043db93 100644 --- a/feature/regex.js +++ b/feature/regex.js @@ -11,13 +11,19 @@ */ import { token, skip, err, next, idx, cur } from '../parse.js'; -const SLASH = 47, BSLASH = 92; +const SLASH = 47, BSLASH = 92, LBRACK = 91, RBRACK = 93; token('/', 140, a => { // left operand = division; `//` `/*` `/?` `/+` `/=` = not a regex start const c = cur.charCodeAt(idx); if (a || c === SLASH || c === 42 || c === 43 || c === 63 || c === 61) return; - const pattern = next(c => c === BSLASH ? 2 : c && c !== SLASH); // \x = 2 chars, else 1 until / + let cls = false; + const pattern = next(c => + c === BSLASH ? 2 : + c === LBRACK ? (cls = true, 1) : + c === RBRACK ? (cls = false, 1) : + c && (cls || c !== SLASH) + ); cur.charCodeAt(idx) === SLASH || err('Unterminated regex'); skip(); const flags = next(c => c === 103 || c === 105 || c === 109 || c === 115 || c === 117 || c === 121); // gimsuy diff --git a/test/feature/regex.js b/test/feature/regex.js index 8465f49..b6750d0 100644 --- a/test/feature/regex.js +++ b/test/feature/regex.js @@ -1,6 +1,7 @@ import test, { is, throws } from 'tst' import { parse, compile } from '../../subscript.js' import '../../feature/regex.js' +import '../../eval/regex.js' const run = (code, ctx = {}) => compile(parse(code))(ctx) @@ -22,6 +23,12 @@ test('regex: escapes', t => { is(parse('/a\\nb/')[1], 'a\\nb') }) +test('regex: character classes', t => { + is(parse('/[^/]+$/'), ['//', '[^/]+$']) + is(parse('/[\\]/]/')[1], '[\\]/]') + is(run('"a/b".match(/([^/]+)$/)')[1], 'b') +}) + test('regex: eval', t => { is(run('/abc/.test("abc")'), true) is(run('/abc/.test("def")'), false)