1use std::mem;
2use std::ops::{Index, IndexMut, Range};
3
4use ecow::{EcoString, eco_format};
5use rustc_hash::{FxHashMap, FxHashSet};
6use typst_utils::default_math_class;
7use unicode_math_class::MathClass;
8
9use crate::set::{SyntaxSet, syntax_set};
10use crate::{Lexer, SyntaxError, SyntaxKind, SyntaxMode, SyntaxNode, ast, set};
11
12pub fn parse(text: &str) -> SyntaxNode {
14 let _scope = typst_timing::TimingScope::new("parse");
15 let mut p = Parser::new(text, 0, SyntaxMode::Markup);
16 markup_exprs(&mut p, true, syntax_set!(End));
17 p.finish_into(SyntaxKind::Markup)
18}
19
20pub fn parse_code(text: &str) -> SyntaxNode {
22 let _scope = typst_timing::TimingScope::new("parse code");
23 let mut p = Parser::new(text, 0, SyntaxMode::Code);
24 code_exprs(&mut p, syntax_set!(End));
25 p.finish_into(SyntaxKind::Code)
26}
27
28pub fn parse_math(text: &str) -> SyntaxNode {
30 let _scope = typst_timing::TimingScope::new("parse math");
31 let mut p = Parser::new(text, 0, SyntaxMode::Math);
32 math_exprs(&mut p, syntax_set!(End));
33 p.finish_into(SyntaxKind::Math)
34}
35
36fn markup(p: &mut Parser, at_start: bool, wrap_trivia: bool, stop_set: SyntaxSet) {
38 let m = if wrap_trivia { p.before_trivia() } else { p.marker() };
39 markup_exprs(p, at_start, stop_set);
40 if wrap_trivia {
41 p.flush_trivia();
42 }
43 p.wrap(m, SyntaxKind::Markup);
44}
45
46fn markup_exprs(p: &mut Parser, mut at_start: bool, stop_set: SyntaxSet) {
48 debug_assert!(stop_set.contains(SyntaxKind::End));
49 at_start |= p.had_newline();
50 let mut nesting: usize = 0;
51 while !p.at_set(stop_set) || (nesting > 0 && p.at(SyntaxKind::RightBracket)) {
53 markup_expr(p, at_start, &mut nesting);
54 at_start = p.had_newline();
55 }
56}
57
58pub(super) fn reparse_markup(
60 text: &str,
61 range: Range<usize>,
62 at_start: &mut bool,
63 nesting: &mut usize,
64 top_level: bool,
65) -> Option<Vec<SyntaxNode>> {
66 let mut p = Parser::new(text, range.start, SyntaxMode::Markup);
67 *at_start |= p.had_newline();
68 while !p.end() && p.current_start() < range.end {
69 if !top_level && *nesting == 0 && p.at(SyntaxKind::RightBracket) {
71 break;
72 }
73 markup_expr(&mut p, *at_start, nesting);
74 *at_start = p.had_newline();
75 }
76 (p.balanced && p.current_start() == range.end).then(|| p.finish())
77}
78
79fn markup_expr(p: &mut Parser, at_start: bool, nesting: &mut usize) {
83 match p.current() {
84 SyntaxKind::LeftBracket => {
85 *nesting += 1;
86 p.convert_and_eat(SyntaxKind::Text);
87 }
88 SyntaxKind::RightBracket if *nesting > 0 => {
89 *nesting -= 1;
90 p.convert_and_eat(SyntaxKind::Text);
91 }
92 SyntaxKind::RightBracket => {
93 p.unexpected();
94 p.hint("try using a backslash escape: \\]");
95 }
96
97 SyntaxKind::Shebang => p.eat(),
98
99 SyntaxKind::Text
100 | SyntaxKind::Linebreak
101 | SyntaxKind::Escape
102 | SyntaxKind::Shorthand
103 | SyntaxKind::SmartQuote
104 | SyntaxKind::Link
105 | SyntaxKind::Label => p.eat(),
106
107 SyntaxKind::Raw => p.eat(), SyntaxKind::Hash => embedded_code_expr(p),
110 SyntaxKind::Star => strong(p),
111 SyntaxKind::Underscore => emph(p),
112 SyntaxKind::HeadingMarker if at_start => heading(p),
113 SyntaxKind::ListMarker if at_start => list_item(p),
114 SyntaxKind::EnumMarker if at_start => enum_item(p),
115 SyntaxKind::TermMarker if at_start => term_item(p),
116 SyntaxKind::RefMarker => reference(p),
117 SyntaxKind::Dollar => equation(p),
118
119 SyntaxKind::HeadingMarker
120 | SyntaxKind::ListMarker
121 | SyntaxKind::EnumMarker
122 | SyntaxKind::TermMarker
123 | SyntaxKind::Colon => p.convert_and_eat(SyntaxKind::Text),
124
125 _ => p.unexpected(),
126 }
127}
128
129fn strong(p: &mut Parser) {
131 p.with_nl_mode(AtNewline::StopParBreak, |p| {
132 let m = p.marker();
133 p.assert(SyntaxKind::Star);
134 markup(p, false, true, syntax_set!(Star, RightBracket, End));
135 p.expect_closing_delimiter(m, SyntaxKind::Star);
136 p.wrap(m, SyntaxKind::Strong);
137 });
138}
139
140fn emph(p: &mut Parser) {
142 p.with_nl_mode(AtNewline::StopParBreak, |p| {
143 let m = p.marker();
144 p.assert(SyntaxKind::Underscore);
145 markup(p, false, true, syntax_set!(Underscore, RightBracket, End));
146 p.expect_closing_delimiter(m, SyntaxKind::Underscore);
147 p.wrap(m, SyntaxKind::Emph);
148 });
149}
150
151fn heading(p: &mut Parser) {
153 p.with_nl_mode(AtNewline::Stop, |p| {
154 let m = p.marker();
155 p.assert(SyntaxKind::HeadingMarker);
156 markup(p, false, false, syntax_set!(Label, RightBracket, End));
157 p.wrap(m, SyntaxKind::Heading);
158 });
159}
160
161fn list_item(p: &mut Parser) {
163 p.with_nl_mode(AtNewline::RequireColumn(p.current_column()), |p| {
164 let m = p.marker();
165 p.assert(SyntaxKind::ListMarker);
166 markup(p, true, false, syntax_set!(RightBracket, End));
167 p.wrap(m, SyntaxKind::ListItem);
168 });
169}
170
171fn enum_item(p: &mut Parser) {
173 p.with_nl_mode(AtNewline::RequireColumn(p.current_column()), |p| {
174 let m = p.marker();
175 p.assert(SyntaxKind::EnumMarker);
176 markup(p, true, false, syntax_set!(RightBracket, End));
177 p.wrap(m, SyntaxKind::EnumItem);
178 });
179}
180
181fn term_item(p: &mut Parser) {
183 p.with_nl_mode(AtNewline::RequireColumn(p.current_column()), |p| {
184 let m = p.marker();
185 p.with_nl_mode(AtNewline::Stop, |p| {
186 p.assert(SyntaxKind::TermMarker);
187 markup(p, false, false, syntax_set!(Colon, RightBracket, End));
188 });
189 p.expect(SyntaxKind::Colon);
190 markup(p, true, false, syntax_set!(RightBracket, End));
191 p.wrap(m, SyntaxKind::TermItem);
192 });
193}
194
195fn reference(p: &mut Parser) {
197 let m = p.marker();
198 p.assert(SyntaxKind::RefMarker);
199 if p.directly_at(SyntaxKind::LeftBracket) {
200 content_block(p);
201 }
202 p.wrap(m, SyntaxKind::Ref);
203}
204
205fn equation(p: &mut Parser) {
207 let m = p.marker();
208 p.enter_modes(SyntaxMode::Math, AtNewline::Continue, |p| {
209 p.assert(SyntaxKind::Dollar);
210 math(p, syntax_set!(Dollar, End));
211 p.expect_closing_delimiter(m, SyntaxKind::Dollar);
212 });
213 p.wrap(m, SyntaxKind::Equation);
214}
215
216fn math(p: &mut Parser, stop_set: SyntaxSet) {
218 let m = p.marker();
219 math_exprs(p, stop_set);
220 p.wrap(m, SyntaxKind::Math);
221}
222
223fn math_exprs(p: &mut Parser, stop_set: SyntaxSet) -> usize {
226 debug_assert!(stop_set.contains(SyntaxKind::End));
227 let mut count = 0;
228 while !p.at_set(stop_set) {
229 if p.at_set(set::MATH_EXPR) {
230 math_expr(p);
231 count += 1;
232 } else {
233 p.unexpected();
234 }
235 }
236 count
237}
238
239fn math_expr(p: &mut Parser) {
242 math_expr_prec(p, 0, SyntaxKind::End)
243}
244
245fn math_expr_prec(p: &mut Parser, min_prec: usize, stop: SyntaxKind) {
247 let m = p.marker();
248 let mut continuable = false;
249 match p.current() {
250 SyntaxKind::Hash => embedded_code_expr(p),
251 SyntaxKind::MathIdent | SyntaxKind::FieldAccess => {
253 continuable = true;
254 p.eat();
255 if min_prec < 3
257 && p.directly_at(SyntaxKind::MathText)
258 && p.current_text() == "("
259 {
260 math_args(p);
261 p.wrap(m, SyntaxKind::FuncCall);
262 continuable = false;
263 }
264 }
265
266 SyntaxKind::Dot
267 | SyntaxKind::Comma
268 | SyntaxKind::Semicolon
269 | SyntaxKind::RightParen => {
270 p.convert_and_eat(SyntaxKind::MathText);
271 }
272
273 SyntaxKind::Text | SyntaxKind::MathText | SyntaxKind::MathShorthand => {
274 continuable = math_class(p.current_text()) == Some(MathClass::Alphabetic)
276 || p.current_text().chars().all(char::is_alphabetic);
277 if !maybe_delimited(p) {
278 p.eat();
279 }
280 }
281
282 SyntaxKind::Linebreak | SyntaxKind::MathAlignPoint => p.eat(),
283 SyntaxKind::Escape | SyntaxKind::Str => {
284 continuable = true;
285 p.eat();
286 }
287
288 SyntaxKind::Root => {
289 if min_prec < 3 {
290 p.eat();
291 let m2 = p.marker();
292 math_expr_prec(p, 2, stop);
293 math_unparen(p, m2);
294 p.wrap(m, SyntaxKind::MathRoot);
295 }
296 }
297
298 SyntaxKind::Prime => {
299 continuable = true;
301 while p.at(SyntaxKind::Prime) {
302 let m2 = p.marker();
303 p.eat();
304 while p.eat_if_direct(SyntaxKind::Prime) {}
306 p.wrap(m2, SyntaxKind::MathPrimes);
307 }
308 }
309
310 _ => p.expected("expression"),
311 }
312
313 if continuable && min_prec < 3 && !p.had_trivia() && maybe_delimited(p) {
314 p.wrap(m, SyntaxKind::Math);
315 }
316
317 let mut primed = false;
319
320 while !p.end() && !p.at(stop) {
321 if p.directly_at(SyntaxKind::MathText) && p.current_text() == "!" {
322 p.eat();
323 p.wrap(m, SyntaxKind::Math);
324 continue;
325 }
326
327 let prime_marker = p.marker();
328 if p.eat_if_direct(SyntaxKind::Prime) {
329 while p.eat_if_direct(SyntaxKind::Prime) {}
331 p.wrap(prime_marker, SyntaxKind::MathPrimes);
332
333 if p.at(stop) {
335 p.wrap(m, SyntaxKind::MathAttach);
336 }
337
338 primed = true;
339 continue;
340 }
341
342 let Some((kind, stop, assoc, mut prec)) = math_op(p.current()) else {
343 if primed {
345 p.wrap(m, SyntaxKind::MathAttach);
346 }
347
348 break;
349 };
350
351 if primed && kind == SyntaxKind::MathFrac {
352 p.wrap(m, SyntaxKind::MathAttach);
353 }
354
355 if prec < min_prec {
356 break;
357 }
358
359 match assoc {
360 ast::Assoc::Left => prec += 1,
361 ast::Assoc::Right => {}
362 }
363
364 if kind == SyntaxKind::MathFrac {
365 math_unparen(p, m);
366 }
367
368 p.eat();
369 let m2 = p.marker();
370 math_expr_prec(p, prec, stop);
371 math_unparen(p, m2);
372
373 if p.eat_if(SyntaxKind::Underscore) || p.eat_if(SyntaxKind::Hat) {
374 let m3 = p.marker();
375 math_expr_prec(p, prec, SyntaxKind::End);
376 math_unparen(p, m3);
377 }
378
379 p.wrap(m, kind);
380 }
381}
382
383fn math_op(kind: SyntaxKind) -> Option<(SyntaxKind, SyntaxKind, ast::Assoc, usize)> {
385 match kind {
386 SyntaxKind::Underscore => {
387 Some((SyntaxKind::MathAttach, SyntaxKind::Hat, ast::Assoc::Right, 2))
388 }
389 SyntaxKind::Hat => {
390 Some((SyntaxKind::MathAttach, SyntaxKind::Underscore, ast::Assoc::Right, 2))
391 }
392 SyntaxKind::Slash => {
393 Some((SyntaxKind::MathFrac, SyntaxKind::End, ast::Assoc::Left, 1))
394 }
395 _ => None,
396 }
397}
398
399fn maybe_delimited(p: &mut Parser) -> bool {
401 let open = math_class(p.current_text()) == Some(MathClass::Opening);
402 if open {
403 math_delimited(p);
404 }
405 open
406}
407
408fn math_delimited(p: &mut Parser) {
410 let m = p.marker();
411 p.eat();
412 let m2 = p.marker();
413 while !p.at_set(syntax_set!(Dollar, End)) {
414 if math_class(p.current_text()) == Some(MathClass::Closing) {
415 p.wrap(m2, SyntaxKind::Math);
416 if p.at(SyntaxKind::RightParen) {
419 p.convert_and_eat(SyntaxKind::MathText);
420 } else {
421 p.eat();
422 }
423 p.wrap(m, SyntaxKind::MathDelimited);
424 return;
425 }
426
427 if p.at_set(set::MATH_EXPR) {
428 math_expr(p);
429 } else {
430 p.unexpected();
431 }
432 }
433
434 p.wrap(m, SyntaxKind::Math);
435}
436
437fn math_unparen(p: &mut Parser, m: Marker) {
440 let Some(node) = p.nodes.get_mut(m.0) else { return };
441 if node.kind() != SyntaxKind::MathDelimited {
442 return;
443 }
444
445 if let [first, .., last] = node.children_mut()
446 && first.text() == "("
447 && last.text() == ")"
448 {
449 first.convert_to_kind(SyntaxKind::LeftParen);
450 last.convert_to_kind(SyntaxKind::RightParen);
451 node.convert_to_kind(SyntaxKind::Math);
453 }
454}
455
456fn math_class(text: &str) -> Option<MathClass> {
461 match text {
462 "[|" => return Some(MathClass::Opening),
463 "|]" => return Some(MathClass::Closing),
464 "||" => return Some(MathClass::Fence),
465 _ => {}
466 }
467
468 let mut chars = text.chars();
469 chars
470 .next()
471 .filter(|_| chars.next().is_none())
472 .and_then(default_math_class)
473}
474
475fn math_args(p: &mut Parser) {
477 let m = p.marker();
478 p.convert_and_eat(SyntaxKind::LeftParen);
479
480 let mut positional = true;
481 let mut has_arrays = false;
482
483 let mut maybe_array_start = p.marker();
484 let mut seen = FxHashSet::default();
485 while !p.at_set(syntax_set!(End, Dollar, RightParen)) {
486 positional = math_arg(p, &mut seen);
487
488 match p.current() {
489 SyntaxKind::Comma => {
490 p.eat();
491 if !positional {
492 maybe_array_start = p.marker();
493 }
494 }
495 SyntaxKind::Semicolon => {
496 if !positional {
497 maybe_array_start = p.marker();
498 }
499
500 p.wrap(maybe_array_start, SyntaxKind::Array);
504 p.eat();
505 maybe_array_start = p.marker();
506 has_arrays = true;
507 }
508 SyntaxKind::End | SyntaxKind::Dollar | SyntaxKind::RightParen => {}
509 _ => p.expected("comma or semicolon"),
510 }
511 }
512
513 if maybe_array_start != p.marker() && has_arrays && positional {
515 p.wrap(maybe_array_start, SyntaxKind::Array);
516 }
517
518 p.expect_closing_delimiter(m, SyntaxKind::RightParen);
519 p.wrap(m, SyntaxKind::Args);
520}
521
522fn math_arg<'s>(p: &mut Parser<'s>, seen: &mut FxHashSet<&'s str>) -> bool {
526 let m = p.marker();
527 let start = p.current_start();
528
529 if p.at(SyntaxKind::Dot) {
530 if let Some(spread) = p.lexer.maybe_math_spread_arg(start) {
532 p.token.node = spread;
533 p.eat();
534 let m_arg = p.marker();
535 let count =
537 math_exprs(p, syntax_set!(End, Dollar, Comma, Semicolon, RightParen));
538 if count == 0 {
539 let dots = vec![
540 SyntaxNode::leaf(SyntaxKind::MathText, "."),
541 SyntaxNode::leaf(SyntaxKind::MathText, "."),
542 ];
543 p[m] = SyntaxNode::inner(SyntaxKind::Math, dots);
544 } else {
545 if count > 1 {
546 p.wrap(m_arg, SyntaxKind::Math);
547 }
548 p.wrap(m, SyntaxKind::Spread);
549 }
550 return true;
551 }
552 }
553
554 let mut positional = true;
555 if p.at_set(syntax_set!(MathText, MathIdent, Underscore)) {
556 if let Some(named) = p.lexer.maybe_math_named_arg(start) {
558 p.token.node = named;
559 let text = p.current_text();
560 p.eat();
561 p.convert_and_eat(SyntaxKind::Colon);
562 if !seen.insert(text) {
563 p[m].convert_to_error(eco_format!("duplicate argument: {text}"));
564 }
565 positional = false;
566 }
567 }
568
569 let arg = p.marker();
571 let count = math_exprs(p, syntax_set!(End, Dollar, Comma, Semicolon, RightParen));
572 if count == 0 {
573 if !positional {
575 p.expected("expression");
576 }
577
578 p.flush_trivia();
586 }
587
588 if count != 1 {
594 p.wrap(arg, SyntaxKind::Math);
595 }
596
597 if !positional {
598 p.wrap(m, SyntaxKind::Named);
599 }
600 positional
601}
602
603fn code(p: &mut Parser, stop_set: SyntaxSet) {
605 let m = p.marker();
606 code_exprs(p, stop_set);
607 p.wrap(m, SyntaxKind::Code);
608}
609
610fn code_exprs(p: &mut Parser, stop_set: SyntaxSet) {
612 debug_assert!(stop_set.contains(SyntaxKind::End));
613 while !p.at_set(stop_set) {
614 p.with_nl_mode(AtNewline::ContextualContinue, |p| {
615 if !p.at_set(set::CODE_EXPR) {
616 p.unexpected();
617 return;
618 }
619 code_expr(p);
620 if !p.at_set(stop_set) && !p.eat_if(SyntaxKind::Semicolon) {
621 p.expected("semicolon or line break");
622 if p.at(SyntaxKind::Label) {
623 p.hint("labels can only be applied in markup mode");
624 p.hint("try wrapping your code in a markup block (`[ ]`)");
625 }
626 }
627 });
628 }
629}
630
631fn embedded_code_expr(p: &mut Parser) {
633 p.enter_modes(SyntaxMode::Code, AtNewline::Stop, |p| {
634 p.assert(SyntaxKind::Hash);
635 if p.had_trivia() || p.end() {
636 p.expected("expression");
637 return;
638 }
639
640 let stmt = p.at_set(set::STMT);
641 let at = p.at_set(set::ATOMIC_CODE_EXPR);
642 code_expr_prec(p, true, 0);
643
644 if !at {
646 p.unexpected();
647 }
648
649 let semi = (stmt || p.directly_at(SyntaxKind::Semicolon))
650 && p.eat_if(SyntaxKind::Semicolon);
651
652 if stmt && !semi && !p.end() && !p.at(SyntaxKind::RightBracket) {
653 p.expected("semicolon or line break");
654 }
655 });
656}
657
658fn code_expr(p: &mut Parser) {
660 code_expr_prec(p, false, 0)
661}
662
663fn code_expr_prec(p: &mut Parser, atomic: bool, min_prec: u8) {
665 let m = p.marker();
666 if !atomic && p.at_set(set::UNARY_OP) {
667 let op = ast::UnOp::from_kind(p.current()).unwrap();
668 p.eat();
669 code_expr_prec(p, atomic, op.precedence());
670 p.wrap(m, SyntaxKind::Unary);
671 } else {
672 code_primary(p, atomic);
673 }
674
675 loop {
676 if p.directly_at(SyntaxKind::LeftParen) || p.directly_at(SyntaxKind::LeftBracket)
677 {
678 args(p);
679 p.wrap(m, SyntaxKind::FuncCall);
680 continue;
681 }
682
683 let at_field_or_method = p.directly_at(SyntaxKind::Dot)
684 && p.lexer.clone().next().0 == SyntaxKind::Ident;
685
686 if atomic && !at_field_or_method {
687 break;
688 }
689
690 if p.eat_if(SyntaxKind::Dot) {
691 p.expect(SyntaxKind::Ident);
692 p.wrap(m, SyntaxKind::FieldAccess);
693 continue;
694 }
695
696 let binop = if p.at_set(set::BINARY_OP) {
697 ast::BinOp::from_kind(p.current())
698 } else if min_prec <= ast::BinOp::NotIn.precedence() && p.eat_if(SyntaxKind::Not)
699 {
700 if p.at(SyntaxKind::In) {
701 Some(ast::BinOp::NotIn)
702 } else {
703 p.expected("keyword `in`");
704 break;
705 }
706 } else {
707 None
708 };
709
710 if let Some(op) = binop {
711 let mut prec = op.precedence();
712 if prec < min_prec {
713 break;
714 }
715
716 match op.assoc() {
717 ast::Assoc::Left => prec += 1,
718 ast::Assoc::Right => {}
719 }
720
721 p.eat();
722 code_expr_prec(p, false, prec);
723 p.wrap(m, SyntaxKind::Binary);
724 continue;
725 }
726
727 break;
728 }
729}
730
731fn code_primary(p: &mut Parser, atomic: bool) {
735 let m = p.marker();
736 match p.current() {
737 SyntaxKind::Ident => {
738 p.eat();
739 if !atomic && p.at(SyntaxKind::Arrow) {
740 p.wrap(m, SyntaxKind::Params);
741 p.assert(SyntaxKind::Arrow);
742 code_expr(p);
743 p.wrap(m, SyntaxKind::Closure);
744 }
745 }
746 SyntaxKind::Underscore if !atomic => {
747 p.eat();
748 if p.at(SyntaxKind::Arrow) {
749 p.wrap(m, SyntaxKind::Params);
750 p.eat();
751 code_expr(p);
752 p.wrap(m, SyntaxKind::Closure);
753 } else if p.eat_if(SyntaxKind::Eq) {
754 code_expr(p);
755 p.wrap(m, SyntaxKind::DestructAssignment);
756 } else {
757 p[m].expected("expression");
758 }
759 }
760
761 SyntaxKind::LeftBrace => code_block(p),
762 SyntaxKind::LeftBracket => content_block(p),
763 SyntaxKind::LeftParen => expr_with_paren(p, atomic),
764 SyntaxKind::Dollar => equation(p),
765 SyntaxKind::Let => let_binding(p),
766 SyntaxKind::Set => set_rule(p),
767 SyntaxKind::Show => show_rule(p),
768 SyntaxKind::Context => contextual(p, atomic),
769 SyntaxKind::If => conditional(p),
770 SyntaxKind::While => while_loop(p),
771 SyntaxKind::For => for_loop(p),
772 SyntaxKind::Import => module_import(p),
773 SyntaxKind::Include => module_include(p),
774 SyntaxKind::Break => break_stmt(p),
775 SyntaxKind::Continue => continue_stmt(p),
776 SyntaxKind::Return => return_stmt(p),
777
778 SyntaxKind::Raw => p.eat(), SyntaxKind::None
781 | SyntaxKind::Auto
782 | SyntaxKind::Int
783 | SyntaxKind::Float
784 | SyntaxKind::Bool
785 | SyntaxKind::Numeric
786 | SyntaxKind::Str
787 | SyntaxKind::Label => p.eat(),
788
789 _ => p.expected("expression"),
790 }
791}
792
793pub(super) fn reparse_block(text: &str, range: Range<usize>) -> Option<SyntaxNode> {
795 let mut p = Parser::new(text, range.start, SyntaxMode::Code);
796 assert!(p.at(SyntaxKind::LeftBracket) || p.at(SyntaxKind::LeftBrace));
797 block(&mut p);
798 (p.balanced && p.prev_end() == range.end)
799 .then(|| p.finish().into_iter().next().unwrap())
800}
801
802fn block(p: &mut Parser) {
804 match p.current() {
805 SyntaxKind::LeftBracket => content_block(p),
806 SyntaxKind::LeftBrace => code_block(p),
807 _ => p.expected("block"),
808 }
809}
810
811fn code_block(p: &mut Parser) {
813 let m = p.marker();
814 p.enter_modes(SyntaxMode::Code, AtNewline::Continue, |p| {
815 p.assert(SyntaxKind::LeftBrace);
816 code(p, syntax_set!(RightBrace, RightBracket, RightParen, End));
817 p.expect_closing_delimiter(m, SyntaxKind::RightBrace);
818 });
819 p.wrap(m, SyntaxKind::CodeBlock);
820}
821
822fn content_block(p: &mut Parser) {
824 let m = p.marker();
825 p.enter_modes(SyntaxMode::Markup, AtNewline::Continue, |p| {
826 p.assert(SyntaxKind::LeftBracket);
827 markup(p, true, true, syntax_set!(RightBracket, End));
828 p.expect_closing_delimiter(m, SyntaxKind::RightBracket);
829 });
830 p.wrap(m, SyntaxKind::ContentBlock);
831}
832
833fn let_binding(p: &mut Parser) {
835 let m = p.marker();
836 p.assert(SyntaxKind::Let);
837
838 let m2 = p.marker();
839 let mut closure = false;
840 let mut other = false;
841
842 if p.eat_if(SyntaxKind::Ident) {
843 if p.directly_at(SyntaxKind::LeftParen) {
844 params(p);
845 closure = true;
846 }
847 } else {
848 pattern(p, false, &mut FxHashSet::default(), None);
849 other = true;
850 }
851
852 let f = if closure || other { Parser::expect } else { Parser::eat_if };
853 if f(p, SyntaxKind::Eq) {
854 code_expr(p);
855 }
856
857 if closure {
858 p.wrap(m2, SyntaxKind::Closure);
859 }
860
861 p.wrap(m, SyntaxKind::LetBinding);
862}
863
864fn set_rule(p: &mut Parser) {
866 let m = p.marker();
867 p.assert(SyntaxKind::Set);
868
869 let m2 = p.marker();
870 p.expect(SyntaxKind::Ident);
871 while p.eat_if(SyntaxKind::Dot) {
872 p.expect(SyntaxKind::Ident);
873 p.wrap(m2, SyntaxKind::FieldAccess);
874 }
875
876 args(p);
877 if p.eat_if(SyntaxKind::If) {
878 code_expr(p);
879 }
880 p.wrap(m, SyntaxKind::SetRule);
881}
882
883fn show_rule(p: &mut Parser) {
885 let m = p.marker();
886 p.assert(SyntaxKind::Show);
887 let m2 = p.before_trivia();
888
889 if !p.at(SyntaxKind::Colon) {
890 code_expr(p);
891 }
892
893 if p.eat_if(SyntaxKind::Colon) {
894 code_expr(p);
895 } else {
896 p.expected_at(m2, "colon");
897 }
898
899 p.wrap(m, SyntaxKind::ShowRule);
900}
901
902fn contextual(p: &mut Parser, atomic: bool) {
904 let m = p.marker();
905 p.assert(SyntaxKind::Context);
906 code_expr_prec(p, atomic, 0);
907 p.wrap(m, SyntaxKind::Contextual);
908}
909
910fn conditional(p: &mut Parser) {
912 let m = p.marker();
913 p.assert(SyntaxKind::If);
914 code_expr(p);
915 block(p);
916 if p.eat_if(SyntaxKind::Else) {
917 if p.at(SyntaxKind::If) {
918 conditional(p);
919 } else {
920 block(p);
921 }
922 }
923 p.wrap(m, SyntaxKind::Conditional);
924}
925
926fn while_loop(p: &mut Parser) {
928 let m = p.marker();
929 p.assert(SyntaxKind::While);
930 code_expr(p);
931 block(p);
932 p.wrap(m, SyntaxKind::WhileLoop);
933}
934
935fn for_loop(p: &mut Parser) {
937 let m = p.marker();
938 p.assert(SyntaxKind::For);
939
940 let mut seen = FxHashSet::default();
941 pattern(p, false, &mut seen, None);
942
943 if p.at(SyntaxKind::Comma) {
944 let node = p.eat_and_get();
945 node.unexpected();
946 node.hint("destructuring patterns must be wrapped in parentheses");
947 if p.at_set(set::PATTERN) {
948 pattern(p, false, &mut seen, None);
949 }
950 }
951
952 p.expect(SyntaxKind::In);
953 code_expr(p);
954 block(p);
955 p.wrap(m, SyntaxKind::ForLoop);
956}
957
958fn module_import(p: &mut Parser) {
960 let m = p.marker();
961 p.assert(SyntaxKind::Import);
962 code_expr(p);
963 if p.eat_if(SyntaxKind::As) {
964 p.expect(SyntaxKind::Ident);
968 }
969
970 if p.eat_if(SyntaxKind::Colon) {
971 if p.at(SyntaxKind::LeftParen) {
972 p.with_nl_mode(AtNewline::Continue, |p| {
973 let m2 = p.marker();
974 p.assert(SyntaxKind::LeftParen);
975
976 import_items(p);
977
978 p.expect_closing_delimiter(m2, SyntaxKind::RightParen);
979 });
980 } else if !p.eat_if(SyntaxKind::Star) {
981 import_items(p);
982 }
983 }
984
985 p.wrap(m, SyntaxKind::ModuleImport);
986}
987
988fn import_items(p: &mut Parser) {
990 let m = p.marker();
991 while !p.current().is_terminator() {
992 let item_marker = p.marker();
993 if !p.eat_if(SyntaxKind::Ident) {
994 p.unexpected();
995 }
996
997 while p.eat_if(SyntaxKind::Dot) {
999 p.expect(SyntaxKind::Ident);
1000 }
1001
1002 p.wrap(item_marker, SyntaxKind::ImportItemPath);
1003
1004 if p.eat_if(SyntaxKind::As) {
1006 p.expect(SyntaxKind::Ident);
1007 p.wrap(item_marker, SyntaxKind::RenamedImportItem);
1008 }
1009
1010 if !p.current().is_terminator() {
1011 p.expect(SyntaxKind::Comma);
1012 }
1013 }
1014
1015 p.wrap(m, SyntaxKind::ImportItems);
1016}
1017
1018fn module_include(p: &mut Parser) {
1020 let m = p.marker();
1021 p.assert(SyntaxKind::Include);
1022 code_expr(p);
1023 p.wrap(m, SyntaxKind::ModuleInclude);
1024}
1025
1026fn break_stmt(p: &mut Parser) {
1028 let m = p.marker();
1029 p.assert(SyntaxKind::Break);
1030 p.wrap(m, SyntaxKind::LoopBreak);
1031}
1032
1033fn continue_stmt(p: &mut Parser) {
1035 let m = p.marker();
1036 p.assert(SyntaxKind::Continue);
1037 p.wrap(m, SyntaxKind::LoopContinue);
1038}
1039
1040fn return_stmt(p: &mut Parser) {
1042 let m = p.marker();
1043 p.assert(SyntaxKind::Return);
1044 if p.at_set(set::CODE_EXPR) {
1045 code_expr(p);
1046 }
1047 p.wrap(m, SyntaxKind::FuncReturn);
1048}
1049
1050fn expr_with_paren(p: &mut Parser, atomic: bool) {
1052 if atomic {
1053 parenthesized_or_array_or_dict(p);
1056 return;
1057 }
1058
1059 let Some((memo_key, checkpoint)) = p.restore_memo_or_checkpoint() else { return };
1063 let prev_len = checkpoint.node_len;
1065
1066 let kind = parenthesized_or_array_or_dict(p);
1071
1072 if p.at(SyntaxKind::Arrow) {
1090 p.restore(checkpoint);
1091 let m = p.marker();
1092 params(p);
1093 if !p.expect(SyntaxKind::Arrow) {
1094 return;
1095 }
1096 code_expr(p);
1097 p.wrap(m, SyntaxKind::Closure);
1098 } else if p.at(SyntaxKind::Eq) && kind != SyntaxKind::Parenthesized {
1099 p.restore(checkpoint);
1100 let m = p.marker();
1101 destructuring_or_parenthesized(p, true, &mut FxHashSet::default());
1102 if !p.expect(SyntaxKind::Eq) {
1103 return;
1104 }
1105 code_expr(p);
1106 p.wrap(m, SyntaxKind::DestructAssignment);
1107 } else {
1108 return;
1109 }
1110
1111 p.memoize_parsed_nodes(memo_key, prev_len);
1113}
1114
1115fn parenthesized_or_array_or_dict(p: &mut Parser) -> SyntaxKind {
1120 let mut state = GroupState {
1121 count: 0,
1122 maybe_just_parens: true,
1123 kind: None,
1124 seen: FxHashSet::default(),
1125 };
1126
1127 let m = p.marker();
1143 p.with_nl_mode(AtNewline::Continue, |p| {
1144 p.assert(SyntaxKind::LeftParen);
1145 if p.eat_if(SyntaxKind::Colon) {
1146 state.kind = Some(SyntaxKind::Dict);
1147 }
1148
1149 while !p.current().is_terminator() {
1150 if !p.at_set(set::ARRAY_OR_DICT_ITEM) {
1151 p.unexpected();
1152 continue;
1153 }
1154
1155 array_or_dict_item(p, &mut state);
1156 state.count += 1;
1157
1158 if !p.current().is_terminator() && p.expect(SyntaxKind::Comma) {
1159 state.maybe_just_parens = false;
1160 }
1161 }
1162
1163 p.expect_closing_delimiter(m, SyntaxKind::RightParen);
1164 });
1165
1166 let kind = if state.maybe_just_parens && state.count == 1 {
1167 SyntaxKind::Parenthesized
1168 } else {
1169 state.kind.unwrap_or(SyntaxKind::Array)
1170 };
1171
1172 p.wrap(m, kind);
1173 kind
1174}
1175
1176struct GroupState {
1178 count: usize,
1179 maybe_just_parens: bool,
1183 kind: Option<SyntaxKind>,
1185 seen: FxHashSet<EcoString>,
1187}
1188
1189fn array_or_dict_item(p: &mut Parser, state: &mut GroupState) {
1191 let m = p.marker();
1192
1193 if p.eat_if(SyntaxKind::Dots) {
1194 code_expr(p);
1196 p.wrap(m, SyntaxKind::Spread);
1197 state.maybe_just_parens = false;
1198 return;
1199 }
1200
1201 code_expr(p);
1202
1203 if p.eat_if(SyntaxKind::Colon) {
1204 code_expr(p);
1206
1207 let node = &mut p[m];
1208 let pair_kind = match node.kind() {
1209 SyntaxKind::Ident => SyntaxKind::Named,
1210 _ => SyntaxKind::Keyed,
1211 };
1212
1213 if let Some(key) = match node.cast::<ast::Expr>() {
1214 Some(ast::Expr::Ident(ident)) => Some(ident.get().clone()),
1215 Some(ast::Expr::Str(s)) => Some(s.get()),
1216 _ => None,
1217 } && !state.seen.insert(key.clone())
1218 {
1219 node.convert_to_error(eco_format!("duplicate key: {key}"));
1220 }
1221
1222 p.wrap(m, pair_kind);
1223 state.maybe_just_parens = false;
1224
1225 if state.kind == Some(SyntaxKind::Array) {
1226 p[m].expected("expression");
1227 } else {
1228 state.kind = Some(SyntaxKind::Dict);
1229 }
1230 } else {
1231 if state.kind == Some(SyntaxKind::Dict) {
1233 p[m].expected("named or keyed pair");
1234 } else {
1235 state.kind = Some(SyntaxKind::Array)
1236 }
1237 }
1238}
1239
1240fn args(p: &mut Parser) {
1242 if !p.directly_at(SyntaxKind::LeftParen) && !p.directly_at(SyntaxKind::LeftBracket) {
1243 p.expected("argument list");
1244 if p.at(SyntaxKind::LeftParen) || p.at(SyntaxKind::LeftBracket) {
1245 p.hint("there may not be any spaces before the argument list");
1246 }
1247 }
1248
1249 let m = p.marker();
1250 if p.at(SyntaxKind::LeftParen) {
1251 let m2 = p.marker();
1252 p.with_nl_mode(AtNewline::Continue, |p| {
1253 p.assert(SyntaxKind::LeftParen);
1254
1255 let mut seen = FxHashSet::default();
1256 while !p.current().is_terminator() {
1257 if !p.at_set(set::ARG) {
1258 p.unexpected();
1259 continue;
1260 }
1261
1262 arg(p, &mut seen);
1263
1264 if !p.current().is_terminator() {
1265 p.expect(SyntaxKind::Comma);
1266 }
1267 }
1268
1269 p.expect_closing_delimiter(m2, SyntaxKind::RightParen);
1270 });
1271 }
1272
1273 while p.directly_at(SyntaxKind::LeftBracket) {
1274 content_block(p);
1275 }
1276
1277 p.wrap(m, SyntaxKind::Args);
1278}
1279
1280fn arg<'s>(p: &mut Parser<'s>, seen: &mut FxHashSet<&'s str>) {
1282 let m = p.marker();
1283
1284 if p.eat_if(SyntaxKind::Dots) {
1286 code_expr(p);
1287 p.wrap(m, SyntaxKind::Spread);
1288 return;
1289 }
1290
1291 let was_at_expr = p.at_set(set::CODE_EXPR);
1293 let text = p.current_text();
1294 code_expr(p);
1295
1296 if p.eat_if(SyntaxKind::Colon) {
1298 if was_at_expr {
1300 if p[m].kind() != SyntaxKind::Ident {
1301 p[m].expected("identifier");
1302 } else if !seen.insert(text) {
1303 p[m].convert_to_error(eco_format!("duplicate argument: {text}"));
1304 }
1305 }
1306
1307 code_expr(p);
1308 p.wrap(m, SyntaxKind::Named);
1309 }
1310}
1311
1312fn params(p: &mut Parser) {
1314 let m = p.marker();
1315 p.with_nl_mode(AtNewline::Continue, |p| {
1316 p.assert(SyntaxKind::LeftParen);
1317
1318 let mut seen = FxHashSet::default();
1319 let mut sink = false;
1320
1321 while !p.current().is_terminator() {
1322 if !p.at_set(set::PARAM) {
1323 p.unexpected();
1324 continue;
1325 }
1326
1327 param(p, &mut seen, &mut sink);
1328
1329 if !p.current().is_terminator() {
1330 p.expect(SyntaxKind::Comma);
1331 }
1332 }
1333
1334 p.expect_closing_delimiter(m, SyntaxKind::RightParen);
1335 });
1336 p.wrap(m, SyntaxKind::Params);
1337}
1338
1339fn param<'s>(p: &mut Parser<'s>, seen: &mut FxHashSet<&'s str>, sink: &mut bool) {
1341 let m = p.marker();
1342
1343 if p.eat_if(SyntaxKind::Dots) {
1345 if p.at_set(set::PATTERN_LEAF) {
1346 pattern_leaf(p, false, seen, Some("parameter"));
1347 }
1348 p.wrap(m, SyntaxKind::Spread);
1349 if mem::replace(sink, true) {
1350 p[m].convert_to_error("only one argument sink is allowed");
1351 }
1352 return;
1353 }
1354
1355 let was_at_pat = p.at_set(set::PATTERN);
1357 pattern(p, false, seen, Some("parameter"));
1358
1359 if p.eat_if(SyntaxKind::Colon) {
1361 if was_at_pat && p[m].kind() != SyntaxKind::Ident {
1363 p[m].expected("identifier");
1364 }
1365
1366 code_expr(p);
1367 p.wrap(m, SyntaxKind::Named);
1368 }
1369}
1370
1371fn pattern<'s>(
1373 p: &mut Parser<'s>,
1374 reassignment: bool,
1375 seen: &mut FxHashSet<&'s str>,
1376 dupe: Option<&'s str>,
1377) {
1378 match p.current() {
1379 SyntaxKind::Underscore => p.eat(),
1380 SyntaxKind::LeftParen => destructuring_or_parenthesized(p, reassignment, seen),
1381 _ => pattern_leaf(p, reassignment, seen, dupe),
1382 }
1383}
1384
1385fn destructuring_or_parenthesized<'s>(
1387 p: &mut Parser<'s>,
1388 reassignment: bool,
1389 seen: &mut FxHashSet<&'s str>,
1390) {
1391 let mut sink = false;
1392 let mut count = 0;
1393 let mut maybe_just_parens = true;
1394
1395 let m = p.marker();
1396 p.with_nl_mode(AtNewline::Continue, |p| {
1397 p.assert(SyntaxKind::LeftParen);
1398
1399 while !p.current().is_terminator() {
1400 if !p.at_set(set::DESTRUCTURING_ITEM) {
1401 p.unexpected();
1402 continue;
1403 }
1404
1405 destructuring_item(p, reassignment, seen, &mut maybe_just_parens, &mut sink);
1406 count += 1;
1407
1408 if !p.current().is_terminator() && p.expect(SyntaxKind::Comma) {
1409 maybe_just_parens = false;
1410 }
1411 }
1412
1413 p.expect_closing_delimiter(m, SyntaxKind::RightParen);
1414 });
1415
1416 if maybe_just_parens && count == 1 && !sink {
1417 p.wrap(m, SyntaxKind::Parenthesized);
1418 } else {
1419 p.wrap(m, SyntaxKind::Destructuring);
1420 }
1421}
1422
1423fn destructuring_item<'s>(
1425 p: &mut Parser<'s>,
1426 reassignment: bool,
1427 seen: &mut FxHashSet<&'s str>,
1428 maybe_just_parens: &mut bool,
1429 sink: &mut bool,
1430) {
1431 let m = p.marker();
1432
1433 if p.eat_if(SyntaxKind::Dots) {
1435 if p.at_set(set::PATTERN_LEAF) {
1436 pattern_leaf(p, reassignment, seen, None);
1437 }
1438 p.wrap(m, SyntaxKind::Spread);
1439 if mem::replace(sink, true) {
1440 p[m].convert_to_error("only one destructuring sink is allowed");
1441 }
1442 return;
1443 }
1444
1445 let was_at_pat = p.at_set(set::PATTERN);
1447
1448 let checkpoint = p.checkpoint();
1451 if !(p.eat_if(SyntaxKind::Ident) && p.at(SyntaxKind::Colon)) {
1452 p.restore(checkpoint);
1453 pattern(p, reassignment, seen, None);
1454 }
1455
1456 if p.eat_if(SyntaxKind::Colon) {
1458 if was_at_pat && p[m].kind() != SyntaxKind::Ident {
1460 p[m].expected("identifier");
1461 }
1462
1463 pattern(p, reassignment, seen, None);
1464 p.wrap(m, SyntaxKind::Named);
1465 *maybe_just_parens = false;
1466 }
1467}
1468
1469fn pattern_leaf<'s>(
1472 p: &mut Parser<'s>,
1473 reassignment: bool,
1474 seen: &mut FxHashSet<&'s str>,
1475 dupe: Option<&'s str>,
1476) {
1477 if p.current().is_keyword() {
1478 p.eat_and_get().expected("pattern");
1479 return;
1480 } else if !p.at_set(set::PATTERN_LEAF) {
1481 p.expected("pattern");
1482 return;
1483 }
1484
1485 let m = p.marker();
1486 let text = p.current_text();
1487
1488 code_expr_prec(p, true, 0);
1492
1493 if !reassignment {
1494 let node = &mut p[m];
1495 if node.kind() == SyntaxKind::Ident {
1496 if !seen.insert(text) {
1497 node.convert_to_error(eco_format!(
1498 "duplicate {}: {text}",
1499 dupe.unwrap_or("binding"),
1500 ));
1501 }
1502 } else {
1503 node.expected("pattern");
1504 }
1505 }
1506}
1507
1508struct Parser<'s> {
1543 text: &'s str,
1545 lexer: Lexer<'s>,
1549 nl_mode: AtNewline,
1551 token: Token,
1556 balanced: bool,
1559 nodes: Vec<SyntaxNode>,
1562 memo: MemoArena,
1566}
1567
1568#[derive(Debug, Clone)]
1571struct Token {
1572 kind: SyntaxKind,
1574 node: SyntaxNode,
1577 n_trivia: usize,
1579 newline: Option<Newline>,
1581 start: usize,
1584 prev_end: usize,
1586}
1587
1588#[derive(Debug, Copy, Clone)]
1590struct Newline {
1591 column: Option<usize>,
1593 parbreak: bool,
1595}
1596
1597#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1599enum AtNewline {
1600 Continue,
1602 Stop,
1604 ContextualContinue,
1606 StopParBreak,
1608 RequireColumn(usize),
1612}
1613
1614impl AtNewline {
1615 fn stop_at(self, Newline { column, parbreak }: Newline, kind: SyntaxKind) -> bool {
1617 #[allow(clippy::match_like_matches_macro)]
1618 match self {
1619 AtNewline::Continue => false,
1620 AtNewline::Stop => true,
1621 AtNewline::ContextualContinue => match kind {
1622 SyntaxKind::Else | SyntaxKind::Dot => false,
1623 _ => true,
1624 },
1625 AtNewline::StopParBreak => parbreak,
1626 AtNewline::RequireColumn(min_col) => {
1627 column.is_some_and(|column| column <= min_col)
1632 }
1633 }
1634 }
1635}
1636
1637#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1641struct Marker(usize);
1642
1643impl Index<Marker> for Parser<'_> {
1645 type Output = SyntaxNode;
1646
1647 fn index(&self, m: Marker) -> &Self::Output {
1648 &self.nodes[m.0]
1649 }
1650}
1651
1652impl IndexMut<Marker> for Parser<'_> {
1653 fn index_mut(&mut self, m: Marker) -> &mut Self::Output {
1654 &mut self.nodes[m.0]
1655 }
1656}
1657
1658impl<'s> Parser<'s> {
1660 fn new(text: &'s str, offset: usize, mode: SyntaxMode) -> Self {
1662 let mut lexer = Lexer::new(text, mode);
1663 lexer.jump(offset);
1664 let nl_mode = AtNewline::Continue;
1665 let mut nodes = vec![];
1666 let token = Self::lex(&mut nodes, &mut lexer, nl_mode);
1667 Self {
1668 text,
1669 lexer,
1670 nl_mode,
1671 token,
1672 balanced: true,
1673 nodes,
1674 memo: Default::default(),
1675 }
1676 }
1677
1678 fn finish(self) -> Vec<SyntaxNode> {
1680 self.nodes
1681 }
1682
1683 fn finish_into(self, kind: SyntaxKind) -> SyntaxNode {
1685 assert!(self.at(SyntaxKind::End));
1686 SyntaxNode::inner(kind, self.finish())
1687 }
1688
1689 fn current(&self) -> SyntaxKind {
1692 self.token.kind
1693 }
1694
1695 fn at(&self, kind: SyntaxKind) -> bool {
1697 self.token.kind == kind
1698 }
1699
1700 fn at_set(&self, set: SyntaxSet) -> bool {
1702 set.contains(self.token.kind)
1703 }
1704
1705 fn end(&self) -> bool {
1709 self.at(SyntaxKind::End)
1710 }
1711
1712 fn directly_at(&self, kind: SyntaxKind) -> bool {
1714 self.token.kind == kind && !self.had_trivia()
1715 }
1716
1717 fn had_trivia(&self) -> bool {
1719 self.token.n_trivia > 0
1720 }
1721
1722 fn had_newline(&self) -> bool {
1724 self.token.newline.is_some()
1725 }
1726
1727 fn current_column(&self) -> usize {
1730 self.token
1731 .newline
1732 .and_then(|newline| newline.column)
1733 .unwrap_or_else(|| self.lexer.column(self.token.start))
1734 }
1735
1736 fn current_text(&self) -> &'s str {
1738 &self.text[self.token.start..self.current_end()]
1739 }
1740
1741 fn current_start(&self) -> usize {
1743 self.token.start
1744 }
1745
1746 fn current_end(&self) -> usize {
1748 self.lexer.cursor()
1749 }
1750
1751 fn prev_end(&self) -> usize {
1753 self.token.prev_end
1754 }
1755}
1756
1757impl<'s> Parser<'s> {
1759 fn marker(&self) -> Marker {
1762 Marker(self.nodes.len())
1763 }
1764
1765 fn before_trivia(&self) -> Marker {
1768 Marker(self.nodes.len() - self.token.n_trivia)
1769 }
1770
1771 #[track_caller]
1773 fn eat_and_get(&mut self) -> &mut SyntaxNode {
1774 let offset = self.nodes.len();
1775 self.eat();
1776 &mut self.nodes[offset]
1777 }
1778
1779 fn eat_if(&mut self, kind: SyntaxKind) -> bool {
1784 let at = self.at(kind);
1785 if at {
1786 self.eat();
1787 }
1788 at
1789 }
1790
1791 fn eat_if_direct(&mut self, kind: SyntaxKind) -> bool {
1794 let at = self.directly_at(kind);
1795 if at {
1796 self.eat();
1797 }
1798 at
1799 }
1800
1801 #[track_caller]
1805 fn assert(&mut self, kind: SyntaxKind) {
1806 assert_eq!(self.token.kind, kind);
1807 self.eat();
1808 }
1809
1810 fn convert_and_eat(&mut self, kind: SyntaxKind) {
1812 self.token.node.convert_to_kind(kind);
1814 self.eat();
1815 }
1816
1817 fn eat(&mut self) {
1820 self.nodes.push(std::mem::take(&mut self.token.node));
1821 self.token = Self::lex(&mut self.nodes, &mut self.lexer, self.nl_mode);
1822 }
1823
1824 fn flush_trivia(&mut self) {
1827 self.token.n_trivia = 0;
1828 self.token.prev_end = self.token.start;
1829 }
1830
1831 fn wrap(&mut self, from: Marker, kind: SyntaxKind) {
1836 let to = self.before_trivia().0;
1837 let from = from.0.min(to);
1838 let children = self.nodes.drain(from..to).collect();
1839 self.nodes.insert(from, SyntaxNode::inner(kind, children));
1840 }
1841
1842 fn enter_modes(
1847 &mut self,
1848 mode: SyntaxMode,
1849 stop: AtNewline,
1850 func: impl FnOnce(&mut Parser<'s>),
1851 ) {
1852 let previous = self.lexer.mode();
1853 self.lexer.set_mode(mode);
1854 self.with_nl_mode(stop, func);
1855 if mode != previous {
1856 self.lexer.set_mode(previous);
1857 self.lexer.jump(self.token.prev_end);
1858 self.nodes.truncate(self.nodes.len() - self.token.n_trivia);
1859 self.token = Self::lex(&mut self.nodes, &mut self.lexer, self.nl_mode);
1860 }
1861 }
1862
1863 fn with_nl_mode(&mut self, mode: AtNewline, func: impl FnOnce(&mut Parser<'s>)) {
1868 let previous = self.nl_mode;
1869 self.nl_mode = mode;
1870 func(self);
1871 self.nl_mode = previous;
1872 if let Some(newline) = self.token.newline
1873 && mode != previous
1874 {
1875 let actual_kind = self.token.node.kind();
1877 if self.nl_mode.stop_at(newline, actual_kind) {
1878 self.token.kind = SyntaxKind::End;
1879 } else {
1880 self.token.kind = actual_kind;
1881 }
1882 }
1883 }
1884
1885 fn lex(nodes: &mut Vec<SyntaxNode>, lexer: &mut Lexer, nl_mode: AtNewline) -> Token {
1891 let prev_end = lexer.cursor();
1892 let mut start = prev_end;
1893 let (mut kind, mut node) = lexer.next();
1894 let mut n_trivia = 0;
1895 let mut had_newline = false;
1896 let mut parbreak = false;
1897
1898 while kind.is_trivia() {
1899 had_newline |= lexer.newline(); parbreak |= kind == SyntaxKind::Parbreak;
1901 n_trivia += 1;
1902 nodes.push(node);
1903 start = lexer.cursor();
1904 (kind, node) = lexer.next();
1905 }
1906
1907 let newline = if had_newline {
1908 let column =
1909 (lexer.mode() == SyntaxMode::Markup).then(|| lexer.column(start));
1910 let newline = Newline { column, parbreak };
1911 if nl_mode.stop_at(newline, kind) {
1912 kind = SyntaxKind::End;
1915 }
1916 Some(newline)
1917 } else {
1918 None
1919 };
1920
1921 Token { kind, node, n_trivia, newline, start, prev_end }
1922 }
1923}
1924
1925#[derive(Default)]
1930struct MemoArena {
1931 arena: Vec<SyntaxNode>,
1934 memo_map: FxHashMap<MemoKey, (Range<usize>, PartialState)>,
1938}
1939
1940type MemoKey = usize;
1944
1945struct Checkpoint {
1947 node_len: usize,
1948 state: PartialState,
1949}
1950
1951#[derive(Clone)]
1954struct PartialState {
1955 cursor: usize,
1956 lex_mode: SyntaxMode,
1957 token: Token,
1958}
1959
1960impl Parser<'_> {
1962 fn memoize_parsed_nodes(&mut self, key: MemoKey, prev_len: usize) {
1965 let Checkpoint { state, node_len } = self.checkpoint();
1966 let memo_start = self.memo.arena.len();
1967 self.memo.arena.extend_from_slice(&self.nodes[prev_len..node_len]);
1968 let arena_range = memo_start..self.memo.arena.len();
1969 self.memo.memo_map.insert(key, (arena_range, state));
1970 }
1971
1972 fn restore_memo_or_checkpoint(&mut self) -> Option<(MemoKey, Checkpoint)> {
1975 let key: MemoKey = self.current_start();
1977 match self.memo.memo_map.get(&key).cloned() {
1978 Some((range, state)) => {
1979 self.nodes.extend_from_slice(&self.memo.arena[range]);
1980 self.restore_partial(state);
1984 None
1985 }
1986 None => Some((key, self.checkpoint())),
1987 }
1988 }
1989
1990 fn restore(&mut self, checkpoint: Checkpoint) {
1992 self.nodes.truncate(checkpoint.node_len);
1993 self.restore_partial(checkpoint.state);
1994 }
1995
1996 fn restore_partial(&mut self, state: PartialState) {
1998 self.lexer.jump(state.cursor);
1999 self.lexer.set_mode(state.lex_mode);
2000 self.token = state.token;
2001 }
2002
2003 fn checkpoint(&self) -> Checkpoint {
2005 let node_len = self.nodes.len();
2006 let state = PartialState {
2007 cursor: self.lexer.cursor(),
2008 lex_mode: self.lexer.mode(),
2009 token: self.token.clone(),
2010 };
2011 Checkpoint { node_len, state }
2012 }
2013}
2014
2015impl Parser<'_> {
2018 fn expect(&mut self, kind: SyntaxKind) -> bool {
2020 let at = self.at(kind);
2021 if at {
2022 self.eat();
2023 } else if kind == SyntaxKind::Ident && self.token.kind.is_keyword() {
2024 self.trim_errors();
2025 self.eat_and_get().expected(kind.name());
2026 } else {
2027 self.balanced &= !kind.is_grouping();
2028 self.expected(kind.name());
2029 }
2030 at
2031 }
2032
2033 #[track_caller]
2036 fn expect_closing_delimiter(&mut self, open: Marker, kind: SyntaxKind) {
2037 if !self.eat_if(kind) {
2038 self.nodes[open.0].convert_to_error("unclosed delimiter");
2039 }
2040 }
2041
2042 fn expected(&mut self, thing: &str) {
2044 if !self.after_error() {
2045 self.expected_at(self.before_trivia(), thing);
2046 }
2047 }
2048
2049 fn after_error(&mut self) -> bool {
2051 let m = self.before_trivia();
2052 m.0 > 0 && self.nodes[m.0 - 1].kind().is_error()
2053 }
2054
2055 fn expected_at(&mut self, m: Marker, thing: &str) {
2058 let error =
2059 SyntaxNode::error(SyntaxError::new(eco_format!("expected {thing}")), "");
2060 self.nodes.insert(m.0, error);
2061 }
2062
2063 fn hint(&mut self, hint: &str) {
2065 let m = self.before_trivia();
2066 if let Some(error) = self.nodes.get_mut(m.0 - 1) {
2067 error.hint(hint);
2068 }
2069 }
2070
2071 fn unexpected(&mut self) {
2074 self.trim_errors();
2075 self.balanced &= !self.token.kind.is_grouping();
2076 self.eat_and_get().unexpected();
2077 }
2078
2079 fn trim_errors(&mut self) {
2081 let Marker(end) = self.before_trivia();
2082 let mut start = end;
2083 while start > 0
2084 && self.nodes[start - 1].kind().is_error()
2085 && self.nodes[start - 1].is_empty()
2086 {
2087 start -= 1;
2088 }
2089 self.nodes.drain(start..end);
2090 }
2091}