diff --git a/CHANGELOG.md b/CHANGELOG.md index 5c10731437..ce1bbb9338 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -26,6 +26,7 @@ #### :bug: Bug fix +- Fix JS regex literal parsing in character classes. https://github.com/rescript-lang/rescript/pull/7790 - Fix creating interface for functions with upper bounded polymorphic args. https://github.com/rescript-lang/rescript/pull/7786 #### :memo: Documentation diff --git a/compiler/syntax/src/res_scanner.ml b/compiler/syntax/src/res_scanner.ml index ee731f0ec5..7aa249d645 100644 --- a/compiler/syntax/src/res_scanner.ml +++ b/compiler/syntax/src/res_scanner.ml @@ -584,9 +584,9 @@ let scan_regex scanner = bring_buf_up_to_date ~start_offset:last_char_offset; Buffer.contents buf) in - let rec scan () = + let rec scan ?(in_char_class = false) () = match scanner.ch with - | '/' -> + | '/' when not in_char_class -> let last_char_offset = scanner.offset in next scanner; let pattern = result ~first_char_offset ~last_char_offset in @@ -610,10 +610,16 @@ let scan_regex scanner = | '\\' -> next scanner; next scanner; - scan () + scan ~in_char_class () + | '[' when not in_char_class -> + next scanner; + scan ~in_char_class:true () + | ']' when in_char_class -> + next scanner; + scan ~in_char_class:false () | _ -> next scanner; - scan () + scan ~in_char_class () in let pattern, flags = scan () in let end_pos = position scanner in diff --git a/tests/syntax_tests/data/parsing/errors/expressions/expected/regexCharacterClasses.res.txt b/tests/syntax_tests/data/parsing/errors/expressions/expected/regexCharacterClasses.res.txt new file mode 100644 index 0000000000..ccd4e67318 --- /dev/null +++ b/tests/syntax_tests/data/parsing/errors/expressions/expected/regexCharacterClasses.res.txt @@ -0,0 +1,20 @@ + + Syntax error! + syntax_tests/data/parsing/errors/expressions/regexCharacterClasses.res:1:14 + + 1 │ let re = /[]/]/ + 2 │ + + I'm not sure what to parse here when looking at "]". + + + Syntax error! + syntax_tests/data/parsing/errors/expressions/regexCharacterClasses.res:1:16 + + 1 │ let re = /[]/]/ + 2 │ + + unterminated regex + +let re = [%re {js|/[]/|js}] +;;[%re {js|//|js}] \ No newline at end of file diff --git a/tests/syntax_tests/data/parsing/errors/expressions/regexCharacterClasses.res b/tests/syntax_tests/data/parsing/errors/expressions/regexCharacterClasses.res new file mode 100644 index 0000000000..356d64c646 --- /dev/null +++ b/tests/syntax_tests/data/parsing/errors/expressions/regexCharacterClasses.res @@ -0,0 +1 @@ +let re = /[]/]/ diff --git a/tests/syntax_tests/data/parsing/grammar/expressions/expected/regex.res.txt b/tests/syntax_tests/data/parsing/grammar/expressions/expected/regex.res.txt index ccfa5e018b..0549328722 100644 --- a/tests/syntax_tests/data/parsing/grammar/expressions/expected/regex.res.txt +++ b/tests/syntax_tests/data/parsing/grammar/expressions/expected/regex.res.txt @@ -76,10 +76,7 @@ let re = [%re {js|/a[b-d]/|js}] let re = [%re {js|/a[-b]/|js}] let re = [%re {js|/a[\\-b]/|js}] let re = [%re {js|/a[]b/|js}] -let re = [%re {js|/a[/|js}] let re = [%re {js|/a\\/|js}] -let re = [%re {js|/abc)/|js}] -let re = [%re {js|/(abc/|js}] let re = [%re {js|/a]/|js}] let re = [%re {js|/a[]]b/|js}] let re = [%re {js|/a[\\]]b/|js}] @@ -239,7 +236,6 @@ let re = [%re {js|/a[-b]/|js}] let re = [%re {js|/a[b-]/|js}] let re = [%re {js|/a[b-a]/|js}] let re = [%re {js|/a[]b/|js}] -let re = [%re {js|/a[/|js}] let re = [%re {js|/a]/|js}] let re = [%re {js|/a[]]b/|js}] let re = [%re {js|/a[^bc]d/|js}] @@ -258,8 +254,6 @@ let re = [%re {js|/a\\(b/|js}] let re = [%re {js|/a\\(*b/|js}] let re = [%re {js|/a\\(*b/|js}] let re = [%re {js|/a\\\\b/|js}] -let re = [%re {js|/abc)/|js}] -let re = [%re {js|/(abc/|js}] let re = [%re {js|/((a))/|js}] let re = [%re {js|/(a)b(c)/|js}] let re = [%re {js|/a+b+c/|js}] @@ -317,134 +311,6 @@ let re = [%re {js|/[k]/|js}] let re = [%re {js|/a[-]?c/|js}] let re = [%re {js|/(abc)\\1/|js}] let re = [%re {js|/([a-c]*)\\1/|js}] -let re = [%re {js|/(?i)abc/|js}] -let re = [%re {js|/(?i)abc/|js}] -let re = [%re {js|/(?i)abc/|js}] -let re = [%re {js|/(?i)abc/|js}] -let re = [%re {js|/(?i)abc/|js}] -let re = [%re {js|/(?i)abc/|js}] -let re = [%re {js|/(?i)ab*c/|js}] -let re = [%re {js|/(?i)ab*bc/|js}] -let re = [%re {js|/(?i)ab*bc/|js}] -let re = [%re {js|/(?i)ab*?bc/|js}] -let re = [%re {js|/(?i)ab{0,}?bc/|js}] -let re = [%re {js|/(?i)ab+?bc/|js}] -let re = [%re {js|/(?i)ab+bc/|js}] -let re = [%re {js|/(?i)ab+bc/|js}] -let re = [%re {js|/(?i)ab{1,}bc/|js}] -let re = [%re {js|/(?i)ab+bc/|js}] -let re = [%re {js|/(?i)ab{1,}?bc/|js}] -let re = [%re {js|/(?i)ab{1,3}?bc/|js}] -let re = [%re {js|/(?i)ab{3,4}?bc/|js}] -let re = [%re {js|/(?i)ab{4,5}?bc/|js}] -let re = [%re {js|/(?i)ab??bc/|js}] -let re = [%re {js|/(?i)ab??bc/|js}] -let re = [%re {js|/(?i)ab{0,1}?bc/|js}] -let re = [%re {js|/(?i)ab??bc/|js}] -let re = [%re {js|/(?i)ab??c/|js}] -let re = [%re {js|/(?i)ab{0,1}?c/|js}] -let re = [%re {js|/(?i)^abc$/|js}] -let re = [%re {js|/(?i)^abc$/|js}] -let re = [%re {js|/(?i)^abc/|js}] -let re = [%re {js|/(?i)^abc$/|js}] -let re = [%re {js|/(?i)abc$/|js}] -let re = [%re {js|/(?i)^/|js}] -let re = [%re {js|/(?i)$/|js}] -let re = [%re {js|/(?i)a.c/|js}] -let re = [%re {js|/(?i)a.c/|js}] -let re = [%re {js|/(?i)a.*?c/|js}] -let re = [%re {js|/(?i)a.*c/|js}] -let re = [%re {js|/(?i)a[bc]d/|js}] -let re = [%re {js|/(?i)a[bc]d/|js}] -let re = [%re {js|/(?i)a[b-d]e/|js}] -let re = [%re {js|/(?i)a[b-d]e/|js}] -let re = [%re {js|/(?i)a[b-d]/|js}] -let re = [%re {js|/(?i)a[-b]/|js}] -let re = [%re {js|/(?i)a[b-]/|js}] -let re = [%re {js|/(?i)a[b-a]/|js}] -let re = [%re {js|/(?i)a[]b/|js}] -let re = [%re {js|/(?i)a[/|js}] -let re = [%re {js|/(?i)a]/|js}] -let re = [%re {js|/(?i)a[]]b/|js}] -let re = [%re {js|/(?i)a[^bc]d/|js}] -let re = [%re {js|/(?i)a[^bc]d/|js}] -let re = [%re {js|/(?i)a[^-b]c/|js}] -let re = [%re {js|/(?i)a[^-b]c/|js}] -let re = [%re {js|/(?i)a[^]b]c/|js}] -let re = [%re {js|/(?i)a[^]b]c/|js}] -let re = [%re {js|/(?i)ab|cd/|js}] -let re = [%re {js|/(?i)ab|cd/|js}] -let re = [%re {js|/(?i)()ef/|js}] -let re = [%re {js|/(?i)*a/|js}] -let re = [%re {js|/(?i)(*)b/|js}] -let re = [%re {js|/(?i)$b/|js}] -let re = [%re {js|/(?i)a\\/|js}] -let re = [%re {js|/(?i)a\\(b/|js}] -let re = [%re {js|/(?i)a\\(*b/|js}] -let re = [%re {js|/(?i)a\\(*b/|js}] -let re = [%re {js|/(?i)a\\\\b/|js}] -let re = [%re {js|/(?i)abc)/|js}] -let re = [%re {js|/(?i)(abc/|js}] -let re = [%re {js|/(?i)((a))/|js}] -let re = [%re {js|/(?i)(a)b(c)/|js}] -let re = [%re {js|/(?i)a+b+c/|js}] -let re = [%re {js|/(?i)a{1,}b{1,}c/|js}] -let re = [%re {js|/(?i)a**/|js}] -let re = [%re {js|/(?i)a.+?c/|js}] -let re = [%re {js|/(?i)a.*?c/|js}] -let re = [%re {js|/(?i)a.{0,5}?c/|js}] -let re = [%re {js|/(?i)(a+|b)*/|js}] -let re = [%re {js|/(?i)(a+|b){0,}/|js}] -let re = [%re {js|/(?i)(a+|b)+/|js}] -let re = [%re {js|/(?i)(a+|b){1,}/|js}] -let re = [%re {js|/(?i)(a+|b)?/|js}] -let re = [%re {js|/(?i)(a+|b){0,1}/|js}] -let re = [%re {js|/(?i)(a+|b){0,1}?/|js}] -let re = [%re {js|/(?i))(/|js}] -let re = [%re {js|/(?i)[^ab]*/|js}] -let re = [%re {js|/(?i)abc/|js}] -let re = [%re {js|/(?i)a*/|js}] -let re = [%re {js|/(?i)([abc])*d/|js}] -let re = [%re {js|/(?i)([abc])*bcd/|js}] -let re = [%re {js|/(?i)a|b|c|d|e/|js}] -let re = [%re {js|/(?i)(a|b|c|d|e)f/|js}] -let re = [%re {js|/(?i)abcd*efg/|js}] -let re = [%re {js|/(?i)ab*/|js}] -let re = [%re {js|/(?i)ab*/|js}] -let re = [%re {js|/(?i)(ab|cd)e/|js}] -let re = [%re {js|/(?i)[abhgefdc]ij/|js}] -let re = [%re {js|/(?i)^(ab|cd)e/|js}] -let re = [%re {js|/(?i)(abc|)ef/|js}] -let re = [%re {js|/(?i)(a|b)c*d/|js}] -let re = [%re {js|/(?i)(ab|ab*)bc/|js}] -let re = [%re {js|/(?i)a([bc]*)c*/|js}] -let re = [%re {js|/(?i)a([bc]*)(c*d)/|js}] -let re = [%re {js|/(?i)a([bc]+)(c*d)/|js}] -let re = [%re {js|/(?i)a([bc]*)(c+d)/|js}] -let re = [%re {js|/(?i)a[bcd]*dcdcde/|js}] -let re = [%re {js|/(?i)a[bcd]+dcdcde/|js}] -let re = [%re {js|/(?i)(ab|a)b*c/|js}] -let re = [%re {js|/(?i)((a)(b)c)(d)/|js}] -let re = [%re {js|/(?i)[a-zA-Z_][a-zA-Z0-9_]*/|js}] -let re = [%re {js|/(?i)^a(bc+|b[eh])g|.h$/|js}] -let re = [%re {js|/(?i)(bc+d$|ef*g.|h?i(j|k))/|js}] -let re = [%re {js|/(?i)(bc+d$|ef*g.|h?i(j|k))/|js}] -let re = [%re {js|/(?i)(bc+d$|ef*g.|h?i(j|k))/|js}] -let re = [%re {js|/(?i)(bc+d$|ef*g.|h?i(j|k))/|js}] -let re = [%re {js|/(?i)(bc+d$|ef*g.|h?i(j|k))/|js}] -let re = [%re {js|/(?i)((((((((((a))))))))))/|js}] -let re = [%re {js|/(?i)((((((((((a))))))))))\\10/|js}] -let re = [%re {js|/(?i)(((((((((a)))))))))/|js}] -let re = [%re {js|/(?i)(?:(?:(?:(?:(?:(?:(?:(?:(?:(a))))))))))/|js}] -let re = [%re {js|/(?i)(?:(?:(?:(?:(?:(?:(?:(?:(?:(a|b|c))))))))))/|js}] -let re = [%re {js|/(?i)multiple words of text/|js}] -let re = [%re {js|/(?i)multiple words/|js}] -let re = [%re {js|/(?i)(.*)c(.*)/|js}] -let re = [%re {js|/(?i)\\((.*), (.*)\\)/|js}] -let re = [%re {js|/(?i)[k]/|js}] -let re = [%re {js|/(?i)a[-]?c/|js}] -let re = [%re {js|/(?i)(abc)\\1/|js}] -let re = [%re {js|/(?i)([a-c]*)\\1/|js}] let re = [%re {js|/a(?!b)./|js}] let re = [%re {js|/a(?=d)./|js}] let re = [%re {js|/a(?=c|d)./|js}] @@ -499,4 +365,10 @@ let re = [%re {js|/^a*?$/|js}] let re = [%re {js|/^((a)c)?(ab)$/|js}] let re = [%re {js|/^([ab]*?)(?=(b)?)c/|js}] let re = [%re {js|/^([ab]*?)(?!(b))c/|js}] -let re = [%re {js|/^([ab]*?)(?