2020-08-12 15:06:49 +00:00
|
|
|
//! Lexing, bridging to parser (which does the actual parsing) and
|
2019-02-21 12:24:42 +00:00
|
|
|
//! incremental reparsing.
|
|
|
|
|
2019-02-20 13:24:39 +00:00
|
|
|
mod reparsing;
|
2019-02-20 12:47:32 +00:00
|
|
|
|
2021-12-26 13:47:10 +00:00
|
|
|
use rowan::TextRange;
|
|
|
|
|
2021-12-28 15:57:13 +00:00
|
|
|
use crate::{syntax_node::GreenNode, SyntaxError, SyntaxTreeBuilder};
|
2019-02-20 12:47:32 +00:00
|
|
|
|
2021-12-18 14:20:38 +00:00
|
|
|
pub(crate) use crate::parsing::reparsing::incremental_reparse;
|
2019-02-20 12:47:32 +00:00
|
|
|
|
2024-01-30 15:57:40 +00:00
|
|
|
pub(crate) fn parse_text(text: &str, edition: parser::Edition) -> (GreenNode, Vec<SyntaxError>) {
|
2024-06-06 23:52:25 +00:00
|
|
|
let _p = tracing::info_span!("parse_text").entered();
|
2024-07-17 08:49:12 +00:00
|
|
|
let lexed = parser::LexedStr::new(edition, text);
|
2024-07-19 18:04:38 +00:00
|
|
|
let parser_input = lexed.to_input(edition);
|
2024-01-30 15:57:40 +00:00
|
|
|
let parser_output = parser::TopEntryPoint::SourceFile.parse(&parser_input, edition);
|
2021-12-28 16:13:30 +00:00
|
|
|
let (node, errors, _eof) = build_tree(lexed, parser_output);
|
internal: replace TreeSink with a data structure
The general theme of this is to make parser a better independent
library.
The specific thing we do here is replacing callback based TreeSink with
a data structure. That is, rather than calling user-provided tree
construction methods, the parser now spits out a very bare-bones tree,
effectively a log of a DFS traversal.
This makes the parser usable without any *specifc* tree sink, and allows
us to, eg, move tests into this crate.
Now, it's also true that this is a distinction without a difference, as
the old and the new interface are equivalent in expressiveness. Still,
this new thing seems somewhat simpler. But yeah, I admit I don't have a
suuper strong motivation here, just a hunch that this is better.
2021-12-19 14:36:23 +00:00
|
|
|
(node, errors)
|
2019-02-20 12:47:32 +00:00
|
|
|
}
|
2020-06-18 21:43:19 +00:00
|
|
|
|
2024-06-02 18:09:36 +00:00
|
|
|
pub(crate) fn parse_text_at(
|
|
|
|
text: &str,
|
|
|
|
entry: parser::TopEntryPoint,
|
|
|
|
edition: parser::Edition,
|
|
|
|
) -> (GreenNode, Vec<SyntaxError>) {
|
2024-06-06 23:52:25 +00:00
|
|
|
let _p = tracing::info_span!("parse_text_at").entered();
|
2024-07-17 08:49:12 +00:00
|
|
|
let lexed = parser::LexedStr::new(edition, text);
|
2024-07-19 18:04:38 +00:00
|
|
|
let parser_input = lexed.to_input(edition);
|
2024-03-09 02:45:35 +00:00
|
|
|
let parser_output = entry.parse(&parser_input, edition);
|
|
|
|
let (node, errors, _eof) = build_tree(lexed, parser_output);
|
|
|
|
(node, errors)
|
|
|
|
}
|
|
|
|
|
2021-12-26 13:47:10 +00:00
|
|
|
pub(crate) fn build_tree(
|
|
|
|
lexed: parser::LexedStr<'_>,
|
|
|
|
parser_output: parser::Output,
|
|
|
|
) -> (GreenNode, Vec<SyntaxError>, bool) {
|
2024-06-06 23:52:25 +00:00
|
|
|
let _p = tracing::info_span!("build_tree").entered();
|
2021-12-26 13:47:10 +00:00
|
|
|
let mut builder = SyntaxTreeBuilder::default();
|
|
|
|
|
2021-12-28 16:13:30 +00:00
|
|
|
let is_eof = lexed.intersperse_trivia(&parser_output, &mut |step| match step {
|
2021-12-26 13:47:10 +00:00
|
|
|
parser::StrStep::Token { kind, text } => builder.token(kind, text),
|
|
|
|
parser::StrStep::Enter { kind } => builder.start_node(kind),
|
|
|
|
parser::StrStep::Exit => builder.finish_node(),
|
|
|
|
parser::StrStep::Error { msg, pos } => {
|
2024-02-09 15:51:58 +00:00
|
|
|
builder.error(msg.to_owned(), pos.try_into().unwrap())
|
2021-12-26 13:47:10 +00:00
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
let (node, mut errors) = builder.finish_raw();
|
|
|
|
for (i, err) in lexed.errors() {
|
|
|
|
let text_range = lexed.text_range(i);
|
|
|
|
let text_range = TextRange::new(
|
|
|
|
text_range.start.try_into().unwrap(),
|
|
|
|
text_range.end.try_into().unwrap(),
|
|
|
|
);
|
|
|
|
errors.push(SyntaxError::new(err, text_range))
|
|
|
|
}
|
|
|
|
|
|
|
|
(node, errors, is_eof)
|
|
|
|
}
|