1use std::{collections::HashSet, mem::discriminant, sync::LazyLock};
2
3use crate::lexer::{MultilineString, SpannedToken, Token, TokenKind};
4use crate::list::TokenKindList;
5use crate::parser::parse_error::{ParseError, ParseErrorMessage};
6use crate::parser::types::*;
7use crate::parser::RsmlParser;
8use crate::types::LanguageMode;
9
10type SymResult<T> = Result<T, T>;
11
12impl<'a> RsmlParser<'a> {
13 pub(crate) fn next_token(&mut self) -> Option<SpannedToken<'a>> {
14 self.lexer.next()
15 }
16
17 pub(crate) fn handle_multiline_string_error(
18 &mut self,
19 token: &SpannedToken,
20 expected_nestedness: usize
21 ) {
22 self.ast_errors.push(
23 ParseError::MissingToken {
24 msg: Some(ParseErrorMessage::Expected(&format!("\"]{}]\"", "=".repeat(expected_nestedness))))
25 },
26 self.range_from_span(clamp_span_to_end(token.end()))
27 )
28 }
29
30 pub(crate) fn next_node(&mut self) -> Option<Node<'a>> {
31 if let Some(node) = self.pending_node.take() {
32 return Some(node);
33 }
34
35 let mut token = self.next_token()?;
36
37 match token.value() {
38 Token::CommentMulti(MultilineString { nestedness: Err(expected_nestedness), .. }) => {
39 self.handle_multiline_string_error(&token, *expected_nestedness)
40 },
41
42 Token::Directive(_) => self.handle_directive_token(&token),
43
44 Token::CommentSingle(_) | Token::CommentMulti(MultilineString { nestedness: Ok(_), .. }) => (),
45
46 _ => return Some(Node {
47 token: token,
48 leading_trivia: None
49 })
50 }
51
52 let mut leading_trivia = vec![ token ];
53
54 loop {
55 let Some(next_token) = self.next_token() else {
56 return Some(Node {
57 token: SpannedToken::new(self.last_token_end, Token::None, self.last_token_end),
58 leading_trivia: Some(leading_trivia)
59 })
60 };
61 token = next_token;
62
63 match token.value() {
64 Token::CommentMulti(MultilineString { nestedness: Err(expected_nestedness), .. }) => {
65 self.handle_multiline_string_error(&token, *expected_nestedness);
66
67 leading_trivia.push(token);
68 },
69
70 Token::Directive(_) => {
71 self.handle_directive_token(&token);
72 leading_trivia.push(token);
73 },
74
75 Token::CommentSingle(_) | Token::CommentMulti(MultilineString { nestedness: Ok(_), .. }) =>
76 leading_trivia.push(token),
77
78 _ => return Some(Node {
79 token: token,
80 leading_trivia: Some(leading_trivia)
81 })
82 }
83 }
84 }
85
86 fn handle_directive_token(&mut self, token: &SpannedToken<'a>) {
87 if !self.directives_phase_done {
88 return;
89 }
90
91 let Token::Directive(text) = token.value() else {
92 return;
93 };
94
95 let name = text.split_whitespace().next().unwrap_or("").to_string();
96 self.ast_errors.push(
97 ParseError::DirectiveNotAtTop { name },
98 self.range_from_span(token.span()),
99 );
100 }
101
102 pub(crate) fn parse_directives(&mut self) {
103 let node = self.next_node();
104
105 'directives: {
106 let Some(node) = &node else { break 'directives };
107 let Some(trivia) = &node.leading_trivia else { break 'directives };
108
109 for token in trivia {
110 if let Token::Directive(text) = token.value() {
111 self.apply_directive(text.trim(), token.span());
112 }
113 }
114 }
115
116 self.pending_node = node;
117 self.directives_phase_done = true;
118 }
119
120 fn apply_directive(&mut self, text: &str, span: (usize, usize)) {
121 if text.is_empty() {
122 self.ast_errors.push(ParseError::EmptyDirective, self.range_from_span(span));
123 return;
124 }
125
126 let name = text.split_whitespace().next().unwrap_or("");
127 match name {
128 "nobuiltins" => self.directives.nobuiltins = true,
129 "strict" => self.directives.language_mode = Some(LanguageMode::Strict),
130 "nonstrict" => self.directives.language_mode = Some(LanguageMode::Nonstrict),
131 _ => self.ast_errors.push(
132 ParseError::UnknownDirective { name: name.to_string() },
133 self.range_from_span(span),
134 ),
135 }
136 }
137
138 pub(crate) fn advance_without_flags<'b>(
140 &mut self
141 ) -> Option<Node<'a>> {
142 match self.next_node()? {
143 Node { token: SpannedToken (span_start, Token::Error, mut span_end), .. } => loop {
144 match self.next_node() {
145 Some(Node { token: SpannedToken (_, Token::Error, next_span_end), .. }) => span_end = next_span_end,
146
147 node => {
148 self.ast_errors.push(
149 ParseError::UnexpectedTokens { msg: None },
150 self.range_from_span((span_start, span_end))
151 );
152
153 break node
154 }
155 }
156 },
157
158 node => Some(node)
159 }
160 }
161
162 pub fn advance(&mut self) -> Option<Node<'a>> {
164 let node = self.advance_without_flags()
165 .update_last_token_end(self);
166 self.did_advance = true;
167
168 node
169 }
170
171 pub(crate) fn advance_until_core_loop<const N: usize>(
172 &mut self,
173 allow_list: &TokenKindList<N>,
174 construct_delimiters: &LazyLock<HashSet<TokenKind>>,
175 span_start: usize, mut span_end: usize
176 ) -> Option<SymResult<Node<'a>>> {
177 loop {
178 match self.next_node() {
179 Some(Node { token: SpannedToken (_, Token::Error, next_span_end), .. }) => span_end = next_span_end,
180
181 Some(node) => {
182 let token = &node.token;
183 let token_kind = &token.value().kind();
184
185 if allow_list.has_discriminant(&discriminant(token_kind)) {
186 self.ast_errors.push(
187 ParseError::UnexpectedTokens { msg: None },
188 self.range_from_span((span_start, span_end))
189 );
190
191 self.last_token_end = token.end();
192
193 break Some(Ok(node))
194
195 } else if construct_delimiters.contains(token_kind) {
196 self.ast_errors.push(
197 ParseError::UnexpectedTokens {
198 msg: allow_list.to_string().as_deref().map(|x| ParseErrorMessage::Expected(x))
199 },
200 self.range_from_span((span_start, span_end))
201 );
202
203 break Some(Err(node))
204
205 } else {
206 span_end = token.end()
207 }
208 },
209
210 None => {
211 self.ast_errors.push(
212 ParseError::UnexpectedTokens {
213 msg: allow_list.to_string().as_deref().map(|x| ParseErrorMessage::Expected(x))
214 },
215 self.range_from_span((span_start, span_end))
216 );
217
218 break None
219 }
220 }
221 }
222 }
223
224 pub(crate) fn advance_until_without_flag<const N: usize>(
226 &mut self,
227 allow_list: &TokenKindList<N>,
228 construct_delimiters: &LazyLock<HashSet<TokenKind>>
229 ) -> Option<SymResult<Node<'a>>> {
230 match self.next_node() {
231 Some(Node { token: SpannedToken (span_start, Token::Error, span_end), .. }) => {
232 self.advance_until_core_loop(allow_list, construct_delimiters, span_start, span_end)
233 },
234
235 Some(node) => {
236 let token = &node.token;
237 let token_kind = &token.value().kind();
238
239 if allow_list.has_discriminant(&discriminant(&token_kind)) {
240 self.last_token_end = token.end();
241
242 Some(Ok(node))
243
244 } else if construct_delimiters.contains(token_kind) {
245 self.ast_errors.push(
246 ParseError::MissingToken {
247 msg: allow_list.to_string().as_deref().map(|x| ParseErrorMessage::Expected(x))
248 },
249 self.range_from_span(clamp_span_to_end(self.last_token_end))
250 );
251
252 Some(Err(node))
253
254 } else {
255 self.advance_until_core_loop(allow_list, construct_delimiters, token.start(), token.end())
256 }
257 },
258
259 None => {
260 self.ast_errors.push(
261 ParseError::MissingToken {
262 msg: allow_list.to_string().as_deref().map(|x| ParseErrorMessage::Expected(x))
263 },
264 self.range_from_span(clamp_span_to_end(self.last_token_end))
265 );
266
267 None
268 }
269 }
270 }
271
272 pub(crate) fn advance_until<const N: usize>(
274 &mut self,
275 allow_list: &TokenKindList<N>,
276 construct_delimiters: &LazyLock<HashSet<TokenKind>>
277 ) -> Option<SymResult<Node<'a>>> {
278 let next = self.advance_until_without_flag(allow_list, construct_delimiters);
279 self.did_advance = true;
280 next
281 }
282
283 pub(crate) fn node_is_kind_else_advance_until<const N: usize>(
284 &mut self,
285 node: Node<'a>,
286 allow_list: &TokenKindList<N>,
287 construct_delimiters: &LazyLock<HashSet<TokenKind>>
288 ) -> Option<SymResult<Node<'a>>> {
289 if allow_list.has_discriminant(&node.token.value().discriminant()) { return Some(Ok(node)) };
290
291 if construct_delimiters.contains(&node.token.value().kind()) {
292 self.ast_errors.push(
293 ParseError::MissingToken {
294 msg: allow_list.to_string().as_deref().map(|x| ParseErrorMessage::Expected(x))
295 },
296 self.range_from_span(clamp_span_to_end(self.last_token_end))
297 );
298
299 return Some(Err(node))
300 }
301
302 let last_token = node.token;
303
304 match self.next_node() {
305 Some(Node { token: SpannedToken (_, Token::Error, span_end), .. }) => {
306 self.advance_until_core_loop(allow_list, construct_delimiters, last_token.start(), span_end)
307 },
308
309 Some(node) => {
310 let token = &node.token;
311 let token_kind = &token.value().kind();
312
313 if allow_list.has_discriminant(&discriminant(&token_kind)) {
314 self.ast_errors.push(
315 ParseError::UnexpectedTokens { msg: None },
316 self.range_from_span(last_token.span())
317 );
318
319 self.last_token_end = token.end();
320
321 Some(Ok(node))
322
323 } else if construct_delimiters.contains(token_kind) {
324 self.ast_errors.push(
325 ParseError::UnexpectedTokens {
326 msg: allow_list.to_string().as_deref().map(|x| ParseErrorMessage::Expected(x))
327 },
328 self.range_from_span(last_token.span())
329 );
330
331 Some(Err(node))
332
333 } else {
334 self.advance_until_core_loop(allow_list, construct_delimiters, last_token.start(), token.end())
335 }
336 },
337
338 None => {
339 self.ast_errors.push(
340 ParseError::UnexpectedTokens {
341 msg: allow_list.to_string().as_deref().map(|x| ParseErrorMessage::Expected(x))
342 },
343 self.range_from_span(last_token.span())
344 );
345
346 None
347 }
348 }
349
350 }
351
352 pub(crate) fn optional_node_is_kind_else_advance_until<const N: usize>(
353 &mut self,
354 node: Option<Node<'a>>,
355 allow_list: &TokenKindList<N>,
356 construct_delimiters: &LazyLock<HashSet<TokenKind>>
357 ) -> Option<SymResult<Node<'a>>> {
358 match node {
359 Some(node) => self.node_is_kind_else_advance_until(node, allow_list, construct_delimiters),
360
361 None => {
362 self.ast_errors.push(
363 ParseError::MissingToken {
364 msg: allow_list.to_string().as_deref().map(|x| ParseErrorMessage::Expected(x))
365 },
366 self.range_from_span(clamp_span_to_end(self.last_token_end))
367 );
368
369 None
370 }
371 }
372 }
373}