oxc/crates/oxc_regular_expression/examples/parse_literal.rs
leaysgur 5a73a663dc refactor(regular_expression)!: Simplify public APIs (#6262)
This PR makes 2 changes to improve the existing API that are not very useful.

- Remove `(Literal)Parser` and `FlagsParser` and their ASTs
- Add `with_flags(flags_text)` helper to `ParserOptions`

Here are the details.

> Remove `(Literal)Parser` and `FlagsParser` and their ASTs

Previously, the `oxc_regular_expression` crate exposed 3 parsers.

- `(Literal)Parser`: assumes `/pattern/flags` format
- `PatternParser`: assumes `pattern` part only
- `FlagsParser`: assumes `flags` part only

However, it turns out that in actual usecases, only the `PatternParser` is actually sufficient, as the pattern and flags are validated and sliced in advance on the `oxc_parser` side.

The current usecase for `(Literal)Parser` is mostly for internal testing.

There were also some misuses of `(Literal)Parser` that restore `format!("/{pattern}/{flags}")` back and use `(Literal)Parser`.

Therefore, only `PatternParser` is now published, and unnecessary ASTs have been removed.
(This also obsoletes #5592 .)

> Added `with_flags(flags_text)` helper to `ParserOptions`

Strictly speaking, there was a subtle difference between the "flag" strings that users were aware of and the "mode" recognised by the parser.

Therefore, it was a common mistake to forget to enable `unicode_mode` when using the `v` flag.

With this helper, crate users no longer need to distinguish between flags and modes.
2024-10-03 02:47:08 +00:00

66 lines
1.9 KiB
Rust

#![allow(clippy::print_stdout)]
use oxc_allocator::Allocator;
use oxc_regular_expression::{Parser, ParserOptions};
fn main() {
let allocator = Allocator::default();
for (pattern, flags) in [
(r"ab", ""),
(r"abc", "i"),
(r"abcd", "igv"),
(r"emo👈🏻ji", "u"),
(r"ab|c", "i"),
(r"a|b+|c", "i"),
(r"a{0}|b{1,2}|c{3,}", "i"),
(r"(?=a)|(?<=b)|(?!c)|(?<!d)", "i"),
(r"\n\cM\0\x41\.", ""),
(r"\n\cM\0\x41\u1234\.", "u"),
(r"\n\cM\0\x41\u{1f600}\.", "u"),
(r"a\k<f>x\1c", "u"),
(r"(cg)(?<n>cg)(?:g)", ""),
(r"{3}", ""), // Error
(r"Em🥹j", ""),
(r"^(?=ab)\b(?!cd)(?<=ef)\B(?<!gh)$", ""),
(r"^(?<!ab)$", ""),
(r"a)", ""), // Error
(r"c]", ""),
(r"[abc]", ""),
(r"[|\]]", ""),
(r"[a&&b]", "v"),
(r"[a--b]", "v"),
(r"[a&&&]", "v"), // Error
(r"[a---]", "v"), // Error
(r"[^a--b--c]", "v"),
(r"[a[b[c[d[e[f[g[h[i[j[k[l]]]]]]]]]]]]", "v"),
(r"[\q{abc|d|e|}]", "v"),
(r"\p{Basic_Emoji}", "v"),
(r"\p{Basic_Emoji}", "u"), // Error
(r"[[^\q{}]]", "v"), // Error
(r"(?<a>)(?<a>)", ""), // Error
(r"(?noname)", "v"), // Error
(r"[\bb]", ""),
(r"a{2,1}", "v"), // Error
] {
let parser = Parser::new(
&allocator,
pattern,
ParserOptions::default().with_span_offset(1).with_flags(flags),
);
let ret = parser.parse();
let literal = format!("/{pattern}/{flags}");
println!("Parse: {literal}");
match ret {
Ok(pattern) => {
println!("{pattern:#?}");
}
Err(error) => {
let error = error.with_source_code(literal);
println!("💥 {error:?}");
}
}
println!();
}
}