swc_ecma_regexp/parser/reader/
reader_impl.rs1use swc_atoms::Atom;
2
3use crate::{
4 diagnostics::Result,
5 parser::reader::string_literal_parser::{
6 ast as StringLiteralAst, parse_regexp_literal, Options as StringLiteralParserOptions,
7 Parser as StringLiteralParser,
8 },
9};
10
11pub struct Reader<'a> {
12 source_text: &'a str,
13 units: Vec<StringLiteralAst::CodePoint>,
14 index: usize,
15 offset: u32,
16}
17
18impl<'a> Reader<'a> {
19 pub fn initialize(
20 source_text: &'a str,
21 unicode_mode: bool,
22 parse_string_literal: bool,
23 ) -> Result<Self> {
24 let span_offset = 0;
29
30 let units = if parse_string_literal {
31 let StringLiteralAst::StringLiteral { body, .. } = StringLiteralParser::new(
32 source_text,
33 StringLiteralParserOptions {
34 strict_mode: false,
35 span_offset,
36 combine_surrogate_pair: unicode_mode,
37 },
38 )
39 .parse()?;
40 body
41 } else {
42 parse_regexp_literal(source_text, span_offset, unicode_mode)
43 };
44
45 Ok(Self {
46 source_text,
47 units,
48 index: 0,
49 offset: u32::from(parse_string_literal),
52 })
53 }
54
55 pub fn offset(&self) -> u32 {
56 self.offset
57 }
58
59 pub fn checkpoint(&self) -> (usize, u32) {
60 (self.index, self.offset)
61 }
62
63 pub fn rewind(&mut self, checkpoint: (usize, u32)) {
64 self.index = checkpoint.0;
65 self.offset = checkpoint.1;
66 }
67
68 pub fn advance(&mut self) {
69 if let Some(unit) = self.units.get(self.index) {
70 self.offset = unit.span.hi.0;
71 self.index += 1;
72 }
73 }
74
75 fn peek_nth(&self, n: usize) -> Option<u32> {
76 let nth = self.index + n;
77 self.units.get(nth).map(|cp| cp.value)
78 }
79
80 pub fn peek(&self) -> Option<u32> {
81 self.peek_nth(0)
82 }
83
84 pub fn peek2(&self) -> Option<u32> {
85 self.peek_nth(1)
86 }
87
88 pub fn eat(&mut self, ch: char) -> bool {
89 if self.peek_nth(0) == Some(ch as u32) {
90 self.advance();
91 return true;
92 }
93 false
94 }
95
96 pub fn eat2(&mut self, ch: char, ch2: char) -> bool {
97 if self.peek_nth(0) == Some(ch as u32) && self.peek_nth(1) == Some(ch2 as u32) {
98 self.advance();
99 self.advance();
100 return true;
101 }
102 false
103 }
104
105 pub fn eat3(&mut self, ch: char, ch2: char, ch3: char) -> bool {
106 if self.peek_nth(0) == Some(ch as u32)
107 && self.peek_nth(1) == Some(ch2 as u32)
108 && self.peek_nth(2) == Some(ch3 as u32)
109 {
110 self.advance();
111 self.advance();
112 self.advance();
113 return true;
114 }
115 false
116 }
117
118 pub fn eat4(&mut self, ch: char, ch2: char, ch3: char, ch4: char) -> bool {
119 if self.peek_nth(0) == Some(ch as u32)
120 && self.peek_nth(1) == Some(ch2 as u32)
121 && self.peek_nth(2) == Some(ch3 as u32)
122 && self.peek_nth(3) == Some(ch4 as u32)
123 {
124 self.advance();
125 self.advance();
126 self.advance();
127 self.advance();
128 return true;
129 }
130 false
131 }
132
133 pub fn atom(&self, start: u32, end: u32) -> Atom {
134 Atom::from(&self.source_text[start as usize..end as usize])
135 }
136}