1#![warn(dead_code)]
6pub mod ast;
7use std::cell::{Cell, RefCell};
8
9use ast::{Ast, Concat, ErrorKind, GroupKind, LookaroundKind, RepetitionKind};
10use regex_syntax::{
11 ast::{
12 ClassAscii, ClassBracketed, ClassPerl, ClassSet, ClassSetBinaryOpKind, ClassSetItem,
13 ClassSetRange, ClassSetUnion, ClassUnicode, ClassUnicodeKind, ClassUnicodeOpKind,
14 HexLiteralKind, Literal, LiteralKind, Position, Span, SpecialLiteralKind,
15 },
16 hir::{
17 self,
18 translate::{Translator, TranslatorBuilder},
19 },
20 utf8::Utf8Sequences,
21};
22use resharp_algebra::{Kind, NodeId};
23
24type TB<'s> = resharp_algebra::RegexBuilder;
25
26pub struct PatternFlags {
28 pub unicode: bool,
30 pub full_unicode: bool,
32 pub case_insensitive: bool,
34 pub dot_matches_new_line: bool,
36 pub multiline: bool,
38 pub ignore_whitespace: bool,
40 pub ascii_perl_classes: bool,
43 pub expanded_ast_limit: u64,
46 pub max_list_len: usize,
49 pub max_repeat: u32,
51 pub max_depth: usize,
52}
53
54pub const DEFAULT_MAX_REPEAT: u32 = 500;
57pub const DEFAULT_EXPANDED_AST_LIMIT: u64 = 50_000;
58pub const DEFAULT_MAX_LIST_LEN: usize = 4_000;
59pub const DEFAULT_MAX_DEPTH: usize = 1_000;
60
61impl Default for PatternFlags {
62 fn default() -> Self {
63 Self {
64 unicode: true,
65 full_unicode: false,
66 case_insensitive: false,
67 dot_matches_new_line: false,
68 multiline: true,
69 ignore_whitespace: false,
70 ascii_perl_classes: false,
71 expanded_ast_limit: DEFAULT_EXPANDED_AST_LIMIT,
72 max_list_len: DEFAULT_MAX_LIST_LEN,
73 max_repeat: DEFAULT_MAX_REPEAT,
74 max_depth: DEFAULT_MAX_DEPTH,
75 }
76 }
77}
78
79#[derive(Clone, Copy, PartialEq, Debug)]
80enum WordCharKind {
81 Word,
82 NonWord,
83 MaybeWord,
84 MaybeNonWord,
85 Unknown,
86 Edge,
87}
88
89fn is_word_byte(b: u8) -> bool {
90 b.is_ascii_alphanumeric() || b == b'_'
91}
92
93fn class_set_item_word_kind(item: ®ex_syntax::ast::ClassSetItem) -> WordCharKind {
94 use regex_syntax::ast::{ClassPerlKind, ClassSetItem};
95 use WordCharKind::*;
96 match item {
97 ClassSetItem::Empty(_) => Unknown,
98 ClassSetItem::Literal(l) => {
99 if is_word_byte(l.c as u8) {
100 Word
101 } else {
102 NonWord
103 }
104 }
105 ClassSetItem::Range(r) => {
106 let all_word = (r.start.c as u8..=r.end.c as u8).all(is_word_byte);
107 let all_non = (r.start.c as u8..=r.end.c as u8).all(|b| !is_word_byte(b));
108 if all_word {
109 Word
110 } else if all_non {
111 NonWord
112 } else {
113 Unknown
114 }
115 }
116 ClassSetItem::Perl(p) => match (&p.kind, p.negated) {
117 (ClassPerlKind::Word, false) => Word,
118 (ClassPerlKind::Word, true) => NonWord,
119 (ClassPerlKind::Space, false) => NonWord,
120 (ClassPerlKind::Digit, false) => Word,
121 _ => Unknown,
122 },
123 ClassSetItem::Bracketed(b) => class_bracketed_word_kind(b),
124 ClassSetItem::Union(u) => {
125 let mut kind = Unknown;
126 for item in &u.items {
127 let k = class_set_item_word_kind(item);
128 kind = match (kind, k) {
129 (_, Unknown) => return Unknown,
130 (Unknown, _) => k,
131 (Word, Word) => Word,
132 (NonWord, NonWord) => NonWord,
133 _ => return Unknown,
134 };
135 }
136 kind
137 }
138 _ => Unknown,
139 }
140}
141
142fn utf8_codepoint_node(tb: &mut TB<'_>) -> NodeId {
143 let ascii = tb.mk_range_u8(0, 127);
144 let beta = tb.mk_range_u8(0x80, 0xBF);
145 let c0 = tb.mk_range_u8(0xC0, 0xDF);
146 let c0s = tb.mk_concats([c0, beta].into_iter());
147 let e0 = tb.mk_range_u8(0xE0, 0xEF);
148 let e0s = tb.mk_concats([e0, beta, beta].into_iter());
149 let f0 = tb.mk_range_u8(0xF0, 0xF7);
150 let f0s = tb.mk_concats([f0, beta, beta, beta].into_iter());
151 tb.mk_unions([ascii, c0s, e0s, f0s].into_iter())
152}
153
154fn unicode_ranges_to_node(ranges: &[hir::ClassUnicodeRange], tb: &mut TB<'_>) -> NodeId {
155 let mut chains: Vec<Vec<(u8, u8)>> = Vec::new();
156 for range in ranges {
157 for seq in Utf8Sequences::new(range.start(), range.end()) {
158 let sl = seq.as_slice();
159 chains.push(sl.iter().map(|s| (s.start, s.end)).collect());
160 }
161 }
162 build_utf8_chain_trie(&chains, tb)
163}
164
165fn build_utf8_chain_trie(chains: &[Vec<(u8, u8)>], tb: &mut TB<'_>) -> NodeId {
166 if chains.is_empty() {
167 return NodeId::BOT;
168 }
169 let mut leaf_set_id: Option<resharp_algebra::solver::TSetId> = None;
170 let mut rest: Vec<&Vec<(u8, u8)>> = Vec::new();
171 for c in chains {
172 if c.len() == 1 {
173 let rid = tb.solver().range_to_set_id(c[0].0, c[0].1);
174 leaf_set_id = Some(match leaf_set_id {
175 None => rid,
176 Some(acc) => tb.solver().or_id(acc, rid),
177 });
178 } else {
179 rest.push(c);
180 }
181 }
182 let mut groups: Vec<((u8, u8), Vec<Vec<(u8, u8)>>)> = Vec::new();
183 for c in &rest {
184 match groups.last_mut() {
185 Some((head, tails)) if *head == c[0] => tails.push(c[1..].to_vec()),
186 _ => groups.push((c[0], vec![c[1..].to_vec()])),
187 }
188 }
189 let mut nodes = Vec::with_capacity(groups.len() + 1);
190 if let Some(set_id) = leaf_set_id {
191 nodes.push(tb.mk_pred_from_set(set_id));
192 }
193 for (head, tails) in &groups {
194 let tail_node = build_utf8_chain_trie(tails, tb);
195 let head_node = tb.mk_range_u8(head.0, head.1);
196 nodes.push(tb.mk_concat(head_node, tail_node));
197 }
198 tb.mk_unions(nodes.into_iter())
199}
200
201fn class_bracketed_word_kind(c: ®ex_syntax::ast::ClassBracketed) -> WordCharKind {
202 use regex_syntax::ast::{ClassPerlKind, ClassSet, ClassSetItem};
203 use WordCharKind::*;
204 if c.negated {
205 return match &c.kind {
206 ClassSet::Item(ClassSetItem::Perl(p)) if p.kind == ClassPerlKind::Word => {
207 if p.negated {
208 Word
209 } else {
210 NonWord
211 }
212 }
213 _ => Unknown,
214 };
215 }
216 match &c.kind {
217 ClassSet::Item(item) => class_set_item_word_kind(item),
218 ClassSet::BinaryOp(_) => Unknown,
219 }
220}
221
222fn ascii_class_lit(span: Span, c: char) -> regex_syntax::ast::Literal {
223 regex_syntax::ast::Literal {
224 span,
225 kind: regex_syntax::ast::LiteralKind::Verbatim,
226 c,
227 }
228}
229
230fn ascii_class_range(span: Span, a: char, b: char) -> regex_syntax::ast::ClassSetItem {
231 regex_syntax::ast::ClassSetItem::Range(regex_syntax::ast::ClassSetRange {
232 span,
233 start: ascii_class_lit(span, a),
234 end: ascii_class_lit(span, b),
235 })
236}
237
238fn ascii_perl_positive(
239 span: Span,
240 kind: ®ex_syntax::ast::ClassPerlKind,
241) -> regex_syntax::ast::ClassSetItem {
242 use regex_syntax::ast::{ClassPerlKind, ClassSetItem, ClassSetUnion};
243 match kind {
244 ClassPerlKind::Digit => ascii_class_range(span, '0', '9'),
245 ClassPerlKind::Word => ClassSetItem::Union(ClassSetUnion {
246 span,
247 items: vec![
248 ascii_class_range(span, 'a', 'z'),
249 ascii_class_range(span, 'A', 'Z'),
250 ascii_class_range(span, '0', '9'),
251 ClassSetItem::Literal(ascii_class_lit(span, '_')),
252 ],
253 }),
254 ClassPerlKind::Space => ClassSetItem::Union(ClassSetUnion {
255 span,
256 items: ['\t', '\n', '\x0B', '\x0C', '\r', ' ']
257 .into_iter()
258 .map(|c| ClassSetItem::Literal(ascii_class_lit(span, c)))
259 .collect(),
260 }),
261 }
262}
263
264fn ascii_perl_set_item(
265 span: Span,
266 kind: ®ex_syntax::ast::ClassPerlKind,
267 negated: bool,
268) -> regex_syntax::ast::ClassSetItem {
269 use regex_syntax::ast::{ClassBracketed, ClassSet, ClassSetItem};
270 let positive = ascii_perl_positive(span, kind);
271 if negated {
272 ClassSetItem::Bracketed(Box::new(ClassBracketed {
273 span,
274 negated: true,
275 kind: ClassSet::Item(positive),
276 }))
277 } else {
278 positive
279 }
280}
281
282fn rewrite_ascii_perl_set(set: ®ex_syntax::ast::ClassSet) -> regex_syntax::ast::ClassSet {
283 use regex_syntax::ast::{ClassSet, ClassSetBinaryOp};
284 match set {
285 ClassSet::Item(item) => ClassSet::Item(rewrite_ascii_perl_item(item)),
286 ClassSet::BinaryOp(op) => ClassSet::BinaryOp(ClassSetBinaryOp {
287 span: op.span,
288 kind: op.kind.clone(),
289 lhs: Box::new(rewrite_ascii_perl_set(&op.lhs)),
290 rhs: Box::new(rewrite_ascii_perl_set(&op.rhs)),
291 }),
292 }
293}
294
295fn rewrite_ascii_perl_item(
296 item: ®ex_syntax::ast::ClassSetItem,
297) -> regex_syntax::ast::ClassSetItem {
298 use regex_syntax::ast::{ClassBracketed, ClassSetItem, ClassSetUnion};
299 match item {
300 ClassSetItem::Perl(p) => ascii_perl_set_item(p.span, &p.kind, p.negated),
301 ClassSetItem::Union(u) => ClassSetItem::Union(ClassSetUnion {
302 span: u.span,
303 items: u.items.iter().map(rewrite_ascii_perl_item).collect(),
304 }),
305 ClassSetItem::Bracketed(b) => ClassSetItem::Bracketed(Box::new(ClassBracketed {
306 span: b.span,
307 negated: b.negated,
308 kind: rewrite_ascii_perl_set(&b.kind),
309 })),
310 other => other.clone(),
311 }
312}
313
314#[derive(Clone, Debug, Eq, PartialEq)]
315enum Primitive {
316 Literal(Literal),
317 Assertion(ast::Assertion),
318 Dot(Span),
319 Top(Span),
320 Perl(ClassPerl),
321 Unicode(ClassUnicode),
322}
323
324impl Primitive {
325 fn span(&self) -> &Span {
326 match *self {
327 Primitive::Literal(ref x) => &x.span,
328 Primitive::Assertion(ref x) => &x.span,
329 Primitive::Dot(ref span) => span,
330 Primitive::Top(ref span) => span,
331 Primitive::Perl(ref x) => &x.span,
332 Primitive::Unicode(ref x) => &x.span,
333 }
334 }
335
336 fn into_ast(self) -> Ast {
337 match self {
338 Primitive::Literal(lit) => Ast::literal(lit),
339 Primitive::Assertion(assert) => Ast::assertion(assert),
340 Primitive::Dot(span) => Ast::dot(span),
341 Primitive::Top(span) => Ast::top(span),
342 Primitive::Perl(cls) => Ast::class_perl(cls),
343 Primitive::Unicode(cls) => Ast::class_unicode(cls),
344 }
345 }
346
347 fn into_class_set_item(self, p: &ResharpParser) -> Result<regex_syntax::ast::ClassSetItem> {
348 use self::Primitive::*;
349 use regex_syntax::ast::ClassSetItem;
350
351 match self {
352 Literal(lit) => Ok(ClassSetItem::Literal(lit)),
353 Perl(cls) => Ok(ClassSetItem::Perl(cls)),
354 Unicode(cls) => Ok(ClassSetItem::Unicode(cls)),
355 x => Err(p.error(*x.span(), ast::ErrorKind::ClassEscapeInvalid)),
356 }
357 }
358
359 fn into_class_literal(self, p: &ResharpParser) -> Result<Literal> {
360 use self::Primitive::*;
361
362 match self {
363 Literal(lit) => Ok(lit),
364 x => Err(p.error(*x.span(), ast::ErrorKind::ClassRangeLiteral)),
365 }
366 }
367}
368
369#[derive(Clone, Debug, Eq, PartialEq)]
370pub enum Either<Left, Right> {
371 Left(Left),
372 Right(Right),
373}
374
375#[derive(Clone, Debug, Eq, PartialEq)]
376pub struct ParseError {
377 pub kind: ErrorKind,
379 pattern: String,
382 pub span: Span,
384}
385
386impl std::fmt::Display for ParseError {
387 fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
388 write!(f, "{:?}: {:?}", self.kind, self.span)
389 }
390}
391impl std::error::Error for ParseError {}
392
393type Result<T> = core::result::Result<T, ParseError>;
394
395#[derive(Clone, Debug)]
396enum GroupState {
397 Group {
399 concat: Concat,
401 group: ast::Group,
403 ignore_whitespace: bool,
405 },
406 Alternation(ast::Alternation),
407 Intersection(ast::Intersection),
408}
409
410#[derive(Clone, Debug)]
411enum ClassState {
412 Open {
414 union: regex_syntax::ast::ClassSetUnion,
416 set: regex_syntax::ast::ClassBracketed,
417 },
418 Op {
421 kind: regex_syntax::ast::ClassSetBinaryOpKind,
423 lhs: regex_syntax::ast::ClassSet,
425 },
426}
427
428pub struct ResharpParser<'s> {
430 perl_classes: Vec<(bool, regex_syntax::ast::ClassPerlKind, NodeId)>,
431 unicode_classes: resharp_algebra::UnicodeClassCache,
432 pub translator: regex_syntax::hir::translate::Translator,
433 pub pattern: &'s str,
434 pos: Cell<Position>,
435 capture_index: Cell<u32>,
436 octal: bool,
437 empty_min_range: bool,
438 ignore_whitespace: Cell<bool>,
439 dot_all: Cell<bool>,
440 multiline: Cell<bool>,
441 global_unicode: bool,
442 global_full_unicode: bool,
443 global_ascii_perl: bool,
444 global_case_insensitive: bool,
445 expanded_ast_limit: u64,
446 max_list_len: usize,
447 max_repeat: u32,
448 max_depth: usize,
449 comments: RefCell<Vec<ast::Comment>>,
450 stack_group: RefCell<Vec<GroupState>>,
451 stack_class: RefCell<Vec<ClassState>>,
452 capture_names: RefCell<Vec<ast::CaptureName>>,
453 scratch: RefCell<String>,
454}
455
456fn specialize_err<T>(result: Result<T>, from: ast::ErrorKind, to: ast::ErrorKind) -> Result<T> {
457 result.map_err(|e| {
458 if e.kind == from {
459 ParseError {
460 kind: to,
461 pattern: e.pattern,
462 span: e.span,
463 }
464 } else {
465 e
466 }
467 })
468}
469
470fn is_capture_char(c: char, first: bool) -> bool {
471 if first {
472 c == '_' || c.is_alphabetic()
473 } else {
474 c == '_' || c == '.' || c == '[' || c == ']' || c.is_alphanumeric()
475 }
476}
477
478pub fn is_meta_character(c: char) -> bool {
479 matches!(
480 c,
481 '\\' | '.'
482 | '+'
483 | '*'
484 | '?'
485 | '('
486 | ')'
487 | '|'
488 | '['
489 | ']'
490 | '{'
491 | '}'
492 | '^'
493 | '$'
494 | '#'
495 | '&'
496 | '-'
497 | '~'
498 | '_'
499 )
500}
501
502pub fn escape(text: &str) -> String {
504 let mut buf = String::new();
505 escape_into(text, &mut buf);
506 buf
507}
508
509pub fn escape_into(text: &str, buf: &mut String) {
511 buf.reserve(text.len());
512 for c in text.chars() {
513 if is_meta_character(c) {
514 buf.push('\\');
515 }
516 buf.push(c);
517 }
518}
519
520pub fn is_escapeable_character(c: char) -> bool {
521 if is_meta_character(c) {
522 return true;
523 }
524 if !c.is_ascii() {
525 return false;
526 }
527 match c {
528 '0'..='9' | 'A'..='Z' | 'a'..='z' => false,
529 '<' | '>' => false,
530 _ => true,
531 }
532}
533
534fn is_hex(c: char) -> bool {
535 c.is_ascii_digit() || ('a'..='f').contains(&c) || ('A'..='F').contains(&c)
536}
537
538fn ensure_lookbehind_at_start(ast: &Ast, at_start: bool) -> core::result::Result<(), Span> {
539 match ast {
540 Ast::Concat(c) => {
541 let mut child_at_start = at_start;
542 for child in &c.asts {
543 ensure_lookbehind_at_start(child, child_at_start)?;
544 if ast_may_consume(child) {
545 child_at_start = false;
546 }
547 }
548 Ok(())
549 }
550 Ast::Alternation(a) => {
551 for child in &a.asts {
552 ensure_lookbehind_at_start(child, at_start)?;
553 }
554 Ok(())
555 }
556 Ast::Intersection(i) => {
557 for child in &i.asts {
558 ensure_lookbehind_at_start(child, at_start)?;
559 }
560 Ok(())
561 }
562 Ast::Complement(c) => ensure_lookbehind_at_start(&c.ast, at_start),
563 Ast::Group(g) => ensure_lookbehind_at_start(&g.ast, at_start),
564 Ast::Repetition(r) => ensure_lookbehind_at_start(&r.ast, at_start),
565 Ast::Lookaround(g) => {
566 match g.kind {
567 LookaroundKind::PositiveLookbehind | LookaroundKind::NegativeLookbehind => {
568 if !at_start {
569 return Err(g.span);
570 }
571 }
572 LookaroundKind::PositiveLookahead | LookaroundKind::NegativeLookahead => {}
573 }
574 ensure_lookbehind_at_start(&g.ast, true)
575 }
576 Ast::Empty(_)
577 | Ast::Flags(_)
578 | Ast::Literal(_)
579 | Ast::Dot(_)
580 | Ast::Top(_)
581 | Ast::Assertion(_)
582 | Ast::ClassUnicode(_)
583 | Ast::ClassPerl(_)
584 | Ast::ClassBracketed(_) => Ok(()),
585 }
586}
587
588fn ast_may_consume(ast: &Ast) -> bool {
589 match ast {
590 Ast::Empty(_) | Ast::Flags(_) | Ast::Assertion(_) | Ast::Lookaround(_) => false,
591 Ast::Literal(_)
592 | Ast::Dot(_)
593 | Ast::Top(_)
594 | Ast::ClassUnicode(_)
595 | Ast::ClassPerl(_)
596 | Ast::ClassBracketed(_) => true,
597 Ast::Group(g) => ast_may_consume(&g.ast),
598 Ast::Repetition(r) => {
599 if !ast_may_consume(&r.ast) {
600 return false;
601 }
602 match r.op.kind {
603 RepetitionKind::ZeroOrOne
604 | RepetitionKind::ZeroOrMore
605 | RepetitionKind::OneOrMore => true,
606 RepetitionKind::Range(ast::RepetitionRange::Exactly(0)) => false,
607 RepetitionKind::Range(ast::RepetitionRange::Bounded(_, 0)) => false,
608 RepetitionKind::Range(_) => true,
609 }
610 }
611 Ast::Alternation(a) => a.asts.iter().any(ast_may_consume),
612 Ast::Intersection(i) => i.asts.iter().any(ast_may_consume),
613 Ast::Complement(_) => true,
614 Ast::Concat(c) => c.asts.iter().any(ast_may_consume),
615 }
616}
617
618impl<'s> ResharpParser<'s> {
619 fn default_translator_builder(&self) -> TranslatorBuilder {
620 let mut trb = TranslatorBuilder::new();
621 trb.unicode(self.global_unicode);
622 trb.utf8(false);
623 trb.case_insensitive(self.global_case_insensitive);
624 trb
625 }
626
627 pub fn new(pattern: &'s str) -> Self {
628 Self::with_flags(pattern, &PatternFlags::default())
629 }
630
631 pub fn with_flags(pattern: &'s str, flags: &PatternFlags) -> Self {
632 let mut trb = TranslatorBuilder::new();
633 trb.unicode(flags.unicode);
634 trb.utf8(false);
635 trb.case_insensitive(flags.case_insensitive);
636 Self {
637 translator: trb.build(),
638 pattern,
639 perl_classes: vec![],
640 unicode_classes: resharp_algebra::UnicodeClassCache::default(),
641 pos: Cell::new(Position::new(0, 0, 0)),
642 capture_index: Cell::new(0),
643 octal: false,
644 empty_min_range: false,
645 ignore_whitespace: Cell::new(flags.ignore_whitespace),
646 dot_all: Cell::new(flags.dot_matches_new_line),
647 multiline: Cell::new(flags.multiline),
648 global_unicode: flags.unicode || flags.full_unicode || flags.ascii_perl_classes,
649 global_full_unicode: flags.full_unicode,
650 global_ascii_perl: flags.ascii_perl_classes,
651 global_case_insensitive: flags.case_insensitive,
652 expanded_ast_limit: flags.expanded_ast_limit,
653 max_list_len: flags.max_list_len,
654 max_repeat: flags.max_repeat,
655 max_depth: flags.max_depth,
656 comments: RefCell::new(vec![]),
657 stack_group: RefCell::new(vec![]),
658 stack_class: RefCell::new(vec![]),
659 capture_names: RefCell::new(vec![]),
660 scratch: RefCell::new(String::new()),
661 }
662 }
663
664 fn parser(&'_ self) -> &'_ ResharpParser<'_> {
665 self
666 }
667
668 fn pattern(&self) -> &str {
669 self.pattern
670 }
671
672 fn error(&self, span: Span, kind: ast::ErrorKind) -> ParseError {
673 ParseError {
674 kind,
675 pattern: self.pattern().to_string(),
676 span,
677 }
678 }
679
680 fn unsupported_error(&self, _: regex_syntax::hir::Error) -> ParseError {
681 self.error(
682 Span::splat(self.pos()),
683 ast::ErrorKind::UnsupportedResharpRegex,
684 )
685 }
686
687 fn offset(&self) -> usize {
688 self.parser().pos.get().offset
689 }
690
691 fn line(&self) -> usize {
692 self.parser().pos.get().line
693 }
694
695 fn column(&self) -> usize {
696 self.parser().pos.get().column
697 }
698
699 fn next_capture_index(&self, span: Span) -> Result<u32> {
700 let current = self.parser().capture_index.get();
701 let i = current
702 .checked_add(1)
703 .ok_or_else(|| self.error(span, ast::ErrorKind::CaptureLimitExceeded))?;
704 self.parser().capture_index.set(i);
705 Ok(i)
706 }
707
708 fn add_capture_name(&self, cap: &ast::CaptureName) -> Result<()> {
709 let mut names = self.parser().capture_names.borrow_mut();
710 match names.binary_search_by_key(&cap.name.as_str(), |c| c.name.as_str()) {
711 Err(i) => {
712 names.insert(i, cap.clone());
713 Ok(())
714 }
715 Ok(i) => Err(self.error(
716 cap.span,
717 ast::ErrorKind::GroupNameDuplicate {
718 original: names[i].span,
719 },
720 )),
721 }
722 }
723
724 fn ignore_whitespace(&self) -> bool {
725 self.parser().ignore_whitespace.get()
726 }
727
728 fn char(&self) -> char {
729 self.char_at(self.offset())
730 }
731
732 fn char_at(&self, i: usize) -> char {
733 self.pattern()[i..]
734 .chars()
735 .next()
736 .unwrap_or_else(|| panic!("expected char at offset {}", i))
737 }
738
739 fn bump(&self) -> bool {
740 if self.is_eof() {
741 return false;
742 }
743 let Position {
744 mut offset,
745 mut line,
746 mut column,
747 } = self.pos();
748 if self.char() == '\n' {
749 line = line.checked_add(1).unwrap();
750 column = 1;
751 } else {
752 column = column.checked_add(1).unwrap();
753 }
754 offset += self.char().len_utf8();
755 self.parser().pos.set(Position {
756 offset,
757 line,
758 column,
759 });
760 self.pattern()[self.offset()..].chars().next().is_some()
761 }
762
763 fn bump_if(&self, prefix: &str) -> bool {
764 if self.pattern()[self.offset()..].starts_with(prefix) {
765 for _ in 0..prefix.chars().count() {
766 self.bump();
767 }
768 true
769 } else {
770 false
771 }
772 }
773
774 fn is_lookaround_prefix(&self) -> Option<(bool, bool)> {
775 if self.bump_if("?=") {
776 return Some((true, true));
777 }
778 if self.bump_if("?!") {
779 return Some((true, false));
780 }
781 if self.bump_if("?<=") {
782 return Some((false, true));
783 }
784 if self.bump_if("?<!") {
785 return Some((false, false));
786 }
787 None
788 }
789
790 fn bump_and_bump_space(&self) -> bool {
791 if !self.bump() {
792 return false;
793 }
794 self.bump_space();
795 !self.is_eof()
796 }
797
798 fn bump_space(&self) {
799 if !self.ignore_whitespace() {
800 return;
801 }
802 while !self.is_eof() {
803 if self.char().is_whitespace() {
804 self.bump();
805 } else if self.char() == '#' {
806 let start = self.pos();
807 let mut comment_text = String::new();
808 self.bump();
809 while !self.is_eof() {
810 let c = self.char();
811 self.bump();
812 if c == '\n' {
813 break;
814 }
815 comment_text.push(c);
816 }
817 let comment = ast::Comment {
818 span: Span::new(start, self.pos()),
819 comment: comment_text,
820 };
821 self.parser().comments.borrow_mut().push(comment);
822 } else {
823 break;
824 }
825 }
826 }
827
828 fn peek(&self) -> Option<char> {
829 if self.is_eof() {
830 return None;
831 }
832 self.pattern()[self.offset() + self.char().len_utf8()..]
833 .chars()
834 .next()
835 }
836
837 fn peek_space(&self) -> Option<char> {
840 if !self.ignore_whitespace() {
841 return self.peek();
842 }
843 if self.is_eof() {
844 return None;
845 }
846 let mut start = self.offset() + self.char().len_utf8();
847 let mut in_comment = false;
848 for (i, c) in self.pattern()[start..].char_indices() {
849 if c.is_whitespace() {
850 continue;
851 } else if !in_comment && c == '#' {
852 in_comment = true;
853 } else if in_comment && c == '\n' {
854 in_comment = false;
855 } else {
856 start += i;
857 break;
858 }
859 }
860 self.pattern()[start..].chars().next()
861 }
862
863 fn is_eof(&self) -> bool {
864 self.offset() == self.pattern().len()
865 }
866
867 fn pos(&self) -> Position {
868 self.parser().pos.get()
869 }
870
871 fn span(&self) -> Span {
872 Span::splat(self.pos())
873 }
874
875 fn span_char(&self) -> Span {
876 let mut next = Position {
877 offset: self.offset().checked_add(self.char().len_utf8()).unwrap(),
878 line: self.line(),
879 column: self.column().checked_add(1).unwrap(),
880 };
881 if self.char() == '\n' {
882 next.line += 1;
883 next.column = 1;
884 }
885 Span::new(self.pos(), next)
886 }
887
888 #[inline(never)]
889 fn push_alternate(&self, mut concat: ast::Concat) -> Result<ast::Concat> {
890 assert_eq!(self.char(), '|');
891 concat.span.end = self.pos();
892 self.push_or_add_alternation(concat);
893 self.bump();
894 Ok(ast::Concat {
895 span: self.span(),
896 asts: vec![],
897 })
898 }
899
900 fn push_or_add_alternation(&self, concat: Concat) {
901 use self::GroupState::*;
902
903 let mut stack = self.parser().stack_group.borrow_mut();
904 if let Some(&mut Alternation(ref mut alts)) = stack.last_mut() {
905 alts.asts.push(concat.into_ast());
906 return;
907 }
908 stack.push(Alternation(ast::Alternation {
909 span: Span::new(concat.span.start, self.pos()),
910 asts: vec![concat.into_ast()],
911 }));
912 }
913
914 #[inline(never)]
915 fn push_intersect(&self, mut concat: Concat) -> Result<Concat> {
916 assert_eq!(self.char(), '&');
917 concat.span.end = self.pos();
918 self.push_or_add_intersect(concat);
919 self.bump();
920 Ok(Concat {
921 span: self.span(),
922 asts: vec![],
923 })
924 }
925
926 fn push_or_add_intersect(&self, concat: Concat) {
927 use self::GroupState::*;
928
929 let mut stack = self.parser().stack_group.borrow_mut();
930 if let Some(&mut Intersection(ref mut alts)) = stack.last_mut() {
931 alts.asts.push(concat.into_ast());
932 return;
933 }
934 stack.push(Intersection(ast::Intersection {
935 span: Span::new(concat.span.start, self.pos()),
936 asts: vec![concat.into_ast()],
937 }));
938 }
939
940 #[inline(never)]
941 fn push_group(&self, mut concat: Concat) -> Result<Concat> {
942 assert_eq!(self.char(), '(');
943 match self.parse_group()? {
944 Either::Left(set) => {
945 let ignore = set.flags.flag_state(ast::Flag::IgnoreWhitespace);
946 if let Some(v) = ignore {
947 self.parser().ignore_whitespace.set(v);
948 }
949
950 concat.asts.push(Ast::flags(set));
951 Ok(concat)
952 }
953 Either::Right(group) => {
954 let old_ignore_whitespace = self.ignore_whitespace();
955 let new_ignore_whitespace = group
956 .flags()
957 .and_then(|f| f.flag_state(ast::Flag::IgnoreWhitespace))
958 .unwrap_or(old_ignore_whitespace);
959 self.parser()
960 .stack_group
961 .borrow_mut()
962 .push(GroupState::Group {
963 concat,
964 group,
965 ignore_whitespace: old_ignore_whitespace,
966 });
967 self.parser().ignore_whitespace.set(new_ignore_whitespace);
968 Ok(Concat {
969 span: self.span(),
970 asts: vec![],
971 })
972 }
973 }
974 }
975
976 #[inline(never)]
977 fn push_compl_group(&self, concat: Concat) -> Result<Concat> {
978 assert_eq!(self.char(), '~');
979 self.bump();
980 if self.is_eof() || self.char() != '(' {
981 return Err(self.error(self.span(), ast::ErrorKind::ComplementGroupExpected));
982 }
983 let open_span = self.span_char();
984 self.bump();
985 let group = ast::Group {
986 span: open_span,
987 kind: ast::GroupKind::Complement,
988 ast: Box::new(Ast::empty(self.span())),
989 };
990
991 let old_ignore_whitespace = self.ignore_whitespace();
992 let new_ignore_whitespace = group
993 .flags()
994 .and_then(|f| f.flag_state(ast::Flag::IgnoreWhitespace))
995 .unwrap_or(old_ignore_whitespace);
996 self.parser()
997 .stack_group
998 .borrow_mut()
999 .push(GroupState::Group {
1000 concat,
1001 group,
1002 ignore_whitespace: old_ignore_whitespace,
1003 });
1004 self.parser().ignore_whitespace.set(new_ignore_whitespace);
1005 Ok(Concat {
1006 span: self.span(),
1007 asts: vec![],
1008 })
1009 }
1010
1011 #[inline(never)]
1012 fn pop_group(&self, mut group_concat: Concat) -> Result<Concat> {
1013 use self::GroupState::*;
1014 assert_eq!(self.char(), ')');
1015 let mut stack = self.parser().stack_group.borrow_mut();
1016 let topstack = stack.pop();
1017
1018 let (mut prior_concat, mut group, ignore_whitespace, alt) = match topstack {
1019 Some(Group {
1020 concat,
1021 group,
1022 ignore_whitespace,
1023 }) => (concat, group, ignore_whitespace, None),
1024 Some(Alternation(alt)) => match stack.pop() {
1025 Some(Group {
1026 concat,
1027 group,
1028 ignore_whitespace,
1029 }) => (
1030 concat,
1031 group,
1032 ignore_whitespace,
1033 Some(Either::Left::<ast::Alternation, ast::Intersection>(alt)),
1034 ),
1035 None | Some(Alternation(_)) | Some(Intersection(_)) => {
1036 return Err(self.error(self.span_char(), ast::ErrorKind::GroupUnopened));
1037 }
1038 },
1039 Some(Intersection(int)) => match stack.pop() {
1040 Some(Group {
1041 concat,
1042 group,
1043 ignore_whitespace,
1044 }) => (
1045 concat,
1046 group,
1047 ignore_whitespace,
1048 Some(Either::Right::<ast::Alternation, ast::Intersection>(int)),
1049 ),
1050 None | Some(Alternation(_)) | Some(Intersection(_)) => {
1051 return Err(self.error(self.span_char(), ast::ErrorKind::GroupUnopened));
1052 }
1053 },
1054
1055 None => {
1056 return Err(self.error(self.span_char(), ast::ErrorKind::GroupUnopened));
1057 }
1058 };
1059 self.parser().ignore_whitespace.set(ignore_whitespace);
1060 group_concat.span.end = self.pos();
1061 self.bump();
1062 group.span.end = self.pos();
1063 match alt {
1064 Some(Either::Left(mut alt)) => {
1065 alt.span.end = group_concat.span.end;
1066 alt.asts.push(group_concat.into_ast());
1067 group.ast = Box::new(alt.into_ast());
1068 }
1069 Some(Either::Right(mut int)) => {
1070 int.span.end = group_concat.span.end;
1071 int.asts.push(group_concat.into_ast());
1072 group.ast = Box::new(int.into_ast());
1073 }
1074 None => {
1075 group.ast = Box::new(group_concat.into_ast());
1076 }
1077 }
1078
1079 if group.kind == GroupKind::Complement {
1080 let complement = ast::Complement {
1081 span: self.span(),
1082 ast: group.ast,
1083 };
1084 prior_concat.asts.push(Ast::complement(complement));
1085 }
1086 else {
1088 prior_concat.asts.push(Ast::group(group));
1089 }
1090 Ok(prior_concat)
1091 }
1092
1093 #[inline(never)]
1094 fn pop_group_end(&self, mut concat: ast::Concat) -> Result<Ast> {
1095 concat.span.end = self.pos();
1096 let mut stack = self.parser().stack_group.borrow_mut();
1097 let ast = match stack.pop() {
1098 None => Ok(concat.into_ast()),
1099 Some(GroupState::Alternation(mut alt)) => {
1100 alt.span.end = self.pos();
1101 alt.asts.push(concat.into_ast());
1102 Ok(Ast::alternation(alt))
1103 }
1104 Some(GroupState::Intersection(mut int)) => {
1105 int.span.end = self.pos();
1106 int.asts.push(concat.into_ast());
1107
1108 Ok(Ast::intersection(int))
1109 }
1110 Some(GroupState::Group { group, .. }) => {
1111 return Err(self.error(group.span, ast::ErrorKind::GroupUnclosed));
1112 }
1113 };
1114 match stack.pop() {
1116 None => ast,
1117 Some(GroupState::Alternation(alt)) => {
1118 Err(self.error(alt.span, ast::ErrorKind::UnsupportedResharpRegex))
1119 }
1120 Some(GroupState::Intersection(int)) => {
1121 Err(self.error(int.span, ast::ErrorKind::UnsupportedResharpRegex))
1122 }
1123 Some(GroupState::Group { group, .. }) => {
1124 Err(self.error(group.span, ast::ErrorKind::GroupUnclosed))
1125 }
1126 }
1127 }
1128
1129 #[inline(never)]
1130 fn push_class_open(
1131 &self,
1132 parent_union: regex_syntax::ast::ClassSetUnion,
1133 ) -> Result<regex_syntax::ast::ClassSetUnion> {
1134 assert_eq!(self.char(), '[');
1135
1136 let (nested_set, nested_union) = self.parse_set_class_open()?;
1137 self.parser()
1138 .stack_class
1139 .borrow_mut()
1140 .push(ClassState::Open {
1141 union: parent_union,
1142 set: nested_set,
1143 });
1144 Ok(nested_union)
1145 }
1146
1147 #[inline(never)]
1148 fn pop_class(
1149 &self,
1150 nested_union: regex_syntax::ast::ClassSetUnion,
1151 ) -> Result<Either<regex_syntax::ast::ClassSetUnion, regex_syntax::ast::ClassBracketed>> {
1152 assert_eq!(self.char(), ']');
1153
1154 let item = regex_syntax::ast::ClassSet::Item(nested_union.into_item());
1155 let prevset = self.pop_class_op(item);
1156 let mut stack = self.parser().stack_class.borrow_mut();
1157 match stack.pop() {
1158 None => panic!("unexpected empty character class stack"),
1159 Some(ClassState::Op { .. }) => panic!("unexpected ClassState::Op"),
1160 Some(ClassState::Open { mut union, mut set }) => {
1161 self.bump();
1162 set.span.end = self.pos();
1163 set.kind = prevset;
1164 if stack.is_empty() {
1165 Ok(Either::Right(set))
1166 } else {
1167 union.push(regex_syntax::ast::ClassSetItem::Bracketed(Box::new(set)));
1168 Ok(Either::Left(union))
1169 }
1170 }
1171 }
1172 }
1173
1174 #[inline(never)]
1175 fn unclosed_class_error(&self) -> ParseError {
1176 for state in self.parser().stack_class.borrow().iter().rev() {
1177 if let ClassState::Open { ref set, .. } = *state {
1178 return self.error(set.span, ast::ErrorKind::ClassUnclosed);
1179 }
1180 }
1181 panic!("no open character class found")
1182 }
1183
1184 #[inline(never)]
1185 fn push_class_op(
1186 &self,
1187 next_kind: regex_syntax::ast::ClassSetBinaryOpKind,
1188 next_union: regex_syntax::ast::ClassSetUnion,
1189 ) -> regex_syntax::ast::ClassSetUnion {
1190 let item = regex_syntax::ast::ClassSet::Item(next_union.into_item());
1191 let new_lhs = self.pop_class_op(item);
1192 self.parser().stack_class.borrow_mut().push(ClassState::Op {
1193 kind: next_kind,
1194 lhs: new_lhs,
1195 });
1196 regex_syntax::ast::ClassSetUnion {
1197 span: self.span(),
1198 items: vec![],
1199 }
1200 }
1201
1202 #[inline(never)]
1203 fn pop_class_op(&self, rhs: regex_syntax::ast::ClassSet) -> regex_syntax::ast::ClassSet {
1204 let mut stack = self.parser().stack_class.borrow_mut();
1205 let (kind, lhs) = match stack.pop() {
1206 Some(ClassState::Op { kind, lhs }) => (kind, lhs),
1207 Some(state @ ClassState::Open { .. }) => {
1208 stack.push(state);
1209 return rhs;
1210 }
1211 None => unreachable!(),
1212 };
1213 let span = Span::new(lhs.span().start, rhs.span().end);
1214 regex_syntax::ast::ClassSet::BinaryOp(regex_syntax::ast::ClassSetBinaryOp {
1215 span,
1216 kind,
1217 lhs: Box::new(lhs),
1218 rhs: Box::new(rhs),
1219 })
1220 }
1221
1222 fn any_codepoint_node(&self, tb: &mut TB<'_>) -> NodeId {
1223 utf8_codepoint_node(tb)
1224 }
1225
1226 fn hir_to_node_id(&self, hir: &hir::Hir, tb: &mut TB<'s>) -> Result<NodeId> {
1227 match hir.kind() {
1228 hir::HirKind::Empty => Ok(NodeId::EPS),
1229 hir::HirKind::Literal(l) => {
1230 if l.0.len() == 1 {
1231 let node = tb.mk_u8(l.0[0]);
1232 Ok(node)
1233 } else {
1234 let ws: Vec<_> = l.0.iter().map(|l| tb.mk_u8(*l)).collect();
1235 let conc = tb.mk_concats(ws.iter().copied());
1236 Ok(conc)
1237 }
1238 }
1239 hir::HirKind::Class(class) => match class {
1240 hir::Class::Unicode(class_unicode) => {
1241 Ok(unicode_ranges_to_node(class_unicode.ranges(), tb))
1242 }
1243 hir::Class::Bytes(class_bytes) => {
1244 let ranges = class_bytes.ranges();
1245 let mut result = NodeId::BOT;
1246 for range in ranges {
1247 let start = range.start();
1248 let end = range.end();
1249 let node = tb.mk_range_u8(start, end);
1250 result = tb.mk_union(result, node);
1251 }
1252 Ok(result)
1253 }
1254 },
1255 hir::HirKind::Look(_) => Err(self.error(
1256 Span::splat(self.pos()),
1257 ast::ErrorKind::UnsupportedResharpRegex,
1258 )),
1259 hir::HirKind::Repetition(_) => Err(self.error(
1260 Span::splat(self.pos()),
1261 ast::ErrorKind::UnsupportedResharpRegex,
1262 )),
1263 hir::HirKind::Capture(_) => Err(self.error(
1264 Span::splat(self.pos()),
1265 ast::ErrorKind::UnsupportedResharpRegex,
1266 )),
1267 hir::HirKind::Concat(body) => {
1268 let mut result = NodeId::EPS;
1269 for child in body {
1270 let node = self.hir_to_node_id(child, tb)?;
1271 result = tb.mk_concat(result, node);
1272 }
1273 Ok(result)
1274 }
1275 hir::HirKind::Alternation(_) => Err(self.error(
1276 Span::splat(self.pos()),
1277 ast::ErrorKind::UnsupportedResharpRegex,
1278 )),
1279 }
1280 }
1281
1282 fn translate_ast_to_hir(
1283 &mut self,
1284 orig_ast: ®ex_syntax::ast::Ast,
1285 tb: &mut TB<'s>,
1286 ) -> Result<NodeId> {
1287 match self.translator.translate("", orig_ast) {
1288 Err(_) => Err(self.error(self.span(), ast::ErrorKind::UnicodeClassInvalid)),
1289 Ok(hir) => self.hir_to_node_id(&hir, tb),
1290 }
1291 }
1292
1293 fn translator_to_node_id(
1294 &mut self,
1295 orig_ast: ®ex_syntax::ast::Ast,
1296 translator: &mut Option<Translator>,
1297 tb: &mut TB<'s>,
1298 ) -> Result<NodeId> {
1299 match translator {
1300 Some(tr) => {
1301 let hir = tr
1302 .translate("", orig_ast)
1303 .map_err(|e| self.unsupported_error(e))?;
1304 self.hir_to_node_id(&hir, tb)
1305 }
1306 None => self.translate_ast_to_hir(orig_ast, tb),
1307 }
1308 }
1309
1310 fn get_class(
1311 &mut self,
1312 negated: bool,
1313 kind: regex_syntax::ast::ClassPerlKind,
1314 tb: &mut TB<'s>,
1315 ) -> Result<NodeId> {
1316 let w = self
1317 .perl_classes
1318 .iter()
1319 .find(|(c_neg, c_kind, _)| *c_kind == kind && *c_neg == negated);
1320 match w {
1321 Some((_, _, value)) => Ok(*value),
1322 None => {
1323 let translated = if self.global_ascii_perl {
1324 let pos = match kind {
1325 regex_syntax::ast::ClassPerlKind::Word => {
1326 let az = tb.mk_range_u8(b'a', b'z');
1327 let big = tb.mk_range_u8(b'A', b'Z');
1328 let dig = tb.mk_range_u8(b'0', b'9');
1329 let us = tb.mk_u8(b'_');
1330 tb.mk_unions([az, big, dig, us].into_iter())
1331 }
1332 regex_syntax::ast::ClassPerlKind::Digit => tb.mk_range_u8(b'0', b'9'),
1333 regex_syntax::ast::ClassPerlKind::Space => {
1334 let sp = tb.mk_u8(b' ');
1335 let tab = tb.mk_u8(b'\t');
1336 let nl = tb.mk_u8(b'\n');
1337 let cr = tb.mk_u8(b'\r');
1338 let ff = tb.mk_u8(0x0C);
1339 let vt = tb.mk_u8(0x0B);
1340 tb.mk_unions([sp, tab, nl, cr, ff, vt].into_iter())
1341 }
1342 };
1343 if negated {
1344 resharp_algebra::neg_class(tb, pos)
1345 } else {
1346 pos
1347 }
1348 } else if self.global_unicode {
1349 match kind {
1350 regex_syntax::ast::ClassPerlKind::Word => {
1351 if self.global_full_unicode {
1352 self.unicode_classes.ensure_word_full(tb);
1353 } else {
1354 self.unicode_classes.ensure_word(tb);
1355 }
1356 if negated {
1357 self.unicode_classes.non_word
1358 } else {
1359 self.unicode_classes.word
1360 }
1361 }
1362 regex_syntax::ast::ClassPerlKind::Digit => {
1363 if self.global_full_unicode {
1364 self.unicode_classes.ensure_digit_full(tb);
1365 } else {
1366 self.unicode_classes.ensure_digit(tb);
1367 }
1368 if negated {
1369 self.unicode_classes.non_digit
1370 } else {
1371 self.unicode_classes.digit
1372 }
1373 }
1374 regex_syntax::ast::ClassPerlKind::Space => {
1375 if self.global_full_unicode {
1376 self.unicode_classes.ensure_space_full(tb);
1377 } else {
1378 self.unicode_classes.ensure_space(tb);
1379 }
1380 if negated {
1381 self.unicode_classes.non_space
1382 } else {
1383 self.unicode_classes.space
1384 }
1385 }
1386 }
1387 } else {
1388 let pos = match kind {
1389 regex_syntax::ast::ClassPerlKind::Word => {
1390 let az = tb.mk_range_u8(b'a', b'z');
1391 let big = tb.mk_range_u8(b'A', b'Z');
1392 let dig = tb.mk_range_u8(b'0', b'9');
1393 let us = tb.mk_u8(b'_');
1394 tb.mk_unions([az, big, dig, us].into_iter())
1395 }
1396 regex_syntax::ast::ClassPerlKind::Digit => tb.mk_range_u8(b'0', b'9'),
1397 regex_syntax::ast::ClassPerlKind::Space => {
1398 let sp = tb.mk_u8(b' ');
1399 let tab = tb.mk_u8(b'\t');
1400 let nl = tb.mk_u8(b'\n');
1401 let cr = tb.mk_u8(b'\r');
1402 let ff = tb.mk_u8(0x0C);
1403 let vt = tb.mk_u8(0x0B);
1404 tb.mk_unions([sp, tab, nl, cr, ff, vt].into_iter())
1405 }
1406 };
1407 if negated {
1408 resharp_algebra::neg_class(tb, pos)
1410 } else {
1411 pos
1412 }
1413 };
1414 self.perl_classes.push((negated, kind, translated));
1415 Ok(translated)
1416 }
1417 }
1418 }
1419
1420 fn word_char_kind(ast: &Ast, left: bool) -> WordCharKind {
1421 use WordCharKind::*;
1422 match ast {
1423 Ast::Literal(lit) => {
1424 if is_word_byte(lit.c as u8) {
1425 Word
1426 } else {
1427 NonWord
1428 }
1429 }
1430 Ast::ClassPerl(c) => match (&c.kind, c.negated) {
1431 (®ex_syntax::ast::ClassPerlKind::Word, false) => Word,
1432 (®ex_syntax::ast::ClassPerlKind::Word, true) => NonWord,
1433 (®ex_syntax::ast::ClassPerlKind::Space, false) => NonWord,
1434 (®ex_syntax::ast::ClassPerlKind::Space, true) => Unknown,
1435 (®ex_syntax::ast::ClassPerlKind::Digit, false) => Word,
1436 (®ex_syntax::ast::ClassPerlKind::Digit, true) => Unknown,
1437 },
1438 Ast::ClassBracketed(c) => class_bracketed_word_kind(c),
1439 Ast::Dot(_) | Ast::Top(_) => Unknown,
1440 Ast::Group(g) => Self::word_char_kind(&g.ast, left),
1441 Ast::Concat(c) if !c.asts.is_empty() => {
1442 let dir: isize = if left { -1 } else { 1 };
1443 let edge = match Self::concat_edge_index(&c.asts, left) {
1444 Some(e) => e,
1445 None => return Unknown,
1446 };
1447 let kind = Self::word_char_kind(&c.asts[edge], left);
1448 match kind {
1449 MaybeWord => {
1450 match Self::concat_neighbor_kind(&c.asts, edge, dir) {
1451 Word => Word,
1452 Edge => MaybeWord,
1453 _ => Unknown,
1454 }
1455 }
1456 MaybeNonWord => {
1457 match Self::concat_neighbor_kind(&c.asts, edge, dir) {
1458 NonWord => NonWord,
1459 Edge => MaybeNonWord,
1460 _ => Unknown,
1461 }
1462 }
1463 other => other,
1464 }
1465 }
1466 Ast::Alternation(alt) if !alt.asts.is_empty() => {
1467 let first = Self::word_char_kind(&alt.asts[0], left);
1468 if alt.asts[1..]
1469 .iter()
1470 .all(|a| Self::word_char_kind(a, left) == first)
1471 {
1472 first
1473 } else {
1474 Unknown
1475 }
1476 }
1477 Ast::Repetition(r) => {
1478 let inner = Self::word_char_kind(&r.ast, left);
1479 let nullable = matches!(
1480 &r.op.kind,
1481 ast::RepetitionKind::ZeroOrMore
1482 | ast::RepetitionKind::ZeroOrOne
1483 | ast::RepetitionKind::Range(
1484 ast::RepetitionRange::Bounded(0, _)
1485 | ast::RepetitionRange::Exactly(0)
1486 )
1487 );
1488 if nullable {
1489 match inner {
1490 Word => MaybeWord,
1491 NonWord => MaybeNonWord,
1492 _ => Unknown,
1493 }
1494 } else {
1495 inner
1496 }
1497 }
1498 Ast::Lookaround(la) => match la.kind {
1499 ast::LookaroundKind::PositiveLookahead
1500 | ast::LookaroundKind::PositiveLookbehind => Self::word_char_kind(&la.ast, left),
1501 _ => Unknown,
1502 },
1503 Ast::Assertion(a) => match (&a.kind, left) {
1504 (ast::AssertionKind::EndText, false) => NonWord,
1505 (ast::AssertionKind::StartText, true) => NonWord,
1506 _ => Unknown,
1507 },
1508 _ => Unknown,
1509 }
1510 }
1511
1512 fn edge_class_ast(ast: &Ast, left: bool) -> Option<&Ast> {
1514 match ast {
1515 Ast::Literal(_)
1516 | Ast::ClassPerl(_)
1517 | Ast::ClassBracketed(_)
1518 | Ast::ClassUnicode(_)
1519 | Ast::Dot(_)
1520 | Ast::Top(_) => Some(ast),
1521 Ast::Group(g) => Self::edge_class_ast(&g.ast, left),
1522 Ast::Concat(c) if !c.asts.is_empty() => {
1523 Self::concat_edge_index(&c.asts, left)
1524 .and_then(|e| Self::edge_class_ast(&c.asts[e], left))
1525 }
1526 Ast::Repetition(r) => {
1527 let nullable = matches!(
1528 &r.op.kind,
1529 ast::RepetitionKind::ZeroOrMore
1530 | ast::RepetitionKind::ZeroOrOne
1531 | ast::RepetitionKind::Range(
1532 ast::RepetitionRange::Bounded(0, _)
1533 | ast::RepetitionRange::Exactly(0)
1534 )
1535 );
1536 if nullable {
1537 None
1538 } else {
1539 Self::edge_class_ast(&r.ast, left)
1540 }
1541 }
1542 _ => None,
1543 }
1544 }
1545
1546 fn resolve_word_kind(
1547 &mut self,
1548 asts: &[Ast],
1549 idx: usize,
1550 dir: isize,
1551 translator: &mut Option<Translator>,
1552 tb: &mut TB<'s>,
1553 word_id: NodeId,
1554 not_word_id: NodeId,
1555 ) -> Result<WordCharKind> {
1556 use WordCharKind::*;
1557 let fast = Self::concat_neighbor_kind(asts, idx, dir);
1558 if fast != Unknown {
1559 return Ok(fast);
1560 }
1561 let neighbor_idx = (idx as isize + dir) as usize;
1562 let node = if let Some(edge) = Self::edge_class_ast(&asts[neighbor_idx], dir < 0) {
1563 self.ast_to_node_id(edge, translator, tb)?
1564 } else if dir > 0 {
1565 let mut bodies: Vec<NodeId> = vec![];
1566 let mut j = neighbor_idx;
1567 while j < asts.len() {
1568 match &asts[j] {
1569 Ast::Lookaround(la) => {
1570 let kind = la.kind.clone();
1571 let lookbehind = matches!(
1572 kind,
1573 ast::LookaroundKind::PositiveLookbehind
1574 | ast::LookaroundKind::NegativeLookbehind
1575 );
1576 if lookbehind {
1577 j += 1;
1578 continue;
1579 }
1580 let body = self.ast_to_node_id(&la.ast, translator, tb)?;
1581 let body = tb.try_elim_lookarounds(body).ok_or_else(|| {
1582 self.error(self.span(), ast::ErrorKind::UnsupportedResharpRegex)
1583 })?;
1584 let body_ts = tb.mk_concat(body, NodeId::TS);
1585 let constraint = match kind {
1586 ast::LookaroundKind::PositiveLookahead => body_ts,
1587 ast::LookaroundKind::NegativeLookahead => tb.mk_compl(body_ts),
1588 _ => unreachable!(),
1589 };
1590 bodies.push(constraint);
1591 j += 1;
1592 }
1593 other => {
1594 let n = self.ast_to_node_id(other, translator, tb)?;
1595 let n = tb.try_elim_lookarounds(n).ok_or_else(|| {
1596 self.error(self.span(), ast::ErrorKind::UnsupportedResharpRegex)
1597 })?;
1598 bodies.push(tb.mk_concat(n, NodeId::TS));
1599 break;
1600 }
1601 }
1602 }
1603 if bodies.is_empty() {
1604 return Ok(Unknown);
1605 }
1606 let combined = tb.mk_inters(bodies.into_iter());
1607 let word_prefix = tb.mk_concat(word_id, NodeId::TS);
1608 let non_word_prefix = tb.mk_concat(not_word_id, NodeId::TS);
1609 return if tb.subsumes(word_prefix, combined) == Some(true) {
1610 Ok(Word)
1611 } else if tb.subsumes(non_word_prefix, combined) == Some(true) {
1612 Ok(NonWord)
1613 } else {
1614 Ok(Unknown)
1615 };
1616 } else {
1617 let neighbor_node = self.ast_to_node_id(&asts[neighbor_idx], translator, tb)?;
1618 let neighbor_node = Self::strip_trailing_lookahead(tb, neighbor_node);
1619 let mut neighbor_node = tb
1620 .try_elim_lookarounds(neighbor_node)
1621 .ok_or_else(|| self.error(self.span(), ast::ErrorKind::UnsupportedResharpRegex))?;
1622 neighbor_node = tb.reverse(neighbor_node).or_else(|_| {
1623 Err(self.error(self.span(), ast::ErrorKind::UnsupportedResharpRegex))
1624 })?;
1625 let word_prefix = tb.mk_concat(word_id, NodeId::TS);
1626 let non_word_prefix = tb.mk_concat(not_word_id, NodeId::TS);
1627 return if tb.subsumes(word_prefix, neighbor_node) == Some(true) {
1628 Ok(Word)
1629 } else if tb.subsumes(non_word_prefix, neighbor_node) == Some(true) {
1630 Ok(NonWord)
1631 } else {
1632 Ok(Unknown)
1633 };
1634 };
1635 if tb.subsumes(word_id, node) == Some(true) {
1636 Ok(Word)
1637 } else if tb.subsumes(not_word_id, node) == Some(true) {
1638 Ok(NonWord)
1639 } else {
1640 Ok(Unknown)
1641 }
1642 }
1643
1644 fn strip_trailing_lookahead(tb: &mut TB<'s>, node: NodeId) -> NodeId {
1645 match tb.get_kind(node) {
1646 Kind::Lookahead if tb.get_min_max_length(node).1 == 0 => NodeId::EPS,
1647 Kind::Concat => {
1648 let l = node.left(tb);
1649 let r = node.right(tb);
1650 let stripped_r = Self::strip_trailing_lookahead(tb, r);
1651 if stripped_r == NodeId::EPS {
1652 Self::strip_trailing_lookahead(tb, l)
1653 } else if stripped_r == r {
1654 node
1655 } else {
1656 tb.mk_concat(l, stripped_r)
1657 }
1658 }
1659 _ => node,
1660 }
1661 }
1662
1663 fn concat_edge_index(asts: &[Ast], left: bool) -> Option<usize> {
1664 let dir: isize = if left { -1 } else { 1 };
1665 let mut e = if left { asts.len() as isize - 1 } else { 0 };
1666 while e >= 0
1667 && (e as usize) < asts.len()
1668 && Self::is_transparent_for_dir(&asts[e as usize], dir)
1669 {
1670 e += dir;
1671 }
1672 if e < 0 || e as usize >= asts.len() {
1673 None
1674 } else {
1675 Some(e as usize)
1676 }
1677 }
1678
1679 fn is_transparent_for_dir(ast: &Ast, dir: isize) -> bool {
1680 match ast {
1681 Ast::Lookaround(la) => match la.kind {
1682 ast::LookaroundKind::PositiveLookahead | ast::LookaroundKind::NegativeLookahead => {
1683 dir < 0
1684 }
1685 ast::LookaroundKind::PositiveLookbehind
1686 | ast::LookaroundKind::NegativeLookbehind => dir > 0,
1687 },
1688 Ast::Repetition(r) => matches!(
1689 &r.op.kind,
1690 ast::RepetitionKind::Range(ast::RepetitionRange::Exactly(0))
1691 ),
1692 _ => false,
1693 }
1694 }
1695
1696 fn concat_neighbor_kind(asts: &[Ast], idx: usize, dir: isize) -> WordCharKind {
1697 use WordCharKind::*;
1698 let next = idx as isize + dir;
1699 if next < 0 || next >= asts.len() as isize {
1700 return Edge;
1701 }
1702 if Self::is_transparent_for_dir(&asts[next as usize], dir) {
1703 return Self::concat_neighbor_kind(asts, next as usize, dir);
1704 }
1705 let kind = Self::word_char_kind(&asts[next as usize], dir < 0);
1706 match kind {
1707 MaybeWord => match Self::concat_neighbor_kind(asts, next as usize, dir) {
1708 Word => Word,
1709 _ => Unknown,
1710 },
1711 MaybeNonWord => match Self::concat_neighbor_kind(asts, next as usize, dir) {
1712 NonWord => NonWord,
1713 _ => Unknown,
1714 },
1715 other => other,
1716 }
1717 }
1718
1719 fn specialize_word_boundaries(
1720 &mut self,
1721 children: &mut [NodeId],
1722 tb: &mut TB<'s>,
1723 ) -> Result<()> {
1724 let wb = self.unicode_classes.wb;
1725 let non_wb = self.unicode_classes.non_wb;
1726 if wb == NodeId::MISSING {
1727 return Ok(());
1728 }
1729 let word = self.unicode_classes.word;
1730 let non_word = self.unicode_classes.non_word;
1731 if word == NodeId::MISSING {
1732 return Ok(());
1733 }
1734 let word_pref = tb.mk_concat(word, NodeId::TS);
1737 let non_word_pref = tb.mk_concat(non_word, NodeId::TS);
1738 let word_suf = tb.mk_concat(NodeId::TS, word);
1739 let non_word_suf = tb.mk_concat(NodeId::TS, non_word);
1740 let len = children.len();
1741 for k in 0..len {
1742 let l = if k == 0 {
1743 WordCharKind::Edge
1744 } else {
1745 use resharp_algebra::Kind;
1746 if tb.get_kind(children[k - 1]) == Kind::End
1747 && (children[k] == wb || children[k] == non_wb)
1748 {
1749 return Err(
1750 self.error(self.span(), ast::ErrorKind::UnsupportedResharpRegex)
1751 );
1752 }
1753 Self::classify(tb, children[k - 1], word_suf, non_word_suf)
1754 };
1755 let r = if k + 1 >= len {
1756 WordCharKind::Edge
1757 } else {
1758 Self::classify(tb, children[k + 1], word_pref, non_word_pref)
1759 };
1760 children[k] = Self::rewrite_wb_in_node(tb, children[k], wb, non_wb, word, l, r)
1761 .ok_or_else(|| self.error(self.span(), ast::ErrorKind::UnsupportedResharpRegex))?;
1762 }
1763 Ok(())
1764 }
1765
1766 fn rewrite_wb_in_node(
1767 b: &mut TB<'s>,
1768 node: NodeId,
1769 wb: NodeId,
1770 non_wb: NodeId,
1771 word: NodeId,
1772 left: WordCharKind,
1773 right: WordCharKind,
1774 ) -> Option<NodeId> {
1775 let boundary_match = if node == wb {
1776 true
1777 } else if node == non_wb {
1778 false
1779 } else if b.get_kind(node) == Kind::Union {
1780 let l = Self::rewrite_wb_in_node(b, node.left(b), wb, non_wb, word, left, right)?;
1781 let r = Self::rewrite_wb_in_node(b, node.right(b), wb, non_wb, word, left, right)?;
1782 return Some(b.mk_union(l, r));
1783 } else {
1784 return Some(node);
1785 };
1786 use WordCharKind::*;
1787 let result = match (left, right) {
1788 (NonWord, Word) | (Word, NonWord) => {
1789 if boundary_match {
1790 NodeId::EPS
1791 } else {
1792 NodeId::BOT
1793 }
1794 }
1795 (Word, Word) | (NonWord, NonWord) => {
1796 if boundary_match {
1797 NodeId::BOT
1798 } else {
1799 NodeId::EPS
1800 }
1801 }
1802 (Word, _) => {
1803 if boundary_match {
1804 b.mk_neg_lookahead(word, 0)
1805 } else {
1806 let tail = b.mk_concat(word, NodeId::TS);
1807 b.mk_lookahead(tail, NodeId::MISSING, 0)
1808 }
1809 }
1810 (NonWord, _) => {
1811 if boundary_match {
1812 let tail = b.mk_concat(word, NodeId::TS);
1813 b.mk_lookahead(tail, NodeId::MISSING, 0)
1814 } else {
1815 b.mk_neg_lookahead(word, 0)
1816 }
1817 }
1818 (_, Word) => {
1819 if boundary_match {
1820 b.mk_neg_lookbehind(word)
1821 } else {
1822 b.mk_lookbehind(word, NodeId::MISSING)
1823 }
1824 }
1825 (_, NonWord) => {
1826 if boundary_match {
1827 b.mk_lookbehind(word, NodeId::MISSING)
1828 } else {
1829 b.mk_neg_lookbehind(word)
1830 }
1831 }
1832 _ => return Some(node),
1833 };
1834 Some(result)
1835 }
1836
1837 fn classify(
1838 b: &mut TB<'s>,
1839 node: NodeId,
1840 word_dir: NodeId,
1841 non_word_dir: NodeId,
1842 ) -> WordCharKind {
1843 if b.contains_look(node) || b.contains_anchors(node) {
1844 return WordCharKind::Unknown;
1845 }
1846 if b.subsumes(word_dir, node) == Some(true) {
1847 WordCharKind::Word
1848 } else if b.subsumes(non_word_dir, node) == Some(true) {
1849 WordCharKind::NonWord
1850 } else {
1851 WordCharKind::Unknown
1852 }
1853 }
1854
1855 fn rewrite_word_boundary_in_concat(
1856 &mut self,
1857 asts: &[Ast],
1858 idx: usize,
1859 translator: &mut Option<Translator>,
1860 tb: &mut TB<'s>,
1861 negated: bool,
1862 ) -> Result<(NodeId, usize)> {
1863 use WordCharKind::*;
1864 if self.global_full_unicode {
1865 self.unicode_classes.ensure_word_full(tb);
1866 } else if self.global_unicode && !self.global_ascii_perl {
1867 self.unicode_classes.ensure_word(tb);
1868 } else {
1869 self.unicode_classes.ensure_word_ascii(tb);
1870 }
1871 let word_id = self.unicode_classes.word;
1872 let not_word_id = self.unicode_classes.non_word;
1873 let left = self.resolve_word_kind(asts, idx, -1, translator, tb, word_id, not_word_id)?;
1874 let right = self.resolve_word_kind(asts, idx, 1, translator, tb, word_id, not_word_id)?;
1875 let boundary_match = !negated;
1876 match (left, right) {
1877 (NonWord, Word) | (Word, NonWord) => Ok((
1878 if boundary_match {
1879 NodeId::EPS
1880 } else {
1881 NodeId::BOT
1882 },
1883 idx + 1,
1884 )),
1885 (Word, Word) | (NonWord, NonWord) => Ok((
1886 if boundary_match {
1887 NodeId::BOT
1888 } else {
1889 NodeId::EPS
1890 },
1891 idx + 1,
1892 )),
1893 (Word, _) => {
1894 if boundary_match {
1895 Ok((tb.mk_neg_lookahead(word_id, 0), idx + 1))
1896 } else {
1897 let tail = tb.mk_concat(word_id, NodeId::TS);
1898 self.merge_boundary_with_following_lookaheads(asts, idx, tail, translator, tb)
1899 }
1900 }
1901 (NonWord, _) => {
1902 if boundary_match {
1903 let tail = tb.mk_concat(word_id, NodeId::TS);
1904 self.merge_boundary_with_following_lookaheads(asts, idx, tail, translator, tb)
1905 } else {
1906 Ok((tb.mk_neg_lookahead(word_id, 0), idx + 1))
1907 }
1908 }
1909 (_, Word) => {
1910 if boundary_match {
1911 Ok((tb.mk_neg_lookbehind(word_id), idx + 1))
1912 } else {
1913 Ok((tb.mk_lookbehind(word_id, NodeId::MISSING), idx + 1))
1914 }
1915 }
1916 (_, NonWord) => {
1917 if boundary_match {
1918 Ok((tb.mk_lookbehind(word_id, NodeId::MISSING), idx + 1))
1919 } else {
1920 Ok((tb.mk_neg_lookbehind(word_id), idx + 1))
1921 }
1922 }
1923 _ => {
1927 self.unicode_classes.ensure_wb(tb);
1928 let node = if boundary_match {
1929 self.unicode_classes.wb
1930 } else {
1931 self.unicode_classes.non_wb
1932 };
1933 Ok((node, idx + 1))
1934 }
1935 }
1936 }
1937
1938 fn merge_boundary_with_following_lookaheads(
1939 &mut self,
1940 asts: &[Ast],
1941 wb_idx: usize,
1942 boundary_tail: NodeId,
1943 translator: &mut Option<Translator>,
1944 tb: &mut TB<'s>,
1945 ) -> Result<(NodeId, usize)> {
1946 let mut next = wb_idx + 1;
1947 let mut la_bodies = vec![boundary_tail];
1948 while next < asts.len() {
1949 match &asts[next] {
1950 Ast::Lookaround(la) if la.kind == ast::LookaroundKind::PositiveLookahead => {
1951 let body = self.ast_to_node_id(&la.ast, translator, tb)?;
1952 la_bodies.push(tb.mk_concat(body, NodeId::TS));
1953 next += 1;
1954 }
1955 _ => break,
1956 }
1957 }
1958 let merged = tb.mk_inters(la_bodies.into_iter());
1959 Ok((tb.mk_lookahead(merged, NodeId::MISSING, 0), next))
1960 }
1961
1962 fn ast_to_node_id(
1963 &mut self,
1964 ast: &Ast,
1965 translator: &mut Option<Translator>,
1966 tb: &mut TB<'s>,
1967 ) -> Result<NodeId> {
1968 match ast {
1969 Ast::Empty(_) => Ok(NodeId::EPS),
1970 Ast::Flags(f) => {
1971 if f.flags.flag_state(ast::Flag::SwapGreed).is_some() {
1972 return Err(self.error(f.span, ast::ErrorKind::UnsupportedResharpRegex));
1973 }
1974 let mut translator_builder = self.default_translator_builder();
1975 if let Some(state) = f.flags.flag_state(ast::Flag::CaseInsensitive) {
1976 translator_builder.case_insensitive(state);
1977 }
1978 if let Some(state) = f.flags.flag_state(ast::Flag::Unicode) {
1979 translator_builder.unicode(state);
1980 }
1981 if let Some(state) = f.flags.flag_state(ast::Flag::DotMatchesNewLine) {
1982 self.dot_all.set(state);
1983 }
1984 if let Some(state) = f.flags.flag_state(ast::Flag::MultiLine) {
1985 self.multiline.set(state);
1986 }
1987 let concat_translator = Some(translator_builder.build());
1988 *translator = concat_translator;
1989 Ok(NodeId::EPS)
1990 }
1991 Ast::Literal(l) => {
1992 let ast_lit = regex_syntax::ast::Ast::literal(*l.to_owned());
1993 self.translator_to_node_id(&ast_lit, translator, tb)
1994 }
1995 Ast::Top(_) => Ok(NodeId::TOP),
1996 Ast::Dot(_) => {
1997 let codepoint_dot = self.global_ascii_perl || self.global_full_unicode;
1998 let hirv = match (codepoint_dot, self.dot_all.get()) {
1999 (true, true) => hir::Hir::dot(hir::Dot::AnyChar),
2000 (true, false) => hir::Hir::dot(hir::Dot::AnyCharExceptLF),
2001 (false, true) => return Ok(NodeId::TOP),
2002 (false, false) => hir::Hir::dot(hir::Dot::AnyByteExceptLF),
2003 };
2004 self.hir_to_node_id(&hirv, tb)
2005 }
2006 Ast::Assertion(a) => match &a.kind {
2007 ast::AssertionKind::StartText => Ok(NodeId::BEGIN),
2008 ast::AssertionKind::EndText => Ok(NodeId::END),
2009 ast::AssertionKind::WordBoundary => {
2010 let only = Ast::Assertion(a.clone());
2011 let asts = std::slice::from_ref(&only);
2012 let (node, _) =
2013 self.rewrite_word_boundary_in_concat(asts, 0, translator, tb, false)?;
2014 Ok(node)
2015 }
2016 ast::AssertionKind::NotWordBoundary => {
2017 let only = Ast::Assertion(a.clone());
2019 let asts = std::slice::from_ref(&only);
2020 let (node, _) =
2021 self.rewrite_word_boundary_in_concat(asts, 0, translator, tb, true)?;
2022 Ok(node)
2023 }
2024 ast::AssertionKind::StartLine => {
2025 if !self.multiline.get() {
2026 return Ok(NodeId::BEGIN);
2027 }
2028 let left = NodeId::BEGIN;
2029 let right = tb.mk_u8(b'\n');
2030 let union = tb.mk_union(left, right);
2031 Ok(tb.mk_lookbehind(union, NodeId::MISSING))
2032 }
2033 ast::AssertionKind::EndLine => {
2034 if !self.multiline.get() {
2035 return Ok(NodeId::END);
2036 }
2037 let left = NodeId::END;
2038 let right = tb.mk_u8(b'\n');
2039 let union = tb.mk_union(left, right);
2040 Ok(tb.mk_lookahead(union, NodeId::MISSING, 0))
2041 }
2042 ast::AssertionKind::WordBoundaryStart => {
2043 Err(self.error(a.span, ast::ErrorKind::UnsupportedResharpRegex))
2044 }
2045 ast::AssertionKind::WordBoundaryEnd => {
2046 Err(self.error(a.span, ast::ErrorKind::UnsupportedResharpRegex))
2047 }
2048 ast::AssertionKind::WordBoundaryStartAngle => {
2049 Err(self.error(a.span, ast::ErrorKind::UnsupportedResharpRegex))
2050 }
2051 ast::AssertionKind::WordBoundaryEndAngle => {
2052 Err(self.error(a.span, ast::ErrorKind::UnsupportedResharpRegex))
2053 }
2054 ast::AssertionKind::WordBoundaryStartHalf => {
2055 Err(self.error(a.span, ast::ErrorKind::UnsupportedResharpRegex))
2056 }
2057 ast::AssertionKind::WordBoundaryEndHalf => {
2058 Err(self.error(a.span, ast::ErrorKind::UnsupportedResharpRegex))
2059 }
2060 },
2061 Ast::ClassUnicode(c) => {
2062 let tmp = regex_syntax::ast::ClassUnicode {
2063 span: c.span,
2064 negated: c.negated,
2065 kind: c.kind.clone(),
2066 };
2067 if !c.negated {
2068 if let regex_syntax::ast::ClassUnicodeKind::Named(s) = &c.kind {
2069 match s.as_str() {
2070 "ascii" => return Ok(tb.mk_range_u8(0, 127)),
2072 "utf8" => return Ok(utf8_codepoint_node(tb)),
2074 "hex" => {
2075 let nums = tb.mk_range_u8(b'0', b'9');
2076 let lets = tb.mk_range_u8(b'a', b'f');
2077 let lets2 = tb.mk_range_u8(b'A', b'F');
2078 let merged = tb.mk_unions([nums, lets, lets2].into_iter());
2079 return Ok(merged);
2080 }
2081 _ => {}
2082 }
2083 };
2084 }
2085
2086 let orig_ast = regex_syntax::ast::Ast::class_unicode(tmp);
2087 self.translator_to_node_id(&orig_ast, translator, tb)
2088 }
2089 Ast::ClassPerl(c) => self.get_class(c.negated, c.kind.clone(), tb),
2090 Ast::ClassBracketed(c) => match &c.kind {
2091 regex_syntax::ast::ClassSet::Item(item) => {
2092 if !c.negated && is_universal_perl_pair(item) {
2093 if self.global_ascii_perl || self.global_full_unicode {
2094 return Ok(self.any_codepoint_node(tb));
2095 }
2096 return Ok(NodeId::TOP);
2097 }
2098 if let regex_syntax::ast::ClassSetItem::Perl(p) = item {
2099 return self.get_class(c.negated ^ p.negated, p.kind.clone(), tb);
2100 }
2101 let kind = if self.global_ascii_perl {
2102 rewrite_ascii_perl_set(&c.kind)
2103 } else {
2104 c.kind.clone()
2105 };
2106 let tmp = regex_syntax::ast::ClassBracketed {
2107 span: c.span,
2108 negated: c.negated,
2109 kind,
2110 };
2111 let orig_ast = regex_syntax::ast::Ast::class_bracketed(tmp);
2112 self.translator_to_node_id(&orig_ast, translator, tb)
2113 }
2114 regex_syntax::ast::ClassSet::BinaryOp(_) => {
2115 Err(self.error(c.span, ast::ErrorKind::UnsupportedResharpRegex))
2116 }
2117 },
2118 Ast::Repetition(r) => {
2119 let body = self.ast_to_node_id(&r.ast, translator, tb);
2120 match body {
2121 Ok(body) => match &r.op.kind {
2122 ast::RepetitionKind::ZeroOrOne => Ok(tb.mk_opt(body)),
2123 ast::RepetitionKind::ZeroOrMore => Ok(tb.mk_star(body)),
2124 ast::RepetitionKind::OneOrMore => Ok(tb.mk_plus(body)),
2125 ast::RepetitionKind::Range(r) => match r {
2126 ast::RepetitionRange::Exactly(n) => Ok(tb.mk_repeat(body, *n, *n)),
2127 ast::RepetitionRange::AtLeast(n) => {
2128 let rep = tb.mk_repeat(body, *n, *n);
2129 let st = tb.mk_star(body);
2130 Ok(tb.mk_concat(rep, st))
2131 }
2132
2133 ast::RepetitionRange::Bounded(n, m) => Ok(tb.mk_repeat(body, *n, *m)),
2134 },
2135 },
2136 Err(_) => body,
2137 }
2138 }
2139 Ast::Lookaround(g) => {
2140 let body = self.ast_to_node_id(&g.ast, translator, tb)?;
2141 match g.kind {
2142 ast::LookaroundKind::PositiveLookahead if body.contains_lookbehind(tb) => {
2143 let mut prefix = NodeId::EPS;
2144 let mut rest = body;
2145 while tb.get_kind(rest) == Kind::Concat
2146 && tb.get_kind(rest.left(tb)) == Kind::Lookbehind
2147 {
2148 prefix = tb.mk_concat(prefix, rest.left(tb));
2149 rest = rest.right(tb);
2150 }
2151 if prefix == NodeId::EPS || rest.contains_lookbehind(tb) {
2152 return Err(self.error(g.span, ast::ErrorKind::UnsupportedResharpRegex));
2153 }
2154 let la = tb.mk_lookahead(rest, NodeId::MISSING, 0);
2155 Ok(tb.mk_concat(prefix, la))
2156 }
2157 ast::LookaroundKind::NegativeLookahead if body.contains_lookbehind(tb) => {
2158 Err(self.error(g.span, ast::ErrorKind::UnsupportedResharpRegex))
2159 }
2160 ast::LookaroundKind::PositiveLookahead => {
2161 Ok(tb.mk_lookahead(body, NodeId::MISSING, 0))
2162 }
2163 ast::LookaroundKind::PositiveLookbehind
2164 | ast::LookaroundKind::NegativeLookbehind
2165 if body.contains_lookahead(tb) =>
2166 {
2167 Err(self.error(g.span, ast::ErrorKind::UnsupportedResharpRegex))
2168 }
2169 ast::LookaroundKind::PositiveLookbehind => {
2170 Ok(tb.mk_lookbehind(body, NodeId::MISSING))
2171 }
2172 ast::LookaroundKind::NegativeLookahead => Ok(tb.mk_neg_lookahead(body, 0)),
2173 ast::LookaroundKind::NegativeLookbehind => Ok(tb.mk_neg_lookbehind(body)),
2174 }
2175 }
2176 Ast::Group(g) => {
2177 if let ast::GroupKind::NonCapturing(ref flags) = g.kind {
2178 if !flags.items.is_empty() {
2179 let mut translator_builder = self.default_translator_builder();
2180 if let Some(state) = flags.flag_state(ast::Flag::CaseInsensitive) {
2181 translator_builder.case_insensitive(state);
2182 }
2183 if let Some(state) = flags.flag_state(ast::Flag::Unicode) {
2184 translator_builder.unicode(state);
2185 }
2186 let saved_dot_all = self.dot_all.get();
2187 if let Some(state) = flags.flag_state(ast::Flag::DotMatchesNewLine) {
2188 self.dot_all.set(state);
2189 }
2190 let saved_multiline = self.multiline.get();
2191 if let Some(state) = flags.flag_state(ast::Flag::MultiLine) {
2192 self.multiline.set(state);
2193 }
2194 let mut scoped = Some(translator_builder.build());
2195 let result = self.ast_to_node_id(&g.ast, &mut scoped, tb);
2196 self.dot_all.set(saved_dot_all);
2197 self.multiline.set(saved_multiline);
2198 return result;
2199 }
2200 }
2201 self.ast_to_node_id(&g.ast, translator, tb)
2202 }
2203 Ast::Alternation(a) => {
2204 let mut children = vec![];
2205 for ast in &a.asts {
2206 match self.ast_to_node_id(ast, translator, tb) {
2207 Ok(node_id) => children.push(node_id),
2208 Err(err) => return Err(err),
2209 }
2210 }
2211 Ok(tb.mk_unions(children.iter().copied()))
2212 }
2213 Ast::Concat(c) => {
2214 let mut concat_translator: Option<Translator> = None;
2215 let mut children = vec![];
2216 let mut prev_boundary_child: Option<usize> = None;
2217 let mut i = 0;
2218 while i < c.asts.len() {
2219 let ast = &c.asts[i];
2220 match ast {
2221 Ast::Flags(f) => {
2222 if f.flags.flag_state(ast::Flag::SwapGreed).is_some() {
2223 return Err(
2224 self.error(f.span, ast::ErrorKind::UnsupportedResharpRegex)
2225 );
2226 }
2227 let mut translator_builder = self.default_translator_builder();
2228 if let Some(state) = f.flags.flag_state(ast::Flag::CaseInsensitive) {
2229 translator_builder.case_insensitive(state);
2230 }
2231 if let Some(state) = f.flags.flag_state(ast::Flag::Unicode) {
2232 translator_builder.unicode(state);
2233 }
2234 if let Some(state) = f.flags.flag_state(ast::Flag::DotMatchesNewLine) {
2235 self.dot_all.set(state);
2236 }
2237 if let Some(state) = f.flags.flag_state(ast::Flag::MultiLine) {
2238 self.multiline.set(state);
2239 }
2240 concat_translator = Some(translator_builder.build());
2241 *translator = concat_translator.clone();
2242 i += 1;
2243 continue;
2244 }
2245 Ast::Assertion(a)
2246 if a.kind == ast::AssertionKind::WordBoundary
2247 || a.kind == ast::AssertionKind::NotWordBoundary =>
2248 {
2249 let negated = a.kind == ast::AssertionKind::NotWordBoundary;
2250 let node = self.rewrite_word_boundary_in_concat(
2251 &c.asts, i, translator, tb, negated,
2252 )?;
2253 match prev_boundary_child {
2254 Some(idx) => children[idx] = tb.mk_inter(children[idx], node.0),
2255 None => {
2256 children.push(node.0);
2257 prev_boundary_child = Some(children.len() - 1);
2258 }
2259 }
2260 i = node.1; continue;
2262 }
2263 _ => {}
2264 }
2265 match concat_translator {
2266 Some(_) => match self.ast_to_node_id(ast, &mut concat_translator, tb) {
2267 Ok(node_id) => {
2268 if node_id != resharp_algebra::NodeId::EPS {
2269 prev_boundary_child = None;
2270 children.push(node_id);
2271 }
2272 }
2273 Err(err) => return Err(err),
2274 },
2275 None => match self.ast_to_node_id(ast, translator, tb) {
2276 Ok(node_id) => {
2277 if node_id != resharp_algebra::NodeId::EPS {
2278 prev_boundary_child = None;
2279 children.push(node_id);
2280 }
2281 }
2282 Err(err) => return Err(err),
2283 },
2284 }
2285 i += 1;
2286 }
2287 self.specialize_word_boundaries(&mut children, tb)?;
2288 Ok(tb.mk_concats(children.iter().cloned()))
2289 }
2290 Ast::Intersection(intersection) => {
2291 let mut children = vec![];
2292 for ast in &intersection.asts {
2293 match self.ast_to_node_id(ast, translator, tb) {
2294 Ok(node_id) => children.push(node_id),
2295 Err(err) => return Err(err),
2296 }
2297 }
2298 Ok(tb.mk_inters(children.into_iter()))
2299 }
2300 Ast::Complement(complement) => {
2301 let body = self.ast_to_node_id(&complement.ast, translator, tb);
2302 body.map(|x| tb.mk_compl(x))
2303 }
2304 }
2305 }
2306
2307 fn parse_inner(&mut self) -> Result<Ast> {
2308 let mut concat = Concat {
2309 span: self.span(),
2310 asts: vec![],
2311 };
2312 loop {
2313 self.bump_space();
2314 if self.is_eof() {
2315 break;
2316 }
2317 match self.char() {
2318 '(' => concat = self.push_group(concat)?,
2319 ')' => concat = self.pop_group(concat)?,
2320 '|' => concat = self.push_alternate(concat)?,
2321 '&' => concat = self.push_intersect(concat)?,
2322 '~' => concat = self.push_compl_group(concat)?,
2323 '[' => {
2324 let class = self.parse_set_class()?;
2325 concat.asts.push(Ast::class_bracketed(class));
2326 }
2327 '?' => {
2328 concat =
2329 self.parse_uncounted_repetition(concat, ast::RepetitionKind::ZeroOrOne)?;
2330 }
2331 '*' => {
2332 concat =
2333 self.parse_uncounted_repetition(concat, ast::RepetitionKind::ZeroOrMore)?;
2334 }
2335 '+' => {
2336 concat =
2337 self.parse_uncounted_repetition(concat, ast::RepetitionKind::OneOrMore)?;
2338 }
2339 '{' => {
2340 concat = self.parse_counted_repetition(concat)?;
2341 }
2342 _ => concat.asts.push(self.parse_primitive()?.into_ast()),
2343 }
2344 if self.stack_group.borrow().len() > self.max_depth {
2345 return Err(self.error(self.span(), ast::ErrorKind::UnsupportedResharpRegex));
2346 }
2347 }
2348 let ast = self.pop_group_end(concat)?;
2349 if expanded_ast_size(&ast, self.expanded_ast_limit) >= self.expanded_ast_limit
2350 || max_concat_length(&ast) >= self.max_list_len
2351 {
2352 return Err(self.error(*ast.span(), ast::ErrorKind::UnsupportedResharpRegex));
2353 }
2354 Ok(ast)
2355 }
2356
2357 fn parse(&mut self, tb: &mut TB<'s>) -> Result<NodeId> {
2358 let ast = self.parse_inner()?;
2359 if let Err(span) = ensure_lookbehind_at_start(&ast, true) {
2360 return Err(self.error(span, ast::ErrorKind::UnsupportedResharpRegex));
2361 }
2362 self.ast_to_node_id(&ast, &mut None, tb)
2363 }
2364
2365 #[inline(never)]
2366 fn parse_uncounted_repetition(
2367 &self,
2368 mut concat: ast::Concat,
2369 kind: ast::RepetitionKind,
2370 ) -> Result<ast::Concat> {
2371 let op_start = self.pos();
2373 let ast = match concat.asts.pop() {
2374 Some(ast) => ast,
2375 None => return Err(self.error(self.span(), ast::ErrorKind::RepetitionMissing)),
2376 };
2377 match ast {
2378 Ast::Empty(_) | Ast::Flags(_) => {
2379 return Err(self.error(self.span(), ast::ErrorKind::RepetitionMissing))
2380 }
2381 _ => {}
2382 }
2383 if self.bump() && self.char() == '?' {
2384 return Err(self.error(
2385 Span::new(op_start, self.pos()),
2386 ast::ErrorKind::UnsupportedLazyQuantifier,
2387 ));
2388 }
2389 concat.asts.push(Ast::repetition(ast::Repetition {
2390 span: ast.span().with_end(self.pos()),
2391 op: ast::RepetitionOp {
2392 span: Span::new(op_start, self.pos()),
2393 kind,
2394 },
2395 greedy: true,
2396 ast: Box::new(ast),
2397 }));
2398 Ok(concat)
2399 }
2400
2401 #[inline(never)]
2402 fn parse_counted_repetition(&self, mut concat: ast::Concat) -> Result<ast::Concat> {
2403 assert!(self.char() == '{');
2404 let start = self.pos();
2405 let ast = match concat.asts.pop() {
2406 Some(ast) => ast,
2407 None => return Err(self.error(self.span(), ast::ErrorKind::RepetitionMissing)),
2408 };
2409 match ast {
2410 Ast::Empty(_) | Ast::Flags(_) => {
2411 return Err(self.error(self.span(), ast::ErrorKind::RepetitionMissing))
2412 }
2413 _ => {}
2414 }
2415 if !self.bump_and_bump_space() {
2416 return Err(self.error(
2417 Span::new(start, self.pos()),
2418 ast::ErrorKind::RepetitionCountUnclosed,
2419 ));
2420 }
2421 let count_start = specialize_err(
2422 self.parse_decimal(),
2423 ast::ErrorKind::DecimalEmpty,
2424 ast::ErrorKind::RepetitionCountDecimalEmpty,
2425 );
2426 if self.is_eof() {
2427 return Err(self.error(
2428 Span::new(start, self.pos()),
2429 ast::ErrorKind::RepetitionCountUnclosed,
2430 ));
2431 }
2432 let range = if self.char() == ',' {
2433 if !self.bump_and_bump_space() {
2434 return Err(self.error(
2435 Span::new(start, self.pos()),
2436 ast::ErrorKind::RepetitionCountUnclosed,
2437 ));
2438 }
2439 if self.char() != '}' {
2440 let count_start = match count_start {
2441 Ok(c) => c,
2442 Err(err) if err.kind == ast::ErrorKind::RepetitionCountDecimalEmpty => {
2443 if self.parser().empty_min_range {
2444 0
2445 } else {
2446 return Err(err);
2447 }
2448 }
2449 err => err?,
2450 };
2451 let count_end = specialize_err(
2452 self.parse_decimal(),
2453 ast::ErrorKind::DecimalEmpty,
2454 ast::ErrorKind::RepetitionCountDecimalEmpty,
2455 )?;
2456 ast::RepetitionRange::Bounded(count_start, count_end)
2457 } else {
2458 ast::RepetitionRange::AtLeast(count_start?)
2459 }
2460 } else {
2461 ast::RepetitionRange::Exactly(count_start?)
2462 };
2463
2464 if self.is_eof() || self.char() != '}' {
2465 return Err(self.error(
2466 Span::new(start, self.pos()),
2467 ast::ErrorKind::RepetitionCountUnclosed,
2468 ));
2469 }
2470
2471 if self.bump_and_bump_space() && self.char() == '?' {
2472 return Err(self.error(
2473 Span::new(start, self.pos()),
2474 ast::ErrorKind::UnsupportedLazyQuantifier,
2475 ));
2476 }
2477
2478 let op_span = Span::new(start, self.pos());
2479 if !range.is_valid() {
2480 return Err(self.error(op_span, ast::ErrorKind::RepetitionCountInvalid));
2481 }
2482
2483 let over_limit = match &range {
2484 ast::RepetitionRange::Exactly(n) => *n > self.max_repeat,
2485 ast::RepetitionRange::AtLeast(n) => *n > self.max_repeat,
2486 ast::RepetitionRange::Bounded(n, m) => *n > self.max_repeat || *m > self.max_repeat,
2487 };
2488 if over_limit {
2489 return Err(self.error(op_span, ast::ErrorKind::UnsupportedResharpRegex));
2490 }
2491 concat.asts.push(Ast::repetition(ast::Repetition {
2492 span: ast.span().with_end(self.pos()),
2493 op: ast::RepetitionOp {
2494 span: op_span,
2495 kind: ast::RepetitionKind::Range(range),
2496 },
2497 greedy: true,
2498 ast: Box::new(ast),
2499 }));
2500 Ok(concat)
2501 }
2502
2503 #[inline(never)]
2504 fn parse_group(&self) -> Result<Either<ast::SetFlags, ast::Group>> {
2505 assert_eq!(self.char(), '(');
2506 let open_span = self.span_char();
2507 self.bump();
2508 self.bump_space();
2509 if let Some((ahead, pos)) = self.is_lookaround_prefix() {
2510 let kind = match (pos, ahead) {
2511 (true, true) => LookaroundKind::PositiveLookahead,
2512 (true, false) => LookaroundKind::PositiveLookbehind,
2513 (false, true) => LookaroundKind::NegativeLookahead,
2514 (false, false) => LookaroundKind::NegativeLookbehind,
2515 };
2516 return Ok(Either::Right(ast::Group {
2517 span: open_span,
2518 kind: ast::GroupKind::Lookaround(kind),
2519 ast: Box::new(Ast::empty(self.span())),
2520 }));
2521 }
2522 let inner_span = self.span();
2523 let mut starts_with_p = true;
2524 if self.bump_if("?P<") || {
2525 starts_with_p = false;
2526 self.bump_if("?<")
2527 } {
2528 let capture_index = self.next_capture_index(open_span)?;
2529 let name = self.parse_capture_name(capture_index)?;
2530 Ok(Either::Right(ast::Group {
2531 span: open_span,
2532 kind: ast::GroupKind::CaptureName {
2533 starts_with_p,
2534 name,
2535 },
2536 ast: Box::new(Ast::empty(self.span())),
2537 }))
2538 } else if self.bump_if("?") {
2539 if self.is_eof() {
2540 return Err(self.error(open_span, ast::ErrorKind::GroupUnclosed));
2541 }
2542 let flags = self.parse_flags()?;
2543 let char_end = self.char();
2544 self.bump();
2545 if char_end == ')' {
2546 if flags.items.is_empty() {
2549 return Err(self.error(inner_span, ast::ErrorKind::RepetitionMissing));
2550 }
2551 Ok(Either::Left(ast::SetFlags {
2552 span: Span {
2553 end: self.pos(),
2554 ..open_span
2555 },
2556 flags,
2557 }))
2558 } else {
2559 assert_eq!(char_end, ':');
2560 Ok(Either::Right(ast::Group {
2561 span: open_span,
2562 kind: ast::GroupKind::NonCapturing(flags),
2563 ast: Box::new(Ast::empty(self.span())),
2564 }))
2565 }
2566 } else {
2567 let capture_index = self.next_capture_index(open_span)?;
2568 Ok(Either::Right(ast::Group {
2569 span: open_span,
2570 kind: ast::GroupKind::CaptureIndex(capture_index),
2571 ast: Box::new(Ast::empty(self.span())),
2572 }))
2573 }
2574 }
2575
2576 #[inline(never)]
2577 fn parse_capture_name(&self, capture_index: u32) -> Result<ast::CaptureName> {
2578 if self.is_eof() {
2579 return Err(self.error(self.span(), ast::ErrorKind::GroupNameUnexpectedEof));
2580 }
2581 let start = self.pos();
2582 loop {
2583 if self.char() == '>' {
2584 break;
2585 }
2586 if !is_capture_char(self.char(), self.pos() == start) {
2587 return Err(self.error(self.span_char(), ast::ErrorKind::GroupNameInvalid));
2588 }
2589 if !self.bump() {
2590 break;
2591 }
2592 }
2593 let end = self.pos();
2594 if self.is_eof() {
2595 return Err(self.error(self.span(), ast::ErrorKind::GroupNameUnexpectedEof));
2596 }
2597 assert_eq!(self.char(), '>');
2598 self.bump();
2599 let name = &self.pattern()[start.offset..end.offset];
2600 if name.is_empty() {
2601 return Err(self.error(Span::new(start, start), ast::ErrorKind::GroupNameEmpty));
2602 }
2603 let capname = ast::CaptureName {
2604 span: Span::new(start, end),
2605 name: name.to_string(),
2606 index: capture_index,
2607 };
2608 self.add_capture_name(&capname)?;
2609 Ok(capname)
2610 }
2611
2612 #[inline(never)]
2613 fn parse_flags(&self) -> Result<ast::Flags> {
2614 let mut flags = ast::Flags {
2615 span: self.span(),
2616 items: vec![],
2617 };
2618 let mut last_was_negation = None;
2619 while self.char() != ':' && self.char() != ')' {
2620 if self.char() == '-' {
2621 last_was_negation = Some(self.span_char());
2622 let item = ast::FlagsItem {
2623 span: self.span_char(),
2624 kind: ast::FlagsItemKind::Negation,
2625 };
2626 if let Some(i) = flags.add_item(item) {
2627 return Err(self.error(
2628 self.span_char(),
2629 ast::ErrorKind::FlagRepeatedNegation {
2630 original: flags.items[i].span,
2631 },
2632 ));
2633 }
2634 } else {
2635 last_was_negation = None;
2636 let item = ast::FlagsItem {
2637 span: self.span_char(),
2638 kind: ast::FlagsItemKind::Flag(self.parse_flag()?),
2639 };
2640 if let Some(i) = flags.add_item(item) {
2641 return Err(self.error(
2642 self.span_char(),
2643 ast::ErrorKind::FlagDuplicate {
2644 original: flags.items[i].span,
2645 },
2646 ));
2647 }
2648 }
2649 if !self.bump() {
2650 return Err(self.error(self.span(), ast::ErrorKind::FlagUnexpectedEof));
2651 }
2652 }
2653 if let Some(span) = last_was_negation {
2654 return Err(self.error(span, ast::ErrorKind::FlagDanglingNegation));
2655 }
2656 flags.span.end = self.pos();
2657 Ok(flags)
2658 }
2659
2660 #[inline(never)]
2661 fn parse_flag(&self) -> Result<ast::Flag> {
2662 match self.char() {
2663 'i' => Ok(ast::Flag::CaseInsensitive),
2664 'm' => Ok(ast::Flag::MultiLine),
2665 's' => Ok(ast::Flag::DotMatchesNewLine),
2666 'U' => Ok(ast::Flag::SwapGreed),
2667 'u' => Ok(ast::Flag::Unicode),
2668 'R' => Ok(ast::Flag::CRLF),
2669 'x' => Ok(ast::Flag::IgnoreWhitespace),
2670 _ => Err(self.error(self.span_char(), ast::ErrorKind::FlagUnrecognized)),
2671 }
2672 }
2673
2674 fn parse_primitive(&self) -> Result<Primitive> {
2675 match self.char() {
2676 '\\' => self.parse_escape(),
2677 '_' => {
2678 let ast = Primitive::Top(self.span_char());
2679 self.bump();
2680 Ok(ast)
2681 }
2682 '.' => {
2683 let ast = Primitive::Dot(self.span_char());
2684 self.bump();
2685 Ok(ast)
2686 }
2687 '^' => {
2688 let ast = Primitive::Assertion(ast::Assertion {
2689 span: self.span_char(),
2690 kind: ast::AssertionKind::StartLine,
2691 });
2692 self.bump();
2693 Ok(ast)
2694 }
2695 '$' => {
2696 let ast = Primitive::Assertion(ast::Assertion {
2697 span: self.span_char(),
2698 kind: ast::AssertionKind::EndLine,
2699 });
2700 self.bump();
2701 Ok(ast)
2702 }
2703 c => {
2704 let ast = Primitive::Literal(Literal {
2705 span: self.span_char(),
2706 kind: LiteralKind::Verbatim,
2707 c,
2708 });
2709 self.bump();
2710 Ok(ast)
2711 }
2712 }
2713 }
2714
2715 #[inline(never)]
2716 fn parse_escape(&self) -> Result<Primitive> {
2717 assert_eq!(self.char(), '\\');
2718 let start = self.pos();
2719 if !self.bump() {
2720 return Err(self.error(
2721 Span::new(start, self.pos()),
2722 ast::ErrorKind::EscapeUnexpectedEof,
2723 ));
2724 }
2725 let c = self.char();
2726 match c {
2728 '0'..='9' => {
2729 if !self.parser().octal {
2730 return Err(self.error(
2731 Span::new(start, self.span_char().end),
2732 ast::ErrorKind::UnsupportedBackreference,
2733 ));
2734 }
2735 let mut lit = self.parse_octal();
2736 lit.span.start = start;
2737 return Ok(Primitive::Literal(lit));
2738 }
2739 'x' | 'u' | 'U' => {
2740 let mut lit = self.parse_hex()?;
2741 lit.span.start = start;
2742 return Ok(Primitive::Literal(lit));
2743 }
2744 'p' | 'P' => {
2745 let mut cls = self.parse_unicode_class()?;
2746 cls.span.start = start;
2747 return Ok(Primitive::Unicode(cls));
2748 }
2749 'd' | 's' | 'w' | 'D' | 'S' | 'W' => {
2750 let mut cls = self.parse_perl_class();
2751 cls.span.start = start;
2752 return Ok(Primitive::Perl(cls));
2753 }
2754 _ => {}
2755 }
2756
2757 self.bump();
2759 let span = Span::new(start, self.pos());
2760 if is_meta_character(c) {
2761 return Ok(Primitive::Literal(Literal {
2762 span,
2763 kind: LiteralKind::Meta,
2764 c,
2765 }));
2766 }
2767 if is_escapeable_character(c) {
2768 return Ok(Primitive::Literal(Literal {
2769 span,
2770 kind: LiteralKind::Superfluous,
2771 c,
2772 }));
2773 }
2774 let special = |kind, c| {
2775 Ok(Primitive::Literal(Literal {
2776 span,
2777 kind: LiteralKind::Special(kind),
2778 c,
2779 }))
2780 };
2781 match c {
2782 'a' => special(SpecialLiteralKind::Bell, '\x07'),
2783 'f' => special(SpecialLiteralKind::FormFeed, '\x0C'),
2784 't' => special(SpecialLiteralKind::Tab, '\t'),
2785 'n' => special(SpecialLiteralKind::LineFeed, '\n'),
2786 'r' => special(SpecialLiteralKind::CarriageReturn, '\r'),
2787 'v' => special(SpecialLiteralKind::VerticalTab, '\x0B'),
2788 'A' => Ok(Primitive::Assertion(ast::Assertion {
2789 span,
2790 kind: ast::AssertionKind::StartText,
2791 })),
2792 'z' => Ok(Primitive::Assertion(ast::Assertion {
2793 span,
2794 kind: ast::AssertionKind::EndText,
2795 })),
2796 'b' => {
2797 let mut wb = ast::Assertion {
2798 span,
2799 kind: ast::AssertionKind::WordBoundary,
2800 };
2801 if !self.is_eof() && self.char() == '{' {
2804 if let Some(kind) = self.maybe_parse_special_word_boundary(start)? {
2805 wb.kind = kind;
2806 wb.span.end = self.pos();
2807 }
2808 }
2809 Ok(Primitive::Assertion(wb))
2810 }
2811 'B' => Ok(Primitive::Assertion(ast::Assertion {
2812 span,
2813 kind: ast::AssertionKind::NotWordBoundary,
2814 })),
2815 '<' => Ok(Primitive::Assertion(ast::Assertion {
2816 span,
2817 kind: ast::AssertionKind::WordBoundaryStartAngle,
2818 })),
2819 '>' => Ok(Primitive::Assertion(ast::Assertion {
2820 span,
2821 kind: ast::AssertionKind::WordBoundaryEndAngle,
2822 })),
2823 _ => Err(self.error(span, ast::ErrorKind::EscapeUnrecognized)),
2824 }
2825 }
2826
2827 fn maybe_parse_special_word_boundary(
2828 &self,
2829 wb_start: Position,
2830 ) -> Result<Option<ast::AssertionKind>> {
2831 assert_eq!(self.char(), '{');
2832
2833 let is_valid_char = |c| matches!(c, 'A'..='Z' | 'a'..='z' | '-');
2834 let start = self.pos();
2835 if !self.bump_and_bump_space() {
2836 return Err(self.error(
2837 Span::new(wb_start, self.pos()),
2838 ast::ErrorKind::SpecialWordOrRepetitionUnexpectedEof,
2839 ));
2840 }
2841 let start_contents = self.pos();
2842 if !is_valid_char(self.char()) {
2843 self.parser().pos.set(start);
2844 return Ok(None);
2845 }
2846
2847 let mut scratch = self.parser().scratch.borrow_mut();
2849 scratch.clear();
2850 while !self.is_eof() && is_valid_char(self.char()) {
2851 scratch.push(self.char());
2852 self.bump_and_bump_space();
2853 }
2854 if self.is_eof() || self.char() != '}' {
2855 return Err(self.error(
2856 Span::new(start, self.pos()),
2857 ast::ErrorKind::SpecialWordBoundaryUnclosed,
2858 ));
2859 }
2860 let end = self.pos();
2861 self.bump();
2862 let kind = match scratch.as_str() {
2863 "start" => ast::AssertionKind::WordBoundaryStart,
2864 "end" => ast::AssertionKind::WordBoundaryEnd,
2865 "start-half" => ast::AssertionKind::WordBoundaryStartHalf,
2866 "end-half" => ast::AssertionKind::WordBoundaryEndHalf,
2867 _ => {
2868 return Err(self.error(
2869 Span::new(start_contents, end),
2870 ast::ErrorKind::SpecialWordBoundaryUnrecognized,
2871 ))
2872 }
2873 };
2874 Ok(Some(kind))
2875 }
2876
2877 #[inline(never)]
2878 fn parse_octal(&self) -> Literal {
2879 assert!(self.parser().octal);
2880 assert!('0' <= self.char() && self.char() <= '7');
2881 let start = self.pos();
2882 while self.bump()
2884 && '0' <= self.char()
2885 && self.char() <= '7'
2886 && self.pos().offset - start.offset <= 2
2887 {}
2888 let end = self.pos();
2889 let octal = &self.pattern()[start.offset..end.offset];
2890 let codepoint = u32::from_str_radix(octal, 8).expect("valid octal number");
2893 let c = char::from_u32(codepoint).expect("Unicode scalar value");
2896 Literal {
2897 span: Span::new(start, end),
2898 kind: LiteralKind::Octal,
2899 c,
2900 }
2901 }
2902
2903 #[inline(never)]
2904 fn parse_hex(&self) -> Result<Literal> {
2905 assert!(self.char() == 'x' || self.char() == 'u' || self.char() == 'U');
2906
2907 let hex_kind = match self.char() {
2908 'x' => HexLiteralKind::X,
2909 'u' => HexLiteralKind::UnicodeShort,
2910 _ => HexLiteralKind::UnicodeLong,
2911 };
2912 if !self.bump_and_bump_space() {
2913 return Err(self.error(self.span(), ast::ErrorKind::EscapeUnexpectedEof));
2914 }
2915 if self.char() == '{' {
2916 self.parse_hex_brace(hex_kind)
2917 } else {
2918 self.parse_hex_digits(hex_kind)
2919 }
2920 }
2921
2922 #[inline(never)]
2923 fn parse_hex_digits(&self, kind: HexLiteralKind) -> Result<Literal> {
2924 let mut scratch = self.parser().scratch.borrow_mut();
2925 scratch.clear();
2926
2927 let start = self.pos();
2928 for i in 0..kind.digits() {
2929 if i > 0 && !self.bump_and_bump_space() {
2930 return Err(self.error(self.span(), ast::ErrorKind::EscapeUnexpectedEof));
2931 }
2932 if !is_hex(self.char()) {
2933 return Err(self.error(self.span_char(), ast::ErrorKind::EscapeHexInvalidDigit));
2934 }
2935 scratch.push(self.char());
2936 }
2937 self.bump_and_bump_space();
2938 let end = self.pos();
2939 let hex = scratch.as_str();
2940 match u32::from_str_radix(hex, 16).ok().and_then(char::from_u32) {
2941 None => Err(self.error(Span::new(start, end), ast::ErrorKind::EscapeHexInvalid)),
2942 Some(c) => Ok(Literal {
2943 span: Span::new(start, end),
2944 kind: LiteralKind::HexFixed(kind),
2945 c,
2946 }),
2947 }
2948 }
2949
2950 #[inline(never)]
2951 fn parse_hex_brace(&self, kind: HexLiteralKind) -> Result<Literal> {
2952 let mut scratch = self.parser().scratch.borrow_mut();
2953 scratch.clear();
2954
2955 let brace_pos = self.pos();
2956 let start = self.span_char().end;
2957 while self.bump_and_bump_space() && self.char() != '}' {
2958 if !is_hex(self.char()) {
2959 return Err(self.error(self.span_char(), ast::ErrorKind::EscapeHexInvalidDigit));
2960 }
2961 scratch.push(self.char());
2962 }
2963 if self.is_eof() {
2964 return Err(self.error(
2965 Span::new(brace_pos, self.pos()),
2966 ast::ErrorKind::EscapeUnexpectedEof,
2967 ));
2968 }
2969 let end = self.pos();
2970 let hex = scratch.as_str();
2971 assert_eq!(self.char(), '}');
2972 self.bump_and_bump_space();
2973
2974 if hex.is_empty() {
2975 return Err(self.error(
2976 Span::new(brace_pos, self.pos()),
2977 ast::ErrorKind::EscapeHexEmpty,
2978 ));
2979 }
2980 match u32::from_str_radix(hex, 16).ok().and_then(char::from_u32) {
2981 None => Err(self.error(Span::new(start, end), ast::ErrorKind::EscapeHexInvalid)),
2982 Some(c) => Ok(Literal {
2983 span: Span::new(start, self.pos()),
2984 kind: LiteralKind::HexBrace(kind),
2985 c,
2986 }),
2987 }
2988 }
2989
2990 fn parse_decimal(&self) -> Result<u32> {
2991 let mut scratch = self.parser().scratch.borrow_mut();
2992 scratch.clear();
2993
2994 while !self.is_eof() && self.char().is_whitespace() {
2995 self.bump();
2996 }
2997 let start = self.pos();
2998 while !self.is_eof() && '0' <= self.char() && self.char() <= '9' {
2999 scratch.push(self.char());
3000 self.bump_and_bump_space();
3001 }
3002 let span = Span::new(start, self.pos());
3003 while !self.is_eof() && self.char().is_whitespace() {
3004 self.bump_and_bump_space();
3005 }
3006 let digits = scratch.as_str();
3007 if digits.is_empty() {
3008 return Err(self.error(span, ast::ErrorKind::DecimalEmpty));
3009 }
3010 match digits.parse::<u32>().ok() {
3011 Some(n) => Ok(n),
3012 None => Err(self.error(span, ast::ErrorKind::DecimalInvalid)),
3013 }
3014 }
3015
3016 #[inline(never)]
3017 fn parse_set_class(&self) -> Result<ClassBracketed> {
3018 assert_eq!(self.char(), '[');
3019
3020 let mut union = ClassSetUnion {
3021 span: self.span(),
3022 items: vec![],
3023 };
3024 loop {
3025 self.bump_space();
3026 if self.is_eof() {
3027 return Err(self.unclosed_class_error());
3028 }
3029 match self.char() {
3030 '[' => {
3031 if !self.parser().stack_class.borrow().is_empty() {
3032 if let Some(cls) = self.maybe_parse_ascii_class() {
3033 union.push(ClassSetItem::Ascii(cls));
3034 continue;
3035 }
3036 }
3037 union = self.push_class_open(union)?;
3038 }
3039 ']' => match self.pop_class(union)? {
3040 Either::Left(nested_union) => {
3041 union = nested_union;
3042 }
3043 Either::Right(class) => return Ok(class),
3044 },
3045 '&' if self.peek() == Some('&') => {
3046 assert!(self.bump_if("&&"));
3047 union = self.push_class_op(ClassSetBinaryOpKind::Intersection, union);
3048 }
3049 '-' if self.peek() == Some('-') => {
3050 assert!(self.bump_if("--"));
3051 union = self.push_class_op(ClassSetBinaryOpKind::Difference, union);
3052 }
3053 '~' if self.peek() == Some('~') => {
3054 assert!(self.bump_if("~~"));
3055 union = self.push_class_op(ClassSetBinaryOpKind::SymmetricDifference, union);
3056 }
3057 _ => {
3058 union.push(self.parse_set_class_range()?);
3059 }
3060 }
3061 }
3062 }
3063
3064 #[inline(never)]
3065 fn parse_set_class_range(&self) -> Result<ClassSetItem> {
3066 let prim1 = self.parse_set_class_item()?;
3067 self.bump_space();
3068 if self.is_eof() {
3069 return Err(self.unclosed_class_error());
3070 }
3071 if self.char() != '-' || self.peek_space() == Some(']') || self.peek_space() == Some('-') {
3072 return prim1.into_class_set_item(self);
3073 }
3074 if !self.bump_and_bump_space() {
3075 return Err(self.unclosed_class_error());
3076 }
3077 let prim2 = self.parse_set_class_item()?;
3078 let range = ClassSetRange {
3079 span: Span::new(prim1.span().start, prim2.span().end),
3080 start: prim1.into_class_literal(self)?,
3081 end: prim2.into_class_literal(self)?,
3082 };
3083 if !range.is_valid() {
3084 return Err(self.error(range.span, ast::ErrorKind::ClassRangeInvalid));
3085 }
3086 Ok(ClassSetItem::Range(range))
3087 }
3088
3089 #[inline(never)]
3090 fn parse_set_class_item(&self) -> Result<Primitive> {
3091 if self.char() == '\\' {
3092 self.parse_escape()
3093 } else {
3094 let x = Primitive::Literal(Literal {
3095 span: self.span_char(),
3096 kind: LiteralKind::Verbatim,
3097 c: self.char(),
3098 });
3099 self.bump();
3100 Ok(x)
3101 }
3102 }
3103
3104 #[inline(never)]
3105 fn parse_set_class_open(&self) -> Result<(ClassBracketed, ClassSetUnion)> {
3106 assert_eq!(self.char(), '[');
3107 let start = self.pos();
3108 if !self.bump_and_bump_space() {
3109 return Err(self.error(Span::new(start, self.pos()), ast::ErrorKind::ClassUnclosed));
3110 }
3111
3112 let negated = if self.char() != '^' {
3113 false
3114 } else {
3115 if !self.bump_and_bump_space() {
3116 return Err(self.error(Span::new(start, self.pos()), ast::ErrorKind::ClassUnclosed));
3117 }
3118 true
3119 };
3120 let mut union = ClassSetUnion {
3122 span: self.span(),
3123 items: vec![],
3124 };
3125 while self.char() == '-' {
3126 union.push(ClassSetItem::Literal(Literal {
3127 span: self.span_char(),
3128 kind: LiteralKind::Verbatim,
3129 c: '-',
3130 }));
3131 if !self.bump_and_bump_space() {
3132 return Err(self.error(Span::new(start, start), ast::ErrorKind::ClassUnclosed));
3133 }
3134 }
3135 if union.items.is_empty() && self.char() == ']' {
3138 union.push(ClassSetItem::Literal(Literal {
3139 span: self.span_char(),
3140 kind: LiteralKind::Verbatim,
3141 c: ']',
3142 }));
3143 if !self.bump_and_bump_space() {
3144 return Err(self.error(Span::new(start, self.pos()), ast::ErrorKind::ClassUnclosed));
3145 }
3146 }
3147 let set = ClassBracketed {
3148 span: Span::new(start, self.pos()),
3149 negated,
3150 kind: ClassSet::union(ClassSetUnion {
3151 span: Span::new(union.span.start, union.span.start),
3152 items: vec![],
3153 }),
3154 };
3155 Ok((set, union))
3156 }
3157
3158 #[inline(never)]
3159 fn maybe_parse_ascii_class(&self) -> Option<ClassAscii> {
3160 assert_eq!(self.char(), '[');
3161 let start = self.pos();
3163 let mut negated = false;
3164 if !self.bump() || self.char() != ':' {
3165 self.parser().pos.set(start);
3166 return None;
3167 }
3168 if !self.bump() {
3169 self.parser().pos.set(start);
3170 return None;
3171 }
3172 if self.char() == '^' {
3173 negated = true;
3174 if !self.bump() {
3175 self.parser().pos.set(start);
3176 return None;
3177 }
3178 }
3179 let name_start = self.offset();
3180 while self.char() != ':' && self.bump() {}
3181 if self.is_eof() {
3182 self.parser().pos.set(start);
3183 return None;
3184 }
3185 let name = &self.pattern()[name_start..self.offset()];
3186 if !self.bump_if(":]") {
3187 self.parser().pos.set(start);
3188 return None;
3189 }
3190 let kind = match regex_syntax::ast::ClassAsciiKind::from_name(name) {
3191 Some(kind) => kind,
3192 None => {
3193 self.parser().pos.set(start);
3194 return None;
3195 }
3196 };
3197 Some(ClassAscii {
3198 span: Span::new(start, self.pos()),
3199 kind,
3200 negated,
3201 })
3202 }
3203
3204 #[inline(never)]
3205 fn parse_unicode_class(&self) -> Result<ClassUnicode> {
3206 assert!(self.char() == 'p' || self.char() == 'P');
3207
3208 let mut scratch = self.parser().scratch.borrow_mut();
3209 scratch.clear();
3210
3211 let negated = self.char() == 'P';
3212 if !self.bump_and_bump_space() {
3213 return Err(self.error(self.span(), ast::ErrorKind::EscapeUnexpectedEof));
3214 }
3215 let (start, kind) = if self.char() == '{' {
3216 let start = self.span_char().end;
3217 while self.bump_and_bump_space() && self.char() != '}' {
3218 scratch.push(self.char());
3219 }
3220 if self.is_eof() {
3221 return Err(self.error(self.span(), ast::ErrorKind::EscapeUnexpectedEof));
3222 }
3223 assert_eq!(self.char(), '}');
3224 self.bump();
3225
3226 let name = scratch.as_str();
3227 if let Some(i) = name.find("!=") {
3228 (
3229 start,
3230 ClassUnicodeKind::NamedValue {
3231 op: ClassUnicodeOpKind::NotEqual,
3232 name: name[..i].to_string(),
3233 value: name[i + 2..].to_string(),
3234 },
3235 )
3236 } else if let Some(i) = name.find(':') {
3237 (
3238 start,
3239 ClassUnicodeKind::NamedValue {
3240 op: ClassUnicodeOpKind::Colon,
3241 name: name[..i].to_string(),
3242 value: name[i + 1..].to_string(),
3243 },
3244 )
3245 } else if let Some(i) = name.find('=') {
3246 (
3247 start,
3248 ClassUnicodeKind::NamedValue {
3249 op: ClassUnicodeOpKind::Equal,
3250 name: name[..i].to_string(),
3251 value: name[i + 1..].to_string(),
3252 },
3253 )
3254 } else {
3255 (start, ClassUnicodeKind::Named(name.to_string()))
3256 }
3257 } else {
3258 let start = self.pos();
3259 let c = self.char();
3260 if c == '\\' {
3261 return Err(self.error(self.span_char(), ast::ErrorKind::UnicodeClassInvalid));
3262 }
3263 self.bump_and_bump_space();
3264 let kind = ClassUnicodeKind::OneLetter(c);
3265 (start, kind)
3266 };
3267 Ok(ClassUnicode {
3268 span: Span::new(start, self.pos()),
3269 negated,
3270 kind,
3271 })
3272 }
3273
3274 #[inline(never)]
3275 fn parse_perl_class(&self) -> ClassPerl {
3276 let c = self.char();
3277 let span = self.span_char();
3278 self.bump();
3279 let (negated, kind) = match c {
3280 'd' => (false, regex_syntax::ast::ClassPerlKind::Digit),
3281 'D' => (true, regex_syntax::ast::ClassPerlKind::Digit),
3282 's' => (false, regex_syntax::ast::ClassPerlKind::Space),
3283 'S' => (true, regex_syntax::ast::ClassPerlKind::Space),
3284 'w' => (false, regex_syntax::ast::ClassPerlKind::Word),
3285 'W' => (true, regex_syntax::ast::ClassPerlKind::Word),
3286 c => panic!("expected valid Perl class but got '{}'", c),
3287 };
3288 ClassPerl {
3289 span,
3290 kind,
3291 negated,
3292 }
3293 }
3294}
3295
3296fn is_universal_perl_pair(item: ®ex_syntax::ast::ClassSetItem) -> bool {
3297 use regex_syntax::ast::ClassSetItem;
3298 let items = match item {
3299 ClassSetItem::Union(u) => &u.items,
3300 _ => return false,
3301 };
3302 if items.len() != 2 {
3303 return false;
3304 }
3305 match (&items[0], &items[1]) {
3306 (ClassSetItem::Perl(a), ClassSetItem::Perl(b)) => {
3307 let is_all = a.kind == b.kind && a.negated != b.negated;
3308 is_all
3309 }
3310 _ => false,
3311 }
3312}
3313
3314pub fn max_concat_length(ast: &ast::Ast) -> usize {
3315 match ast {
3316 ast::Ast::Empty(_)
3317 | ast::Ast::Flags(_)
3318 | ast::Ast::Literal(_)
3319 | ast::Ast::Dot(_)
3320 | ast::Ast::Top(_)
3321 | ast::Ast::Assertion(_)
3322 | ast::Ast::ClassUnicode(_)
3323 | ast::Ast::ClassPerl(_)
3324 | ast::Ast::ClassBracketed(_) => 0,
3325 ast::Ast::Group(g) => max_concat_length(&g.ast),
3326 ast::Ast::Complement(c) => max_concat_length(&c.ast),
3327 ast::Ast::Lookaround(l) => max_concat_length(&l.ast),
3328 ast::Ast::Repetition(r) => max_concat_length(&r.ast),
3329 ast::Ast::Concat(c) => c
3330 .asts
3331 .len()
3332 .max(c.asts.iter().map(max_concat_length).max().unwrap_or(0)),
3333 ast::Ast::Alternation(a) => a.asts.iter().map(max_concat_length).max().unwrap_or(0),
3334 ast::Ast::Intersection(i) => i.asts.iter().map(max_concat_length).max().unwrap_or(0),
3335 }
3336}
3337
3338pub fn expanded_ast_size(ast: &ast::Ast, limit: u64) -> u64 {
3339 fn go(ast: &ast::Ast, limit: u64) -> u64 {
3340 match ast {
3341 ast::Ast::Empty(_) | ast::Ast::Flags(_) => 1,
3342 ast::Ast::Literal(_) | ast::Ast::Dot(_) | ast::Ast::Top(_) => 1,
3343 ast::Ast::Assertion(_) => 1,
3344 ast::Ast::ClassUnicode(_) | ast::Ast::ClassPerl(_) | ast::Ast::ClassBracketed(_) => 1,
3345 ast::Ast::Group(g) => go(&g.ast, limit).saturating_add(1).min(limit),
3346 ast::Ast::Complement(c) => go(&c.ast, limit).saturating_add(1).min(limit),
3347 ast::Ast::Lookaround(l) => go(&l.ast, limit).saturating_add(1).min(limit),
3348 ast::Ast::Concat(c) => sum_children(&c.asts, limit),
3349 ast::Ast::Alternation(a) => sum_children(&a.asts, limit),
3350 ast::Ast::Intersection(i) => sum_children(&i.asts, limit),
3351 ast::Ast::Repetition(r) => {
3352 let body = go(&r.ast, limit);
3353 let factor: u64 = match &r.op.kind {
3354 ast::RepetitionKind::ZeroOrOne => 2,
3355 ast::RepetitionKind::ZeroOrMore | ast::RepetitionKind::OneOrMore => 2,
3356 ast::RepetitionKind::Range(ast::RepetitionRange::Exactly(n)) => {
3357 (*n as u64).max(1)
3358 }
3359 ast::RepetitionKind::Range(ast::RepetitionRange::AtLeast(n)) => {
3360 (*n as u64).max(1).saturating_add(1)
3361 }
3362 ast::RepetitionKind::Range(ast::RepetitionRange::Bounded(_, m)) => {
3363 (*m as u64).max(1)
3364 }
3365 };
3366 body.saturating_mul(factor).min(limit)
3367 }
3368 }
3369 }
3370 fn sum_children(children: &[ast::Ast], limit: u64) -> u64 {
3371 let mut total: u64 = 0;
3372 for c in children {
3373 total = total.saturating_add(go(c, limit));
3374 if total >= limit {
3375 return limit;
3376 }
3377 }
3378 total
3379 }
3380 go(ast, limit)
3381}
3382
3383pub fn parse_ast<'s>(tb: &mut TB<'s>, pattern: &'s str) -> std::result::Result<NodeId, ParseError> {
3384 let mut p: ResharpParser<'s> = ResharpParser::new(pattern);
3385 p.parse(tb)
3386}
3387
3388pub fn parse_ast_with<'s>(
3389 tb: &mut TB<'s>,
3390 pattern: &'s str,
3391 flags: &PatternFlags,
3392) -> std::result::Result<NodeId, ParseError> {
3393 let mut p: ResharpParser<'s> = ResharpParser::with_flags(pattern, flags);
3394 p.parse(tb)
3395}
3396
3397pub fn parse_to_ast(pattern: &str) -> std::result::Result<ast::Ast, ParseError> {
3399 let mut p: ResharpParser = ResharpParser::new(pattern);
3400 p.parse_inner()
3401}