Skip to content

Commit 2db154d

Browse files
committed
start porting Reader from JS regexpp
1 parent 37a3ea0 commit 2db154d

File tree

1 file changed

+171
-0
lines changed

1 file changed

+171
-0
lines changed

src/reader.rs

Lines changed: 171 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,171 @@
1+
// Copyright (C) 2020 Quentin M. Kniep <[email protected]>
2+
// Distributed under terms of the MIT license.
3+
4+
const legacyImpl = {
5+
at(s: string, end: number, i: number): number {
6+
return i < end ? s.charCodeAt(i) : -1
7+
},
8+
width(c: number): number {
9+
return 1
10+
},
11+
}
12+
13+
const unicodeImpl = {
14+
at(s: string, end: number, i: number): number {
15+
return i < end ? s.codePointAt(i)! : -1
16+
},
17+
width(c: number): number {
18+
return c > 0xffff ? 2 : 1
19+
},
20+
}
21+
22+
struct Reader {
23+
implem = legacyImpl;
24+
src: &str,
25+
index: usize,
26+
end: usize,
27+
cp1: Option<char>,
28+
w1: usize,
29+
cp2: Option<char>,
30+
w2: usize,
31+
cp3: Option<char>,
32+
w3: usize,
33+
cp4: Option<char>,
34+
}
35+
36+
impl Reader {
37+
pub fn new() -> Self {
38+
Self {
39+
implem: legacyImpl,
40+
src: "",
41+
index: 0,
42+
end: 0,
43+
cp1: None,
44+
w1: 1,
45+
cp2: None,
46+
w2: 1,
47+
cp3: None,
48+
w3: 1,
49+
cp4: None,
50+
w4: 1,
51+
}
52+
}
53+
54+
pub fn source(&self) -> &str {
55+
self.src
56+
}
57+
58+
pub fn index(&self) -> usize {
59+
self.index
60+
}
61+
62+
pub fn currentCodePoint(&self) -> char {
63+
self.cp1
64+
}
65+
66+
pub fn nextCodePoint() -> char {
67+
self.cp2
68+
}
69+
70+
pub fn nextCodePoint2() -> char {
71+
self.cp3
72+
}
73+
74+
pub fn nextCodePoint3() -> char {
75+
self.cp4
76+
}
77+
78+
pub fn reset(
79+
&mut self,
80+
source: &str,
81+
start: usize,
82+
end: usize,
83+
uFlag: bool,
84+
) {
85+
self.implem = uFlag ? unicodeImpl : legacyImpl;
86+
self.src = source;
87+
self.end = end;
88+
self.rewind(start);
89+
}
90+
91+
pub fn rewind(&mut self, index: usize) {
92+
let implem = self.implem;
93+
self.index = index;
94+
self.cp1 = implem.at(self.src, self.end, index);
95+
self.w1 = implem.width(this.cp1);
96+
self.cp2 = implem.at(self.src, self.end, index + self.w1);
97+
self.w2 = implem.width(this.cp2);
98+
self.cp3 = implem.at(self.src, self.end, index + self.w1 + self.w2);
99+
self.w3 = implem.width(self.cp3);
100+
self.cp4 = implem.at(
101+
self.src,
102+
self.end,
103+
index + self.w1 + self.w2 + self.w3,
104+
);
105+
}
106+
107+
pub fn advance(&mut self) {
108+
if self.cp1 != -1 {
109+
let implem = self.implem;
110+
self.index += self.w1;
111+
self.cp1 = self.cp2;
112+
self.w1 = self.w2;
113+
self.cp2 = self.cp3;
114+
self.w2 = implem.width(self.cp2);
115+
self.cp3 = self.cp4;
116+
self.w3 = implem.width(self.cp3);
117+
self.cp4 = implem.at(
118+
self.src,
119+
self.end,
120+
self.index + self.w1 + self.w2 + self.w3,
121+
);
122+
}
123+
}
124+
125+
pub fn eat(&mut self, cp: char) -> bool {
126+
if self.cp1 == cp {
127+
self.advance();
128+
return true;
129+
}
130+
return false;
131+
}
132+
133+
pub fn eat2(&mut self, cp1: char, cp2: char) -> bool {
134+
if self.cp1 == cp1 && self.cp2 == cp2 {
135+
self.advance();
136+
self.advance();
137+
return true;
138+
}
139+
return false;
140+
}
141+
142+
pub fn eat3(&mut self, cp1: char, cp2: char, cp3: char) -> bool {
143+
if self.cp1 == cp1 && self.cp2 == cp2 && self.cp3 == cp3 {
144+
self.advance();
145+
self.advance();
146+
self.advance();
147+
return true;
148+
}
149+
return false;
150+
}
151+
}
152+
153+
154+
#[cfg(test)]
155+
mod tests {
156+
use super::*;
157+
158+
#[test]
159+
fn eat_test() {
160+
let reader = Reader::new();
161+
reader.reset("abcdefghijk", 0, 11, true);
162+
assert_eq!(reader.eat('a'), true);
163+
assert_eq!(reader.eat3('b', 'd', 'd'), false);
164+
assert_eq!(reader.eat3('b', 'c', 'd'), true);
165+
assert_eq!(reader.eat2('e', 'f'), true);
166+
assert_eq!(reader.eat('h'), false);
167+
assert_eq!(reader.eat('g'), true);
168+
assert_eq!(reader.eat2('h', 'i'), true);
169+
assert_eq!(reader.eat3('j', 'k', 'a'), false);
170+
}
171+
}

0 commit comments

Comments
 (0)