internal: move ws attachment logic to the parser crate

This has to re-introduce the `sink` pattern, because doing this purely
with iterators is awkward :( Maaaybe the event vector was a false start?

But, anyway, I like the current factoring more -- it sort-of obvious
that we do want to keep ws-attachment business in the parser, and that
we also don't want that to depend on the particular tree structure. I
think `shortcuts` module achieves that.
This commit is contained in:
Aleksey Kladov 2021-12-26 16:47:10 +03:00
parent c456b217d8
commit f4cb0ff9be
6 changed files with 255 additions and 221 deletions

View file

@ -1,12 +1,11 @@
//! Lexing, bridging to parser (which does the actual parsing) and
//! incremental reparsing.
mod text_tree_sink;
mod reparsing;
use crate::{
parsing::text_tree_sink::build_tree, syntax_node::GreenNode, AstNode, SyntaxError, SyntaxNode,
};
use rowan::TextRange;
use crate::{syntax_node::GreenNode, AstNode, SyntaxError, SyntaxNode, SyntaxTreeBuilder};
pub(crate) use crate::parsing::reparsing::incremental_reparse;
@ -37,3 +36,32 @@ pub(crate) fn parse_text_as<T: AstNode>(
SyntaxNode::new_root(node).first_child().and_then(T::cast).ok_or(())
}
pub(crate) fn build_tree(
lexed: parser::LexedStr<'_>,
parser_output: parser::Output,
synthetic_root: bool,
) -> (GreenNode, Vec<SyntaxError>, bool) {
let mut builder = SyntaxTreeBuilder::default();
let is_eof = lexed.intersperse_trivia(&parser_output, synthetic_root, &mut |step| match step {
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 } => {
builder.error(msg.to_string(), pos.try_into().unwrap())
}
});
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)
}