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_with_md};
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
17#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Hash)]
21#[non_exhaustive]
22pub struct ParseOptions {
23 pub roxygen_markdown_default: bool,
35}
36
37impl ParseOptions {
38 #[must_use]
45 pub fn with_roxygen_markdown_default(mut self, on: bool) -> Self {
46 self.roxygen_markdown_default = on;
47 self
48 }
49}
50
51pub fn parse(text: &str) -> ParseOutput {
52 parse_with_options(text, &ParseOptions::default())
53}
54
55pub fn parse_with_options(text: &str, options: &ParseOptions) -> ParseOutput {
58 let md_default = options.roxygen_markdown_default;
59 let tokens = rebalance_brackets(lex_with_md(text, md_default));
60 let mut diagnostics = Vec::new();
61 let mut root_events = Vec::new();
62
63 let mut i = 0usize;
64 let mut statements = StatementTracker::default();
65 while i < tokens.len() {
66 if matches!(
67 tokens[i].kind,
68 TokKind::Whitespace | TokKind::Newline | TokKind::Semicolon
69 ) {
70 root_events.push(Event::Tok(i));
71 i += 1;
72 continue;
73 }
74
75 if tokens[i].kind == TokKind::RoxygenMarker {
76 i = crate::parser::roxygen::emit_roxygen_block(
77 &tokens,
78 i,
79 &mut root_events,
80 md_default,
81 );
82 continue;
83 }
84
85 let before = diagnostics.len();
86 if let Some(expr) = parse_expr(&tokens, i, 0, &mut diagnostics, md_default) {
87 if !tokens[expr.start].kind.is_comment_like() {
91 let recovered = diagnostics.len() > before;
92 statements.record(&tokens, expr.start, expr.end, recovered, &mut diagnostics);
93 }
94 root_events.extend(expr.events);
95 i = expr.end;
96 } else {
97 crate::parser::diagnostics::push_token_diagnostic(
98 &mut diagnostics,
99 &format!("unexpected '{}'", tokens[i].text),
100 &tokens[i],
101 );
102 root_events.push(Event::Tok(i));
103 i += 1;
104 statements.record_recovery(i);
105 }
106 }
107
108 crate::parser::diagnostics::refine_unicode_diagnostics(&tokens, &mut diagnostics);
109 let cst = build_tree(&tokens, &root_events);
110 ParseOutput { cst, diagnostics }
111}
112
113pub fn reconstruct(text: &str) -> String {
114 parse(text)
115 .cst
116 .descendants_with_tokens()
117 .filter_map(|el| el.into_token())
118 .map(|tok| tok.text().to_string())
119 .collect::<String>()
120}