syntax/
parsing.rs

1//! Lexing, bridging to parser (which does the actual parsing) and
2//! incremental reparsing.
3
4mod reparsing;
5
6use rowan::TextRange;
7
8use crate::{SyntaxError, SyntaxTreeBuilder, syntax_node::GreenNode};
9
10pub(crate) use crate::parsing::reparsing::incremental_reparse;
11
12pub(crate) fn parse_text(text: &str, edition: parser::Edition) -> (GreenNode, Vec<SyntaxError>) {
13    let _p = tracing::info_span!("parse_text").entered();
14    let lexed = parser::LexedStr::new(edition, text);
15    let parser_input = lexed.to_input(edition);
16    let parser_output = parser::TopEntryPoint::SourceFile.parse(&parser_input);
17    let (node, errors, _eof) = build_tree(lexed, parser_output);
18    (node, errors)
19}
20
21pub(crate) fn parse_text_at(
22    text: &str,
23    entry: parser::TopEntryPoint,
24    edition: parser::Edition,
25) -> (GreenNode, Vec<SyntaxError>) {
26    let _p = tracing::info_span!("parse_text_at").entered();
27    let lexed = parser::LexedStr::new(edition, text);
28    let parser_input = lexed.to_input(edition);
29    let parser_output = entry.parse(&parser_input);
30    let (node, errors, _eof) = build_tree(lexed, parser_output);
31    (node, errors)
32}
33
34pub(crate) fn build_tree(
35    lexed: parser::LexedStr<'_>,
36    parser_output: parser::Output,
37) -> (GreenNode, Vec<SyntaxError>, bool) {
38    let _p = tracing::info_span!("build_tree").entered();
39    let mut builder = SyntaxTreeBuilder::default();
40
41    let is_eof = lexed.intersperse_trivia(&parser_output, &mut |step| match step {
42        parser::StrStep::Token { kind, text } => builder.token(kind, text),
43        parser::StrStep::Enter { kind } => builder.start_node(kind),
44        parser::StrStep::Exit => builder.finish_node(),
45        parser::StrStep::Error { msg, pos } => {
46            builder.error(msg.to_owned(), pos.try_into().unwrap())
47        }
48    });
49
50    let (node, mut errors) = builder.finish_raw();
51    for (i, err) in lexed.errors() {
52        let text_range = lexed.text_range(i);
53        let text_range = TextRange::new(
54            text_range.start.try_into().unwrap(),
55            text_range.end.try_into().unwrap(),
56        );
57        errors.push(SyntaxError::new(err, text_range))
58    }
59
60    (node, errors, is_eof)
61}