1use ktrs_syntax::SyntaxKind::{self, *};
7
8use super::Parser;
9use crate::token_set::TokenSet;
10
11impl Parser {
12 pub(crate) fn match_token_stream_predicate(&mut self, pattern: &mut dyn TokenStreamPattern) -> i32 {
14 let current_position = self.mark();
15 let mut opens: Vec<SyntaxKind> = Vec::new();
16 let mut open_angle_brackets = 0;
17 let mut open_braces = 0;
18 let mut open_parentheses = 0;
19 let mut open_brackets = 0;
20 while !self.eof() {
21 let offset = self.my_builder.get_current_offset();
22 let top_level = pattern.is_top_level(open_angle_brackets, open_brackets, open_braces, open_parentheses);
23 if pattern.process_token(self, offset, top_level) {
24 break;
25 }
26 match self.get_token_id() {
27 Some(LPAR) => {
28 open_parentheses += 1;
29 opens.push(LPAR);
30 }
31 Some(LT) => {
32 open_angle_brackets += 1;
33 opens.push(LT);
34 }
35 Some(LBRACE) => {
36 open_braces += 1;
37 opens.push(LBRACE);
38 }
39 Some(LBRACKET) => {
40 open_brackets += 1;
41 opens.push(LBRACKET);
42 }
43 Some(RPAR) => {
44 open_parentheses -= 1;
45 if opens.pop() != Some(LPAR) {
47 pattern.handle_unmatched_closing(RPAR);
48 }
49 }
50 Some(GT) => open_angle_brackets -= 1,
51 Some(RBRACE) => open_braces -= 1,
52 Some(RBRACKET) => open_brackets -= 1,
53 _ => {}
54 }
55
56 self.advance(); }
58
59 current_position.rollback_to(self);
60
61 pattern.result()
62 }
63}
64
65pub trait TokenStreamPredicate {
66 fn matching(&self, p: &mut Parser, top_level: bool) -> bool;
67
68 fn or<O: TokenStreamPredicate>(self, other: O) -> Or<Self, O>
70 where
71 Self: Sized,
72 {
73 Or(self, other)
74 }
75}
76
77impl<F: Fn(&mut Parser, bool) -> bool> TokenStreamPredicate for F {
79 fn matching(&self, p: &mut Parser, top_level: bool) -> bool {
80 self(p, top_level)
81 }
82}
83
84pub struct Or<A, B>(A, B);
85
86impl<A: TokenStreamPredicate, B: TokenStreamPredicate> TokenStreamPredicate for Or<A, B> {
87 fn matching(&self, p: &mut Parser, top_level: bool) -> bool {
88 if self.0.matching(p, top_level) {
89 return true;
90 }
91 self.1.matching(p, top_level)
92 }
93}
94
95pub trait TokenStreamPattern {
97 fn process_token(&mut self, p: &mut Parser, offset: i32, top_level: bool) -> bool;
99
100 fn result(&self) -> i32;
102
103 fn is_top_level(&self, open_angle_brackets: i32, open_brackets: i32, open_braces: i32, open_parentheses: i32) -> bool {
104 open_braces == 0 && open_brackets == 0 && open_parentheses == 0 && open_angle_brackets == 0
105 }
106
107 fn handle_unmatched_closing(&mut self, _token: SyntaxKind) -> bool {
109 false
110 }
111}
112
113#[derive(Debug)]
115pub struct AbstractTokenStreamPattern {
116 pub last_occurrence: i32,
117}
118
119impl Default for AbstractTokenStreamPattern {
120 fn default() -> Self {
121 AbstractTokenStreamPattern { last_occurrence: -1 }
122 }
123}
124
125impl AbstractTokenStreamPattern {
126 pub fn fail(&mut self) {
127 self.last_occurrence = -1;
128 }
129
130 pub fn reset(&mut self) {
131 self.last_occurrence = -1;
132 }
133}
134
135pub struct FirstBefore<L, S> {
136 base: AbstractTokenStreamPattern,
137 look_for: L,
138 stop_at: S,
139}
140
141impl<L: TokenStreamPredicate, S: TokenStreamPredicate> FirstBefore<L, S> {
142 pub fn new(look_for: L, stop_at: S) -> Self {
143 FirstBefore { base: AbstractTokenStreamPattern::default(), look_for, stop_at }
144 }
145
146 pub fn reset(&mut self) {
147 self.base.reset();
148 }
149}
150
151impl<L: TokenStreamPredicate, S: TokenStreamPredicate> TokenStreamPattern for FirstBefore<L, S> {
152 fn process_token(&mut self, p: &mut Parser, offset: i32, top_level: bool) -> bool {
153 if self.look_for.matching(p, top_level) {
154 self.base.last_occurrence = offset;
155 return true;
156 }
157 if self.stop_at.matching(p, top_level) {
158 return true;
159 }
160 false
161 }
162
163 fn result(&self) -> i32 {
164 self.base.last_occurrence
165 }
166}
167
168pub struct LastBefore<L, S> {
169 base: AbstractTokenStreamPattern,
170 dont_stop_right_after_occurrence: bool,
171 look_for: L,
172 stop_at: S,
173 previous_look_for_result: bool,
174}
175
176impl<L: TokenStreamPredicate, S: TokenStreamPredicate> LastBefore<L, S> {
177 fn new_3(look_for: L, stop_at: S, dont_stop_right_after_occurrence: bool) -> Self {
179 LastBefore {
180 base: AbstractTokenStreamPattern::default(),
181 dont_stop_right_after_occurrence,
182 look_for,
183 stop_at,
184 previous_look_for_result: false,
185 }
186 }
187
188 pub fn new(look_for: L, stop_at: S) -> Self {
189 Self::new_3(look_for, stop_at, false)
190 }
191
192 pub fn reset(&mut self) {
193 self.base.reset();
194 self.previous_look_for_result = false;
195 }
196}
197
198impl<L: TokenStreamPredicate, S: TokenStreamPredicate> TokenStreamPattern for LastBefore<L, S> {
199 fn process_token(&mut self, p: &mut Parser, offset: i32, top_level: bool) -> bool {
200 let look_for_result = self.look_for.matching(p, top_level);
201 if look_for_result {
202 self.base.last_occurrence = offset;
203 }
204 if self.stop_at.matching(p, top_level)
205 && top_level
206 && (!self.dont_stop_right_after_occurrence || !self.previous_look_for_result)
207 {
208 return true;
209 }
210 self.previous_look_for_result = look_for_result;
211 false
212 }
213
214 fn result(&self) -> i32 {
215 self.base.last_occurrence
216 }
217}
218
219pub struct At {
221 look_for: SyntaxKind,
222 top_level_only: bool,
223}
224
225impl At {
226 pub fn new(look_for: SyntaxKind) -> At {
227 At::new_2(look_for, true)
228 }
229
230 pub fn new_2(look_for: SyntaxKind, top_level_only: bool) -> At {
231 At { look_for, top_level_only }
232 }
233}
234
235impl TokenStreamPredicate for At {
236 fn matching(&self, p: &mut Parser, top_level: bool) -> bool {
237 (top_level || !self.top_level_only) && p.at(self.look_for)
238 }
239}
240
241pub struct AtSet {
243 look_for: TokenSet,
244 top_level_only: TokenSet,
245}
246
247impl AtSet {
248 pub fn new(look_for: TokenSet) -> AtSet {
249 AtSet::new_2(look_for, look_for)
250 }
251
252 pub fn new_2(look_for: TokenSet, top_level_only: TokenSet) -> AtSet {
253 AtSet { look_for, top_level_only }
254 }
255}
256
257impl TokenStreamPredicate for AtSet {
258 fn matching(&self, p: &mut Parser, top_level: bool) -> bool {
259 (top_level || !p.at_set(self.top_level_only)) && p.at_set(self.look_for)
260 }
261}