1use std::mem;
2use std::ops::{DerefMut, Index, IndexMut, Range};
3
4use ecow::{EcoString, eco_format};
5use rustc_hash::{FxHashMap, FxHashSet};
6use typst_utils::{default_math_class, defer};
7use unicode_math_class::MathClass;
8
9use crate::set::{SyntaxSet, syntax_set};
10use crate::{Lexer, SyntaxKind, SyntaxMode, SyntaxNode, ast, set};
11
12const MAX_DEPTH: u32 = 256;
14
15pub fn parse(text: &str) -> SyntaxNode {
17 let _scope = typst_timing::TimingScope::new("parse");
18 let mut p = Parser::new(text, 0, SyntaxMode::Markup);
19 markup_exprs(&mut p, true, syntax_set!(End));
20 p.finish_into(SyntaxKind::Markup)
21}
22
23pub fn parse_code(text: &str) -> SyntaxNode {
25 let _scope = typst_timing::TimingScope::new("parse code");
26 let mut p = Parser::new(text, 0, SyntaxMode::Code);
27 code_exprs(&mut p, syntax_set!(End));
28 p.finish_into(SyntaxKind::Code)
29}
30
31pub fn parse_math(text: &str) -> SyntaxNode {
33 let _scope = typst_timing::TimingScope::new("parse math");
34 let mut p = Parser::new(text, 0, SyntaxMode::Math);
35 math_exprs(&mut p, syntax_set!(End));
36 p.finish_into(SyntaxKind::Math)
37}
38
39fn markup(p: &mut Parser, at_start: bool, wrap_trivia: bool, stop_set: SyntaxSet) {
41 let m = if wrap_trivia { p.before_trivia() } else { p.marker() };
42 markup_exprs(p, at_start, stop_set);
43 if wrap_trivia {
44 p.flush_trivia();
45 }
46 p.wrap(m, SyntaxKind::Markup);
47}
48
49fn markup_exprs(p: &mut Parser, mut at_start: bool, stop_set: SyntaxSet) {
51 debug_assert!(stop_set.contains(SyntaxKind::End));
52 let Some(p) = p.check_depth_until(stop_set) else { return };
53
54 at_start |= p.had_newline();
55 let mut nesting: usize = 0;
56 while !p.at_set(stop_set) || (nesting > 0 && p.at(SyntaxKind::RightBracket)) {
58 markup_expr(p, at_start, &mut nesting);
59 at_start = p.had_newline();
60 }
61}
62
63pub(super) fn reparse_markup(
65 text: &str,
66 range: Range<usize>,
67 at_start: &mut bool,
68 nesting: &mut usize,
69 top_level: bool,
70) -> Option<Vec<SyntaxNode>> {
71 let mut p = Parser::new(text, range.start, SyntaxMode::Markup);
72 *at_start |= p.had_newline();
73 while !p.end() && p.current_start() < range.end {
74 if !top_level && *nesting == 0 && p.at(SyntaxKind::RightBracket) {
76 break;
77 }
78 markup_expr(&mut p, *at_start, nesting);
79 *at_start = p.had_newline();
80 }
81 (p.balanced && p.current_start() == range.end).then(|| p.finish())
82}
83
84fn markup_expr(p: &mut Parser, at_start: bool, nesting: &mut usize) {
88 let Some(p) = &mut p.increase_depth() else { return };
89
90 match p.current() {
91 SyntaxKind::LeftBracket => {
92 *nesting += 1;
93 p.convert_and_eat(SyntaxKind::Text);
94 }
95 SyntaxKind::RightBracket if *nesting > 0 => {
96 *nesting -= 1;
97 p.convert_and_eat(SyntaxKind::Text);
98 }
99 SyntaxKind::RightBracket => {
100 p.unexpected();
101 p.hint("try using a backslash escape: \\]");
102 }
103
104 SyntaxKind::Shebang => p.eat(),
105
106 SyntaxKind::Text
107 | SyntaxKind::Linebreak
108 | SyntaxKind::Escape
109 | SyntaxKind::Shorthand
110 | SyntaxKind::SmartQuote
111 | SyntaxKind::Link
112 | SyntaxKind::Label => p.eat(),
113
114 SyntaxKind::Raw => p.eat(), SyntaxKind::Hash => embedded_code_expr(p),
117 SyntaxKind::Star => strong(p),
118 SyntaxKind::Underscore => emph(p),
119 SyntaxKind::HeadingMarker if at_start => heading(p),
120 SyntaxKind::ListMarker if at_start => list_item(p),
121 SyntaxKind::EnumMarker if at_start => enum_item(p),
122 SyntaxKind::TermMarker if at_start => term_item(p),
123 SyntaxKind::RefMarker => reference(p),
124 SyntaxKind::Dollar => equation(p),
125
126 SyntaxKind::HeadingMarker
127 | SyntaxKind::ListMarker
128 | SyntaxKind::EnumMarker
129 | SyntaxKind::TermMarker
130 | SyntaxKind::Colon => p.convert_and_eat(SyntaxKind::Text),
131
132 _ => p.unexpected(),
133 }
134}
135
136fn strong(p: &mut Parser) {
138 p.with_nl_mode(AtNewline::StopParBreak, |p| {
139 let m = p.marker();
140 p.assert(SyntaxKind::Star);
141 markup(p, false, true, syntax_set!(Star, RightBracket, End));
142 let had_closing = p.expect_closing_delimiter(m, SyntaxKind::Star);
143 p.wrap(m, SyntaxKind::Strong);
144 if had_closing && p[m].len() == 2 {
145 p[m].warn("no text within stars");
146 let hint = "using multiple consecutive stars (e.g. **) has no \
147 additional effect";
148 p[m].hint(hint);
149 }
150 });
151}
152
153fn emph(p: &mut Parser) {
155 p.with_nl_mode(AtNewline::StopParBreak, |p| {
156 let m = p.marker();
157 p.assert(SyntaxKind::Underscore);
158 markup(p, false, true, syntax_set!(Underscore, RightBracket, End));
159 let had_closing = p.expect_closing_delimiter(m, SyntaxKind::Underscore);
160 p.wrap(m, SyntaxKind::Emph);
161 if had_closing && p[m].len() == 2 {
162 p[m].warn("no text within underscores");
163 let hint = "using multiple consecutive underscores (e.g. __) has no \
164 additional effect";
165 p[m].hint(hint);
166 }
167 });
168}
169
170fn heading(p: &mut Parser) {
172 p.with_nl_mode(AtNewline::Stop, |p| {
173 let m = p.marker();
174 p.assert(SyntaxKind::HeadingMarker);
175 markup(p, false, false, syntax_set!(Label, RightBracket, End));
176 p.wrap(m, SyntaxKind::Heading);
177 });
178}
179
180fn list_item(p: &mut Parser) {
182 p.with_nl_mode(AtNewline::RequireColumn(p.current_column()), |p| {
183 let m = p.marker();
184 p.assert(SyntaxKind::ListMarker);
185 markup(p, true, false, syntax_set!(RightBracket, End));
186 p.wrap(m, SyntaxKind::ListItem);
187 });
188}
189
190fn enum_item(p: &mut Parser) {
192 p.with_nl_mode(AtNewline::RequireColumn(p.current_column()), |p| {
193 let m = p.marker();
194 p.assert(SyntaxKind::EnumMarker);
195 markup(p, true, false, syntax_set!(RightBracket, End));
196 p.wrap(m, SyntaxKind::EnumItem);
197 });
198}
199
200fn term_item(p: &mut Parser) {
202 p.with_nl_mode(AtNewline::RequireColumn(p.current_column()), |p| {
203 let m = p.marker();
204 p.with_nl_mode(AtNewline::Stop, |p| {
205 p.assert(SyntaxKind::TermMarker);
206 markup(p, false, false, syntax_set!(Colon, RightBracket, End));
207 });
208 p.expect(SyntaxKind::Colon);
209 markup(p, true, false, syntax_set!(RightBracket, End));
210 p.wrap(m, SyntaxKind::TermItem);
211 });
212}
213
214fn reference(p: &mut Parser) {
216 let m = p.marker();
217 p.assert(SyntaxKind::RefMarker);
218 if p.directly_at(SyntaxKind::LeftBracket) {
219 content_block(p);
220 }
221 p.wrap(m, SyntaxKind::Ref);
222}
223
224fn equation(p: &mut Parser) {
226 let m = p.marker();
227 p.enter_modes(SyntaxMode::Math, AtNewline::Continue, |p| {
228 p.assert(SyntaxKind::Dollar);
229 math(p, syntax_set!(Dollar, End));
230 p.expect_closing_delimiter(m, SyntaxKind::Dollar);
231 });
232 p.wrap(m, SyntaxKind::Equation);
233}
234
235fn math(p: &mut Parser, stop_set: SyntaxSet) {
237 let m = p.marker();
238 math_exprs(p, stop_set);
239 p.wrap(m, SyntaxKind::Math);
240}
241
242fn math_exprs(p: &mut Parser, stop_set: SyntaxSet) -> usize {
245 debug_assert!(stop_set.contains(SyntaxKind::End));
246 let Some(p) = p.check_depth_until(stop_set) else { return 1 };
247
248 let mut count = 0;
249 while !p.at_set(stop_set) {
250 if p.at_set(set::MATH_EXPR) {
251 math_expr(p);
252 } else {
253 p.unexpected();
254 }
255 count += 1;
256 }
257 count
258}
259
260fn math_expr(p: &mut Parser) {
263 math_expr_prec(p, 0, syntax_set!())
264}
265
266fn math_expr_prec(p: &mut Parser, min_prec: u8, stop_set: SyntaxSet) {
269 let Some(p) = &mut p.increase_depth() else { return };
270
271 let m = p.marker();
272 let mut continuable = false;
273 match p.current() {
274 SyntaxKind::Hash => embedded_code_expr(p),
275
276 SyntaxKind::MathIdent | SyntaxKind::MathFieldAccess => {
278 continuable = true;
279 p.eat();
280 if MATH_FUNC_PREC >= min_prec && p.directly_at(SyntaxKind::LeftParen) {
282 math_args(p);
283 p.wrap(m, SyntaxKind::MathCall);
284 continuable = false;
285 }
286 }
287
288 SyntaxKind::LeftBrace | SyntaxKind::LeftParen => {
289 math_delimited(p);
290 }
291 SyntaxKind::RightBrace if p.current_text() == "|]" => {
292 p.convert_and_eat(SyntaxKind::MathShorthand);
293 }
294 SyntaxKind::Dot
295 | SyntaxKind::Bang
296 | SyntaxKind::Comma
297 | SyntaxKind::Semicolon
298 | SyntaxKind::RightBrace
299 | SyntaxKind::RightParen => {
300 p.convert_and_eat(SyntaxKind::MathText);
301 }
302
303 SyntaxKind::MathText => {
304 continuable = is_math_alphabetic(p.current_text());
305 p.eat();
306 }
307
308 SyntaxKind::Linebreak
309 | SyntaxKind::MathAlignPoint
310 | SyntaxKind::MathShorthand => p.eat(),
311
312 SyntaxKind::MathPrimes | SyntaxKind::Escape | SyntaxKind::Str => {
313 continuable = true;
314 p.eat();
315 }
316
317 SyntaxKind::Root => {
318 p.eat();
319 let m2 = p.marker();
320 math_expr_prec(p, MATH_ROOT_PREC, syntax_set!());
321 math_unparen(p, m2);
322 p.wrap(m, SyntaxKind::MathRoot);
323 }
324
325 _ => p.expected("expression"),
326 }
327
328 if continuable
332 && MATH_FUNC_PREC >= min_prec
333 && !p.had_trivia()
334 && p.at_set(syntax_set!(LeftBrace, LeftParen))
335 {
336 math_delimited(p);
337 p.wrap(m, SyntaxKind::Math);
338 }
339
340 while !p.at_set(stop_set)
343 && let op_kind = p.current()
344 && let had_trivia = p.had_trivia()
345 && let Some((wrapper, infix_assoc, prec)) = math_op(op_kind, had_trivia)
346 && prec >= min_prec
347 {
348 let mut chain_set = if wrapper == SyntaxKind::MathAttach {
350 syntax_set!(Hat, Underscore).remove(op_kind)
354 } else {
355 syntax_set!()
356 };
357
358 if op_kind == SyntaxKind::Bang {
360 p.convert_and_eat(SyntaxKind::MathText);
361 } else {
362 p.eat();
363 }
364
365 if wrapper == SyntaxKind::MathFrac {
367 math_unparen(p, m);
368 }
369
370 if let Some(assoc) = infix_assoc {
372 let prec = match assoc {
373 ast::Assoc::Left => prec + 1,
374 ast::Assoc::Right => prec,
375 };
376 let m_rhs = p.marker();
377 math_expr_prec(p, prec, chain_set);
378 math_unparen(p, m_rhs);
379 }
380
381 if !(op_kind == SyntaxKind::MathPrimes && p.at_set(stop_set)) {
384 while p.at_set(chain_set) {
386 chain_set = chain_set.remove(p.current());
387 p.eat();
388 let m_chain_rhs = p.marker();
389 math_expr_prec(p, prec, chain_set);
390 math_unparen(p, m_chain_rhs);
391 }
392 }
393
394 p.wrap(m, wrapper);
396 }
397}
398
399const MATH_FUNC_PREC: u8 = 2;
401const MATH_ROOT_PREC: u8 = 2;
402
403fn math_op(
405 kind: SyntaxKind,
406 had_trivia: bool,
407) -> Option<(SyntaxKind, Option<ast::Assoc>, u8)> {
408 let op = match kind {
409 SyntaxKind::Slash => (SyntaxKind::MathFrac, Some(ast::Assoc::Left), 1),
410 SyntaxKind::Underscore => (SyntaxKind::MathAttach, Some(ast::Assoc::Right), 2),
411 SyntaxKind::Hat => (SyntaxKind::MathAttach, Some(ast::Assoc::Right), 2),
412 SyntaxKind::MathPrimes if !had_trivia => (SyntaxKind::MathAttach, None, 2),
413 SyntaxKind::Bang if !had_trivia => (SyntaxKind::Math, None, 3),
414 _ => return None,
415 };
416 Some(op)
417}
418
419fn is_math_alphabetic(text: &str) -> bool {
422 if let Some((0, c)) = text.char_indices().next_back() {
423 c.is_alphabetic() || default_math_class(c) == Some(MathClass::Alphabetic)
425 } else {
426 text.chars().all(char::is_alphabetic)
428 }
429}
430
431fn math_delimited(p: &mut Parser) {
436 let m = p.marker();
437 if p.current_text() == "[|" {
438 p.convert_and_eat(SyntaxKind::MathShorthand);
439 } else {
440 p.convert_and_eat(SyntaxKind::MathText);
441 }
442 let m_body = p.marker();
443 math_exprs(p, syntax_set!(Dollar, End, RightBrace, RightParen));
444 if p.at_set(syntax_set!(RightBrace, RightParen)) {
445 p.wrap(m_body, SyntaxKind::Math);
446 if p.current_text() == "|]" {
447 p.convert_and_eat(SyntaxKind::MathShorthand);
448 } else {
449 p.convert_and_eat(SyntaxKind::MathText);
450 }
451 p.wrap(m, SyntaxKind::MathDelimited);
452 } else {
453 p.wrap(m, SyntaxKind::Math);
455 }
456}
457
458fn math_unparen(p: &mut Parser, m: Marker) {
461 let Some(node) = p.nodes.get_mut(m.0) else { return };
462 if node.kind() != SyntaxKind::MathDelimited {
463 return;
464 }
465
466 if let [first, .., last] = node.children_mut()
467 && first.leaf_text() == "("
468 && last.leaf_text() == ")"
469 {
470 first.convert_to_kind(SyntaxKind::LeftParen);
471 last.convert_to_kind(SyntaxKind::RightParen);
472 node.convert_to_kind(SyntaxKind::Math);
474 }
475}
476
477fn math_args(p: &mut Parser) {
479 let m = p.marker();
480 p.assert(SyntaxKind::LeftParen);
481
482 let mut seen = FxHashSet::default();
483 while !p.at_set(syntax_set!(End, Dollar, RightParen)) {
484 math_arg(p, &mut seen);
485 match p.current() {
486 SyntaxKind::End | SyntaxKind::Dollar | SyntaxKind::RightParen => {}
487 SyntaxKind::Semicolon | SyntaxKind::Comma => p.eat(),
488 _ => p.expected("comma or semicolon"),
489 }
490 }
491
492 p.expect_closing_delimiter(m, SyntaxKind::RightParen);
493 p.wrap(m, SyntaxKind::MathArgs);
494}
495
496fn math_arg<'s>(p: &mut Parser<'s>, seen: &mut FxHashSet<&'s str>) {
498 let m = p.marker();
499 let start = p.current_start();
500
501 let mut arg_kind = None;
502
503 if let Some(spread) = p.lexer.maybe_math_spread_arg(start) {
504 arg_kind = Some(SyntaxKind::Spread);
506 p.token.node = spread;
507 p.eat();
508 } else if let Some(named) = p.lexer.maybe_math_named_arg(start) {
509 arg_kind = Some(SyntaxKind::Named);
511 p.token.node = named;
512 let text = p.current_text();
513 p.eat();
514 p.convert_and_eat(SyntaxKind::Colon);
515 if !seen.insert(text) {
516 p[m].convert_to_error(eco_format!("duplicate argument: {text}"));
517 }
518 }
519
520 let m_arg = p.marker();
522 let count = math_exprs(p, syntax_set!(End, Dollar, Comma, Semicolon, RightParen));
523
524 if count == 0 {
525 assert_ne!(arg_kind, Some(SyntaxKind::Spread));
527
528 if arg_kind == Some(SyntaxKind::Named) {
530 p.expected("expression");
531 }
532 }
533
534 if count != 1 {
540 p.wrap(m_arg, SyntaxKind::Math);
541 }
542
543 if let Some(kind) = arg_kind {
544 p.wrap(m, kind);
545 }
546}
547
548fn code(p: &mut Parser, stop_set: SyntaxSet) {
550 let m = p.marker();
551 code_exprs(p, stop_set);
552 p.wrap(m, SyntaxKind::Code);
553}
554
555fn code_exprs(p: &mut Parser, stop_set: SyntaxSet) {
557 debug_assert!(stop_set.contains(SyntaxKind::End));
558 let Some(p) = p.check_depth_until(stop_set) else { return };
559
560 while !p.at_set(stop_set) {
561 p.with_nl_mode(AtNewline::ContextualContinue, |p| {
562 if !p.at_set(set::CODE_EXPR) {
563 p.unexpected();
564 return;
565 }
566 code_expr(p);
567 if !p.at_set(stop_set) && !p.eat_if(SyntaxKind::Semicolon) {
568 p.expected("semicolon or line break");
569 if p.at(SyntaxKind::Label) {
570 p.hint("labels can only be applied in markup mode");
571 p.hint("try wrapping your code in a markup block (`[ ]`)");
572 }
573 }
574 });
575 }
576}
577
578fn embedded_code_expr(p: &mut Parser) {
580 p.enter_modes(SyntaxMode::Code, AtNewline::Stop, |p| {
581 p.assert(SyntaxKind::Hash);
582 if p.had_trivia() || p.end() {
583 p.expected("expression");
584 return;
585 }
586
587 let stmt = p.at_set(set::STMT);
588 code_expr_prec(p, true, 0);
589
590 let semi = (stmt || p.directly_at(SyntaxKind::Semicolon))
592 && p.eat_if(SyntaxKind::Semicolon);
593
594 if stmt && !semi && !p.end() && !p.at(SyntaxKind::RightBracket) {
595 p.expected("semicolon or line break");
596 }
597 });
598}
599
600fn code_expr(p: &mut Parser) {
602 code_expr_prec(p, false, 0);
603}
604
605fn code_expr_prec(p: &mut Parser, atomic: bool, min_prec: u8) {
607 let Some(p) = &mut p.increase_depth() else { return };
608
609 let m = p.marker();
610 if p.at_set(set::UNARY_OP) {
611 if !atomic {
612 let op = ast::UnOp::from_kind(p.current()).unwrap();
613 p.eat();
614 code_expr_prec(p, atomic, op.precedence());
615 p.wrap(m, SyntaxKind::Unary);
616 } else {
617 p.unexpected();
618 p.hint(
619 "to use a unary operator here, wrap the entire expression in parentheses",
620 );
621 }
622 } else {
623 code_primary(p, atomic);
624 }
625
626 loop {
627 if p.directly_at(SyntaxKind::LeftParen) || p.directly_at(SyntaxKind::LeftBracket)
628 {
629 args(p);
630 p.wrap(m, SyntaxKind::FuncCall);
631 continue;
632 }
633
634 let at_field_or_method = p.directly_at(SyntaxKind::Dot)
635 && p.lexer.clone().next().0 == SyntaxKind::Ident;
636
637 if atomic && !at_field_or_method {
638 break;
639 }
640
641 if p.eat_if(SyntaxKind::Dot) {
642 p.expect(SyntaxKind::Ident);
643 p.wrap(m, SyntaxKind::FieldAccess);
644 continue;
645 }
646
647 let binop = if p.at_set(set::BINARY_OP) {
648 ast::BinOp::from_kind(p.current())
649 } else if min_prec <= ast::BinOp::NotIn.precedence() && p.eat_if(SyntaxKind::Not)
650 {
651 if p.at(SyntaxKind::In) {
652 Some(ast::BinOp::NotIn)
653 } else {
654 p.expected("keyword `in`");
655 break;
656 }
657 } else {
658 None
659 };
660
661 if let Some(op) = binop {
662 let mut prec = op.precedence();
663 if prec < min_prec {
664 break;
665 }
666
667 match op.assoc() {
668 ast::Assoc::Left => prec += 1,
669 ast::Assoc::Right => {}
670 }
671
672 p.eat();
673 code_expr_prec(p, false, prec);
674 p.wrap(m, SyntaxKind::Binary);
675 continue;
676 }
677
678 break;
679 }
680}
681
682fn code_primary(p: &mut Parser, atomic: bool) {
686 let m = p.marker();
687 match p.current() {
688 SyntaxKind::Ident => {
689 p.eat();
690 if !atomic && p.at(SyntaxKind::Arrow) {
691 p.wrap(m, SyntaxKind::Params);
692 p.assert(SyntaxKind::Arrow);
693 code_expr(p);
694 p.wrap(m, SyntaxKind::Closure);
695 }
696 }
697 SyntaxKind::Underscore if !atomic => {
698 p.eat();
699 if p.at(SyntaxKind::Arrow) {
700 p.wrap(m, SyntaxKind::Params);
701 p.eat();
702 code_expr(p);
703 p.wrap(m, SyntaxKind::Closure);
704 } else if p.eat_if(SyntaxKind::Eq) {
705 code_expr(p);
706 p.wrap(m, SyntaxKind::DestructAssignment);
707 } else {
708 p[m].expected("expression");
709 }
710 }
711
712 SyntaxKind::LeftBrace => code_block(p),
713 SyntaxKind::LeftBracket => content_block(p),
714 SyntaxKind::LeftParen => expr_with_paren(p, atomic),
715 SyntaxKind::Dollar => equation(p),
716 SyntaxKind::Let => let_binding(p),
717 SyntaxKind::Set => set_rule(p),
718 SyntaxKind::Show => show_rule(p),
719 SyntaxKind::Context => contextual(p, atomic),
720 SyntaxKind::If => conditional(p),
721 SyntaxKind::While => while_loop(p),
722 SyntaxKind::For => for_loop(p),
723 SyntaxKind::Import => module_import(p),
724 SyntaxKind::Include => module_include(p),
725 SyntaxKind::Break => break_stmt(p),
726 SyntaxKind::Continue => continue_stmt(p),
727 SyntaxKind::Return => return_stmt(p),
728
729 SyntaxKind::Raw => p.eat(), SyntaxKind::None
732 | SyntaxKind::Auto
733 | SyntaxKind::Int
734 | SyntaxKind::Float
735 | SyntaxKind::Bool
736 | SyntaxKind::Numeric
737 | SyntaxKind::Str
738 | SyntaxKind::Label => p.eat(),
739
740 _ if atomic => p.unexpected(),
742
743 _ => p.expected("expression"),
744 }
745}
746
747pub(super) fn reparse_block(text: &str, range: Range<usize>) -> Option<SyntaxNode> {
750 let mut p = Parser::new(text, range.start, SyntaxMode::Code);
751 assert!(p.at(SyntaxKind::LeftBracket) || p.at(SyntaxKind::LeftBrace));
752 block(&mut p);
753 (p.balanced && p.prev_end() == range.end)
754 .then(|| p.finish().into_iter().next().unwrap())
755}
756
757fn block(p: &mut Parser) {
759 match p.current() {
760 SyntaxKind::LeftBracket => content_block(p),
761 SyntaxKind::LeftBrace => code_block(p),
762 _ => p.expected("block"),
763 }
764}
765
766fn code_block(p: &mut Parser) {
768 let m = p.marker();
769 p.enter_modes(SyntaxMode::Code, AtNewline::Continue, |p| {
770 p.assert(SyntaxKind::LeftBrace);
771 code(p, syntax_set!(RightBrace, RightBracket, RightParen, End));
772 p.expect_closing_delimiter(m, SyntaxKind::RightBrace);
773 });
774 p.wrap(m, SyntaxKind::CodeBlock);
775}
776
777fn content_block(p: &mut Parser) {
779 let m = p.marker();
780 p.enter_modes(SyntaxMode::Markup, AtNewline::Continue, |p| {
781 p.assert(SyntaxKind::LeftBracket);
782 markup(p, true, true, syntax_set!(RightBracket, End));
783 p.expect_closing_delimiter(m, SyntaxKind::RightBracket);
784 });
785 p.wrap(m, SyntaxKind::ContentBlock);
786}
787
788fn let_binding(p: &mut Parser) {
790 let m = p.marker();
791 p.assert(SyntaxKind::Let);
792
793 let m2 = p.marker();
794 let mut closure = false;
795 let mut other = false;
796
797 if p.eat_if(SyntaxKind::Ident) {
798 if p.directly_at(SyntaxKind::LeftParen) {
799 params(p);
800 closure = true;
801 }
802 } else {
803 pattern(p, false, &mut FxHashSet::default(), None);
804 other = true;
805 }
806
807 let f = if closure || other { Parser::expect } else { Parser::eat_if };
808 if f(p, SyntaxKind::Eq) {
809 code_expr(p);
810 }
811
812 if closure {
813 p.wrap(m2, SyntaxKind::Closure);
814 }
815
816 p.wrap(m, SyntaxKind::LetBinding);
817}
818
819fn set_rule(p: &mut Parser) {
821 let m = p.marker();
822 p.assert(SyntaxKind::Set);
823
824 let m2 = p.marker();
825 p.expect(SyntaxKind::Ident);
826 while p.eat_if(SyntaxKind::Dot) {
827 p.expect(SyntaxKind::Ident);
828 p.wrap(m2, SyntaxKind::FieldAccess);
829 }
830
831 args(p);
832 if p.eat_if(SyntaxKind::If) {
833 code_expr(p);
834 }
835 p.wrap(m, SyntaxKind::SetRule);
836}
837
838fn show_rule(p: &mut Parser) {
840 let m = p.marker();
841 p.assert(SyntaxKind::Show);
842 let m2 = p.before_trivia();
843
844 if !p.at(SyntaxKind::Colon) {
845 code_expr(p);
846 }
847
848 if p.eat_if(SyntaxKind::Colon) {
849 code_expr(p);
850 } else {
851 p.expected_at(m2, "colon");
852 }
853
854 p.wrap(m, SyntaxKind::ShowRule);
855}
856
857fn contextual(p: &mut Parser, atomic: bool) {
859 let m = p.marker();
860 p.assert(SyntaxKind::Context);
861 code_expr_prec(p, atomic, 0);
862 p.wrap(m, SyntaxKind::Contextual);
863}
864
865fn conditional(p: &mut Parser) {
867 let m = p.marker();
868 p.assert(SyntaxKind::If);
869 code_expr(p);
870 block(p);
871 if p.eat_if(SyntaxKind::Else) {
872 if p.at(SyntaxKind::If) {
873 conditional(p);
874 } else {
875 block(p);
876 }
877 }
878 p.wrap(m, SyntaxKind::Conditional);
879}
880
881fn while_loop(p: &mut Parser) {
883 let m = p.marker();
884 p.assert(SyntaxKind::While);
885 code_expr(p);
886 block(p);
887 p.wrap(m, SyntaxKind::WhileLoop);
888}
889
890fn for_loop(p: &mut Parser) {
892 let m = p.marker();
893 p.assert(SyntaxKind::For);
894
895 let mut seen = FxHashSet::default();
896 pattern(p, false, &mut seen, None);
897
898 if p.at(SyntaxKind::Comma) {
899 let node = p.eat_and_get();
900 node.unexpected();
901 node.hint("destructuring patterns must be wrapped in parentheses");
902 if p.at_set(set::PATTERN) {
903 pattern(p, false, &mut seen, None);
904 }
905 }
906
907 p.expect(SyntaxKind::In);
908 code_expr(p);
909 block(p);
910 p.wrap(m, SyntaxKind::ForLoop);
911}
912
913fn module_import(p: &mut Parser) {
915 let m = p.marker();
916 p.assert(SyntaxKind::Import);
917 code_expr(p);
918 if p.eat_if(SyntaxKind::As) {
919 p.expect(SyntaxKind::Ident);
923 }
924
925 if p.eat_if(SyntaxKind::Colon) {
926 if p.at(SyntaxKind::LeftParen) {
927 p.with_nl_mode(AtNewline::Continue, |p| {
928 let m2 = p.marker();
929 p.assert(SyntaxKind::LeftParen);
930
931 import_items(p);
932
933 p.expect_closing_delimiter(m2, SyntaxKind::RightParen);
934 });
935 } else if !p.eat_if(SyntaxKind::Star) {
936 import_items(p);
937 }
938 }
939
940 p.wrap(m, SyntaxKind::ModuleImport);
941}
942
943fn import_items(p: &mut Parser) {
945 let m = p.marker();
946 while !p.current().is_terminator() {
947 let item_marker = p.marker();
948 if !p.eat_if(SyntaxKind::Ident) {
949 p.unexpected();
950 }
951
952 while p.eat_if(SyntaxKind::Dot) {
954 p.expect(SyntaxKind::Ident);
955 }
956
957 p.wrap(item_marker, SyntaxKind::ImportItemPath);
958
959 if p.eat_if(SyntaxKind::As) {
961 p.expect(SyntaxKind::Ident);
962 p.wrap(item_marker, SyntaxKind::RenamedImportItem);
963 }
964
965 if !p.current().is_terminator() {
966 p.expect(SyntaxKind::Comma);
967 }
968 }
969
970 p.wrap(m, SyntaxKind::ImportItems);
971}
972
973fn module_include(p: &mut Parser) {
975 let m = p.marker();
976 p.assert(SyntaxKind::Include);
977 code_expr(p);
978 p.wrap(m, SyntaxKind::ModuleInclude);
979}
980
981fn break_stmt(p: &mut Parser) {
983 let m = p.marker();
984 p.assert(SyntaxKind::Break);
985 p.wrap(m, SyntaxKind::LoopBreak);
986}
987
988fn continue_stmt(p: &mut Parser) {
990 let m = p.marker();
991 p.assert(SyntaxKind::Continue);
992 p.wrap(m, SyntaxKind::LoopContinue);
993}
994
995fn return_stmt(p: &mut Parser) {
997 let m = p.marker();
998 p.assert(SyntaxKind::Return);
999 if p.at_set(set::CODE_EXPR) {
1000 code_expr(p);
1001 }
1002 p.wrap(m, SyntaxKind::FuncReturn);
1003}
1004
1005fn expr_with_paren(p: &mut Parser, atomic: bool) {
1007 if atomic {
1008 parenthesized_or_array_or_dict(p);
1011 return;
1012 }
1013
1014 let Some((memo_key, checkpoint)) = p.restore_memo_or_checkpoint() else { return };
1018 let prev_len = checkpoint.node_len;
1020
1021 let kind = parenthesized_or_array_or_dict(p);
1026
1027 if p.at(SyntaxKind::Arrow) {
1045 p.restore(checkpoint);
1046 let m = p.marker();
1047 params(p);
1048 if !p.expect(SyntaxKind::Arrow) {
1049 return;
1050 }
1051 code_expr(p);
1052 p.wrap(m, SyntaxKind::Closure);
1053 } else if p.at(SyntaxKind::Eq) && kind != SyntaxKind::Parenthesized {
1054 p.restore(checkpoint);
1055 let m = p.marker();
1056 destructuring_or_parenthesized(p, true, &mut FxHashSet::default());
1057 if !p.expect(SyntaxKind::Eq) {
1058 return;
1059 }
1060 code_expr(p);
1061 p.wrap(m, SyntaxKind::DestructAssignment);
1062 } else {
1063 return;
1064 }
1065
1066 p.memoize_parsed_nodes(memo_key, prev_len);
1068}
1069
1070fn parenthesized_or_array_or_dict(p: &mut Parser) -> SyntaxKind {
1075 let mut state = GroupState {
1076 count: 0,
1077 maybe_just_parens: true,
1078 kind: None,
1079 seen: FxHashSet::default(),
1080 };
1081
1082 let m = p.marker();
1098 p.with_nl_mode(AtNewline::Continue, |p| {
1099 p.assert(SyntaxKind::LeftParen);
1100 if p.eat_if(SyntaxKind::Colon) {
1101 state.kind = Some(SyntaxKind::Dict);
1102 }
1103
1104 while !p.current().is_terminator() {
1105 if !p.at_set(set::ARRAY_OR_DICT_ITEM) {
1106 p.unexpected();
1107 continue;
1108 }
1109
1110 array_or_dict_item(p, &mut state);
1111 state.count += 1;
1112
1113 if !p.current().is_terminator() && p.expect(SyntaxKind::Comma) {
1114 state.maybe_just_parens = false;
1115 }
1116 }
1117
1118 p.expect_closing_delimiter(m, SyntaxKind::RightParen);
1119 });
1120
1121 let kind = if state.maybe_just_parens && state.count == 1 {
1122 SyntaxKind::Parenthesized
1123 } else {
1124 state.kind.unwrap_or(SyntaxKind::Array)
1125 };
1126
1127 p.wrap(m, kind);
1128 kind
1129}
1130
1131struct GroupState {
1133 count: usize,
1134 maybe_just_parens: bool,
1138 kind: Option<SyntaxKind>,
1140 seen: FxHashSet<EcoString>,
1142}
1143
1144fn array_or_dict_item(p: &mut Parser, state: &mut GroupState) {
1146 let m = p.marker();
1147
1148 if p.eat_if(SyntaxKind::Dots) {
1149 code_expr(p);
1151 p.wrap(m, SyntaxKind::Spread);
1152 state.maybe_just_parens = false;
1153 return;
1154 }
1155
1156 code_expr(p);
1157
1158 if p.eat_if(SyntaxKind::Colon) {
1159 code_expr(p);
1161
1162 let node = &mut p[m];
1163 let pair_kind = match node.kind() {
1164 SyntaxKind::Ident => SyntaxKind::Named,
1165 _ => SyntaxKind::Keyed,
1166 };
1167
1168 if let Some(key) = match node.cast::<ast::Expr>() {
1169 Some(ast::Expr::Ident(ident)) => Some(ident.get().clone()),
1170 Some(ast::Expr::Str(s)) => Some(s.get()),
1171 _ => None,
1172 } && !state.seen.insert(key.clone())
1173 {
1174 node.convert_to_error(eco_format!("duplicate key: {key}"));
1175 }
1176
1177 p.wrap(m, pair_kind);
1178 state.maybe_just_parens = false;
1179
1180 if state.kind == Some(SyntaxKind::Array) {
1181 p[m].expected("expression");
1182 } else {
1183 state.kind = Some(SyntaxKind::Dict);
1184 }
1185 } else {
1186 if state.kind == Some(SyntaxKind::Dict) {
1188 p[m].expected("named or keyed pair");
1189 } else {
1190 state.kind = Some(SyntaxKind::Array)
1191 }
1192 }
1193}
1194
1195fn args(p: &mut Parser) {
1197 if !p.directly_at(SyntaxKind::LeftParen) && !p.directly_at(SyntaxKind::LeftBracket) {
1198 p.expected("argument list");
1199 if p.at(SyntaxKind::LeftParen) || p.at(SyntaxKind::LeftBracket) {
1200 p.hint("there may not be any spaces before the argument list");
1201 }
1202 }
1203
1204 let m = p.marker();
1205 if p.at(SyntaxKind::LeftParen) {
1206 let m2 = p.marker();
1207 p.with_nl_mode(AtNewline::Continue, |p| {
1208 p.assert(SyntaxKind::LeftParen);
1209
1210 let mut seen = FxHashSet::default();
1211 while !p.current().is_terminator() {
1212 if !p.at_set(set::ARG) {
1213 p.unexpected();
1214 continue;
1215 }
1216
1217 arg(p, &mut seen);
1218
1219 if !p.current().is_terminator() {
1220 p.expect(SyntaxKind::Comma);
1221 }
1222 }
1223
1224 p.expect_closing_delimiter(m2, SyntaxKind::RightParen);
1225 });
1226 }
1227
1228 while p.directly_at(SyntaxKind::LeftBracket) {
1229 content_block(p);
1230 }
1231
1232 p.wrap(m, SyntaxKind::Args);
1233}
1234
1235fn arg<'s>(p: &mut Parser<'s>, seen: &mut FxHashSet<&'s str>) {
1237 let m = p.marker();
1238
1239 if p.eat_if(SyntaxKind::Dots) {
1241 code_expr(p);
1242 p.wrap(m, SyntaxKind::Spread);
1243 return;
1244 }
1245
1246 let was_at_expr = p.at_set(set::CODE_EXPR);
1248 let text = p.current_text();
1249 code_expr(p);
1250
1251 if p.eat_if(SyntaxKind::Colon) {
1253 if was_at_expr {
1255 if p[m].kind() != SyntaxKind::Ident {
1256 p[m].expected("identifier");
1257 } else if !seen.insert(text) {
1258 p[m].convert_to_error(eco_format!("duplicate argument: {text}"));
1259 }
1260 }
1261
1262 code_expr(p);
1263 p.wrap(m, SyntaxKind::Named);
1264 }
1265}
1266
1267fn params(p: &mut Parser) {
1269 let m = p.marker();
1270 p.with_nl_mode(AtNewline::Continue, |p| {
1271 p.assert(SyntaxKind::LeftParen);
1272
1273 let mut seen = FxHashSet::default();
1274 let mut sink = false;
1275
1276 while !p.current().is_terminator() {
1277 if !p.at_set(set::PARAM) {
1278 p.unexpected();
1279 continue;
1280 }
1281
1282 param(p, &mut seen, &mut sink);
1283
1284 if !p.current().is_terminator() {
1285 p.expect(SyntaxKind::Comma);
1286 }
1287 }
1288
1289 p.expect_closing_delimiter(m, SyntaxKind::RightParen);
1290 });
1291 p.wrap(m, SyntaxKind::Params);
1292}
1293
1294fn param<'s>(p: &mut Parser<'s>, seen: &mut FxHashSet<&'s str>, sink: &mut bool) {
1296 let m = p.marker();
1297
1298 if p.eat_if(SyntaxKind::Dots) {
1300 if p.at_set(set::PATTERN_LEAF) {
1301 pattern_leaf(p, false, seen, Some("parameter"));
1302 }
1303 p.wrap(m, SyntaxKind::Spread);
1304 if mem::replace(sink, true) {
1305 p[m].convert_to_error("only one argument sink is allowed");
1306 }
1307 return;
1308 }
1309
1310 let was_at_pat = p.at_set(set::PATTERN);
1312 pattern(p, false, seen, Some("parameter"));
1313
1314 if p.eat_if(SyntaxKind::Colon) {
1316 if was_at_pat && p[m].kind() != SyntaxKind::Ident {
1318 p[m].expected("identifier");
1319 }
1320
1321 code_expr(p);
1322 p.wrap(m, SyntaxKind::Named);
1323 }
1324}
1325
1326fn pattern<'s>(
1328 p: &mut Parser<'s>,
1329 reassignment: bool,
1330 seen: &mut FxHashSet<&'s str>,
1331 dupe: Option<&'s str>,
1332) {
1333 let Some(p) = &mut p.increase_depth() else { return };
1334
1335 match p.current() {
1336 SyntaxKind::Underscore => p.eat(),
1337 SyntaxKind::LeftParen => destructuring_or_parenthesized(p, reassignment, seen),
1338 _ => pattern_leaf(p, reassignment, seen, dupe),
1339 }
1340}
1341
1342fn destructuring_or_parenthesized<'s>(
1344 p: &mut Parser<'s>,
1345 reassignment: bool,
1346 seen: &mut FxHashSet<&'s str>,
1347) {
1348 let mut sink = false;
1349 let mut count = 0;
1350 let mut maybe_just_parens = true;
1351
1352 let m = p.marker();
1353 p.with_nl_mode(AtNewline::Continue, |p| {
1354 p.assert(SyntaxKind::LeftParen);
1355
1356 while !p.current().is_terminator() {
1357 if !p.at_set(set::DESTRUCTURING_ITEM) {
1358 p.unexpected();
1359 continue;
1360 }
1361
1362 destructuring_item(p, reassignment, seen, &mut maybe_just_parens, &mut sink);
1363 count += 1;
1364
1365 if !p.current().is_terminator() && p.expect(SyntaxKind::Comma) {
1366 maybe_just_parens = false;
1367 }
1368 }
1369
1370 p.expect_closing_delimiter(m, SyntaxKind::RightParen);
1371 });
1372
1373 if maybe_just_parens && count == 1 && !sink {
1374 p.wrap(m, SyntaxKind::Parenthesized);
1375 } else {
1376 p.wrap(m, SyntaxKind::Destructuring);
1377 }
1378}
1379
1380fn destructuring_item<'s>(
1382 p: &mut Parser<'s>,
1383 reassignment: bool,
1384 seen: &mut FxHashSet<&'s str>,
1385 maybe_just_parens: &mut bool,
1386 sink: &mut bool,
1387) {
1388 let m = p.marker();
1389
1390 if p.eat_if(SyntaxKind::Dots) {
1392 if p.at_set(set::PATTERN_LEAF) {
1393 pattern_leaf(p, reassignment, seen, None);
1394 }
1395 p.wrap(m, SyntaxKind::Spread);
1396 if mem::replace(sink, true) {
1397 p[m].convert_to_error("only one destructuring sink is allowed");
1398 }
1399 return;
1400 }
1401
1402 let was_at_pat = p.at_set(set::PATTERN);
1404
1405 let checkpoint = p.checkpoint();
1408 if !(p.eat_if(SyntaxKind::Ident) && p.at(SyntaxKind::Colon)) {
1409 p.restore(checkpoint);
1410 pattern(p, reassignment, seen, None);
1411 }
1412
1413 if p.eat_if(SyntaxKind::Colon) {
1415 if was_at_pat && p[m].kind() != SyntaxKind::Ident {
1417 p[m].expected("identifier");
1418 }
1419
1420 pattern(p, reassignment, seen, None);
1421 p.wrap(m, SyntaxKind::Named);
1422 *maybe_just_parens = false;
1423 }
1424}
1425
1426fn pattern_leaf<'s>(
1429 p: &mut Parser<'s>,
1430 reassignment: bool,
1431 seen: &mut FxHashSet<&'s str>,
1432 dupe: Option<&'s str>,
1433) {
1434 if p.current().is_keyword() {
1435 p.eat_and_get().expected("pattern");
1436 return;
1437 } else if !p.at_set(set::PATTERN_LEAF) {
1438 p.expected("pattern");
1439 return;
1440 }
1441
1442 let m = p.marker();
1443 let text = p.current_text();
1444
1445 code_expr_prec(p, true, 0);
1449
1450 if !reassignment {
1451 let node = &mut p[m];
1452 if node.kind() == SyntaxKind::Ident {
1453 if !seen.insert(text) {
1454 node.convert_to_error(eco_format!(
1455 "duplicate {}: {text}",
1456 dupe.unwrap_or("binding"),
1457 ));
1458 }
1459 } else {
1460 node.expected("pattern");
1461 }
1462 }
1463}
1464
1465struct Parser<'s> {
1500 text: &'s str,
1502 lexer: Lexer<'s>,
1506 nl_mode: AtNewline,
1508 token: Token,
1513 balanced: bool,
1516 nodes: Vec<SyntaxNode>,
1519 memo: MemoArena,
1523 depth: u32,
1525}
1526
1527#[derive(Debug, Clone)]
1530struct Token {
1531 kind: SyntaxKind,
1533 node: SyntaxNode,
1536 n_trivia: usize,
1538 newline: Option<Newline>,
1540 start: usize,
1543 prev_end: usize,
1545}
1546
1547#[derive(Debug, Copy, Clone)]
1549struct Newline {
1550 column: Option<usize>,
1552 parbreak: bool,
1554}
1555
1556#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1558enum AtNewline {
1559 Continue,
1561 Stop,
1563 ContextualContinue,
1565 StopParBreak,
1567 RequireColumn(usize),
1571}
1572
1573impl AtNewline {
1574 fn stop_at(self, Newline { column, parbreak }: Newline, kind: SyntaxKind) -> bool {
1576 #[allow(clippy::match_like_matches_macro)]
1577 match self {
1578 AtNewline::Continue => false,
1579 AtNewline::Stop => true,
1580 AtNewline::ContextualContinue => match kind {
1581 SyntaxKind::Else | SyntaxKind::Dot => false,
1582 _ => true,
1583 },
1584 AtNewline::StopParBreak => parbreak,
1585 AtNewline::RequireColumn(min_col) => {
1586 column.is_some_and(|column| column <= min_col)
1591 }
1592 }
1593 }
1594}
1595
1596#[derive(Debug, Copy, Clone, Eq, PartialEq)]
1600struct Marker(usize);
1601
1602impl Index<Marker> for Parser<'_> {
1604 type Output = SyntaxNode;
1605
1606 fn index(&self, m: Marker) -> &Self::Output {
1607 &self.nodes[m.0]
1608 }
1609}
1610
1611impl IndexMut<Marker> for Parser<'_> {
1612 fn index_mut(&mut self, m: Marker) -> &mut Self::Output {
1613 &mut self.nodes[m.0]
1614 }
1615}
1616
1617impl<'s> Parser<'s> {
1619 fn new(text: &'s str, offset: usize, mode: SyntaxMode) -> Self {
1621 let mut lexer = Lexer::new(text, mode);
1622 lexer.jump(offset);
1623 let nl_mode = AtNewline::Continue;
1624 let mut nodes = vec![];
1625 let token = Self::lex(&mut nodes, &mut lexer, nl_mode);
1626 Self {
1627 text,
1628 lexer,
1629 nl_mode,
1630 token,
1631 balanced: true,
1632 nodes,
1633 memo: Default::default(),
1634 depth: 0,
1635 }
1636 }
1637
1638 fn finish(self) -> Vec<SyntaxNode> {
1640 self.nodes
1641 }
1642
1643 fn finish_into(self, kind: SyntaxKind) -> SyntaxNode {
1645 assert!(self.at(SyntaxKind::End));
1646 SyntaxNode::inner(kind, self.finish())
1647 }
1648
1649 fn current(&self) -> SyntaxKind {
1652 self.token.kind
1653 }
1654
1655 fn at(&self, kind: SyntaxKind) -> bool {
1657 self.token.kind == kind
1658 }
1659
1660 fn at_set(&self, set: SyntaxSet) -> bool {
1662 set.contains(self.token.kind)
1663 }
1664
1665 fn end(&self) -> bool {
1669 self.at(SyntaxKind::End)
1670 }
1671
1672 fn directly_at(&self, kind: SyntaxKind) -> bool {
1674 self.token.kind == kind && !self.had_trivia()
1675 }
1676
1677 fn had_trivia(&self) -> bool {
1679 self.token.n_trivia > 0
1680 }
1681
1682 fn had_newline(&self) -> bool {
1684 self.token.newline.is_some()
1685 }
1686
1687 fn current_column(&self) -> usize {
1690 self.token
1691 .newline
1692 .and_then(|newline| newline.column)
1693 .unwrap_or_else(|| self.lexer.column(self.token.start))
1694 }
1695
1696 fn current_text(&self) -> &'s str {
1698 &self.text[self.token.start..self.current_end()]
1699 }
1700
1701 fn current_start(&self) -> usize {
1703 self.token.start
1704 }
1705
1706 fn current_end(&self) -> usize {
1708 self.lexer.cursor()
1709 }
1710
1711 fn prev_end(&self) -> usize {
1713 self.token.prev_end
1714 }
1715}
1716
1717impl<'s> Parser<'s> {
1719 fn marker(&self) -> Marker {
1722 Marker(self.nodes.len())
1723 }
1724
1725 fn before_trivia(&self) -> Marker {
1728 Marker(self.nodes.len() - self.token.n_trivia)
1729 }
1730
1731 #[track_caller]
1733 fn eat_and_get(&mut self) -> &mut SyntaxNode {
1734 let offset = self.nodes.len();
1735 self.eat();
1736 &mut self.nodes[offset]
1737 }
1738
1739 fn eat_if(&mut self, kind: SyntaxKind) -> bool {
1744 let at = self.at(kind);
1745 if at {
1746 self.eat();
1747 }
1748 at
1749 }
1750
1751 #[track_caller]
1755 fn assert(&mut self, kind: SyntaxKind) {
1756 assert_eq!(self.token.kind, kind);
1757 self.eat();
1758 }
1759
1760 fn convert_and_eat(&mut self, kind: SyntaxKind) {
1762 self.token.node.convert_to_kind(kind);
1764 self.eat();
1765 }
1766
1767 fn eat(&mut self) {
1770 self.nodes.push(std::mem::take(&mut self.token.node));
1771 self.token = Self::lex(&mut self.nodes, &mut self.lexer, self.nl_mode);
1772 }
1773
1774 fn flush_trivia(&mut self) {
1777 self.token.n_trivia = 0;
1778 self.token.prev_end = self.token.start;
1779 }
1780
1781 fn wrap(&mut self, from: Marker, kind: SyntaxKind) {
1786 let to = self.before_trivia().0;
1787 let from = from.0.min(to);
1788 let children = self.nodes.drain(from..to).collect();
1789 self.nodes.insert(from, SyntaxNode::inner(kind, children));
1790 }
1791
1792 fn wrap_error(&mut self, from: Marker, message: impl Into<EcoString>) {
1797 let to = self.before_trivia().0;
1798 let from = from.0.min(to);
1799 let len: usize = self.nodes.drain(from..to).map(|node| node.len()).sum();
1800 let end = self.token.prev_end;
1801 let start = end - len;
1802 let text = &self.text[start..end];
1803 self.nodes.insert(from, SyntaxNode::error(message.into(), text));
1804 }
1805
1806 fn enter_modes(
1811 &mut self,
1812 mode: SyntaxMode,
1813 stop: AtNewline,
1814 func: impl FnOnce(&mut Parser<'s>),
1815 ) {
1816 let previous = self.lexer.mode();
1817 self.lexer.set_mode(mode);
1818 self.with_nl_mode(stop, func);
1819 if mode != previous {
1820 self.lexer.set_mode(previous);
1821 self.lexer.jump(self.token.prev_end);
1822 self.nodes.truncate(self.nodes.len() - self.token.n_trivia);
1823 self.token = Self::lex(&mut self.nodes, &mut self.lexer, self.nl_mode);
1824 }
1825 }
1826
1827 fn with_nl_mode(&mut self, mode: AtNewline, func: impl FnOnce(&mut Parser<'s>)) {
1832 let previous = self.nl_mode;
1833 self.nl_mode = mode;
1834 func(self);
1835 self.nl_mode = previous;
1836 if let Some(newline) = self.token.newline
1837 && mode != previous
1838 {
1839 let actual_kind = self.token.node.kind();
1841 if self.nl_mode.stop_at(newline, actual_kind) {
1842 self.token.kind = SyntaxKind::End;
1843 } else {
1844 self.token.kind = actual_kind;
1845 }
1846 }
1847 }
1848
1849 fn lex(nodes: &mut Vec<SyntaxNode>, lexer: &mut Lexer, nl_mode: AtNewline) -> Token {
1855 let prev_end = lexer.cursor();
1856 let mut start = prev_end;
1857 let (mut kind, mut node) = lexer.next();
1858 let mut n_trivia = 0;
1859 let mut had_newline = false;
1860 let mut parbreak = false;
1861
1862 while kind.is_trivia() {
1863 had_newline |= lexer.newline(); parbreak |= kind == SyntaxKind::Parbreak;
1865 n_trivia += 1;
1866 nodes.push(node);
1867 start = lexer.cursor();
1868 (kind, node) = lexer.next();
1869 }
1870
1871 let newline = if had_newline {
1872 let column =
1873 (lexer.mode() == SyntaxMode::Markup).then(|| lexer.column(start));
1874 let newline = Newline { column, parbreak };
1875 if nl_mode.stop_at(newline, kind) {
1876 kind = SyntaxKind::End;
1879 }
1880 Some(newline)
1881 } else {
1882 None
1883 };
1884
1885 Token { kind, node, n_trivia, newline, start, prev_end }
1886 }
1887}
1888
1889#[derive(Default)]
1894struct MemoArena {
1895 arena: Vec<SyntaxNode>,
1898 memo_map: FxHashMap<MemoKey, (Range<usize>, PartialState)>,
1902}
1903
1904type MemoKey = usize;
1908
1909struct Checkpoint {
1911 node_len: usize,
1912 state: PartialState,
1913}
1914
1915#[derive(Clone)]
1918struct PartialState {
1919 cursor: usize,
1920 lex_mode: SyntaxMode,
1921 token: Token,
1922}
1923
1924impl Parser<'_> {
1926 fn memoize_parsed_nodes(&mut self, key: MemoKey, prev_len: usize) {
1929 let Checkpoint { state, node_len } = self.checkpoint();
1930 let memo_start = self.memo.arena.len();
1931 self.memo.arena.extend_from_slice(&self.nodes[prev_len..node_len]);
1932 let arena_range = memo_start..self.memo.arena.len();
1933 self.memo.memo_map.insert(key, (arena_range, state));
1934 }
1935
1936 fn restore_memo_or_checkpoint(&mut self) -> Option<(MemoKey, Checkpoint)> {
1939 let key: MemoKey = self.current_start();
1941 match self.memo.memo_map.get(&key).cloned() {
1942 Some((range, state)) => {
1943 self.nodes.extend_from_slice(&self.memo.arena[range]);
1944 self.restore_partial(state);
1948 None
1949 }
1950 None => Some((key, self.checkpoint())),
1951 }
1952 }
1953
1954 fn restore(&mut self, checkpoint: Checkpoint) {
1956 self.nodes.truncate(checkpoint.node_len);
1957 self.restore_partial(checkpoint.state);
1958 }
1959
1960 fn restore_partial(&mut self, state: PartialState) {
1962 self.lexer.jump(state.cursor);
1963 self.lexer.set_mode(state.lex_mode);
1964 self.token = state.token;
1965 }
1966
1967 fn checkpoint(&self) -> Checkpoint {
1969 let node_len = self.nodes.len();
1970 let state = PartialState {
1971 cursor: self.lexer.cursor(),
1972 lex_mode: self.lexer.mode(),
1973 token: self.token.clone(),
1974 };
1975 Checkpoint { node_len, state }
1976 }
1977}
1978
1979impl Parser<'_> {
1982 fn expect(&mut self, kind: SyntaxKind) -> bool {
1984 let at = self.at(kind);
1985 if at {
1986 self.eat();
1987 } else if kind == SyntaxKind::Ident && self.token.kind.is_keyword() {
1988 self.trim_errors();
1989 self.eat_and_get().expected(kind.name());
1990 } else {
1991 self.balanced &= !kind.is_grouping();
1992 self.expected(kind.name());
1993 }
1994 at
1995 }
1996
1997 #[track_caller]
2000 fn expect_closing_delimiter(&mut self, open: Marker, kind: SyntaxKind) -> bool {
2001 let at = self.eat_if(kind);
2002 if !at {
2003 self.nodes[open.0].convert_to_error("unclosed delimiter");
2004 }
2005 at
2006 }
2007
2008 fn expected(&mut self, thing: &str) {
2011 if self.token.kind.is_error() {
2012 self.trim_errors();
2024 self.eat();
2025 } else if !self.after_error() {
2026 self.expected_at(self.before_trivia(), thing);
2027 }
2028 }
2029
2030 fn after_error(&mut self) -> bool {
2032 let m = self.before_trivia();
2033 m.0 > 0 && self.nodes[m.0 - 1].kind().is_error()
2034 }
2035
2036 fn expected_at(&mut self, m: Marker, thing: &str) {
2039 let error = SyntaxNode::error(eco_format!("expected {thing}"), "");
2040 self.nodes.insert(m.0, error);
2041 }
2042
2043 fn hint(&mut self, hint: &str) {
2045 let m = self.before_trivia();
2046 if let Some(error) = self.nodes.get_mut(m.0 - 1) {
2047 error.hint(hint);
2048 }
2049 }
2050
2051 fn unexpected(&mut self) {
2054 self.trim_errors();
2055 self.balanced &= !self.token.kind.is_grouping();
2056 self.eat_and_get().unexpected();
2057 }
2058
2059 fn trim_errors(&mut self) {
2061 let Marker(end) = self.before_trivia();
2062 let mut start = end;
2063 while start > 0
2064 && self.nodes[start - 1].kind().is_error()
2065 && self.nodes[start - 1].is_empty()
2066 {
2067 start -= 1;
2068 }
2069 self.nodes.drain(start..end);
2070 }
2071
2072 fn check_depth_until(&mut self, stop_set: SyntaxSet) -> Option<&mut Self> {
2081 if self.depth < MAX_DEPTH {
2082 Some(self)
2083 } else {
2084 self.depth_check_error(Some(stop_set));
2085 None
2086 }
2087 }
2088
2089 fn increase_depth(&mut self) -> Option<impl DerefMut<Target = Self>> {
2093 if self.depth < MAX_DEPTH {
2094 self.depth += 1;
2095 Some(defer(self, |p| p.depth -= 1))
2096 } else {
2097 self.depth_check_error(None);
2098 None
2099 }
2100 }
2101
2102 fn depth_check_error(&mut self, stop_set: Option<SyntaxSet>) {
2104 let m = self.marker();
2105
2106 let mut balance: usize = 0;
2107 self.with_nl_mode(AtNewline::Continue, |p| {
2112 loop {
2113 if p.at_set(syntax_set!(LeftBracket, LeftBrace, LeftParen)) {
2114 balance = balance.saturating_add(1);
2115 } else if p.at_set(syntax_set!(RightBracket, RightBrace, RightParen)) {
2116 balance = balance.saturating_sub(1);
2117 }
2118 p.eat();
2119
2120 let at_stop = stop_set.is_none_or(|s| p.at_set(s));
2121 if (balance == 0 && at_stop) || p.end() {
2122 break;
2123 }
2124 }
2125 });
2126
2127 self.wrap_error(m, "maximum parsing depth exceeded");
2128 }
2129}