arity_parser/parser/
core.rs1use crate::parser::bracket_balancer::rebalance_brackets;
2use crate::parser::context::StatementTracker;
3use crate::parser::events::Event;
4use crate::parser::expr::parse_expr;
5use crate::parser::lexer::{TokKind, lex};
6use crate::parser::tree_builder::build_tree;
7use crate::syntax::SyntaxNode;
8
9pub use crate::parser::diagnostics::ParseDiagnostic;
10
11#[derive(Debug, Clone)]
12pub struct ParseOutput {
13 pub cst: SyntaxNode,
14 pub diagnostics: Vec<ParseDiagnostic>,
15}
16
17pub fn parse(text: &str) -> ParseOutput {
18 let tokens = rebalance_brackets(lex(text));
19 let mut diagnostics = Vec::new();
20 let mut root_events = Vec::new();
21
22 let mut i = 0usize;
23 let mut statements = StatementTracker::default();
24 while i < tokens.len() {
25 if matches!(
26 tokens[i].kind,
27 TokKind::Whitespace | TokKind::Newline | TokKind::Semicolon
28 ) {
29 root_events.push(Event::Tok(i));
30 i += 1;
31 continue;
32 }
33
34 if tokens[i].kind == TokKind::RoxygenMarker {
35 i = crate::parser::roxygen::emit_roxygen_block(&tokens, i, &mut root_events);
36 continue;
37 }
38
39 let before = diagnostics.len();
40 if let Some(expr) = parse_expr(&tokens, i, 0, &mut diagnostics) {
41 if !tokens[expr.start].kind.is_comment_like() {
45 let recovered = diagnostics.len() > before;
46 statements.record(&tokens, expr.start, expr.end, recovered, &mut diagnostics);
47 }
48 root_events.extend(expr.events);
49 i = expr.end;
50 } else {
51 crate::parser::diagnostics::push_token_diagnostic(
56 &mut diagnostics,
57 &format!("unexpected '{}'", tokens[i].text),
58 &tokens[i],
59 );
60 root_events.push(Event::Tok(i));
61 i += 1;
62 statements.record_recovery(i);
63 }
64 }
65
66 let cst = build_tree(&tokens, &root_events);
67 ParseOutput { cst, diagnostics }
68}
69
70pub fn reconstruct(text: &str) -> String {
71 parse(text)
72 .cst
73 .descendants_with_tokens()
74 .filter_map(|el| el.into_token())
75 .map(|tok| tok.text().to_string())
76 .collect::<String>()
77}