use ktrs_syntax::{Parse, SyntaxKind};
use super::Parser;
use crate::FileKind;
use crate::builder::{ChameleonCache, LazyLeaf, PsiBuilder, SemanticWhitespaceAwarePsiBuilder, TreeSink};
pub fn parse(text: &str, kind: FileKind) -> Parse {
run_top_level(text, |kt_parsing| parse_by_kind(kt_parsing, kind))
}
pub fn parse_cached(text: &str, kind: FileKind, cache: &mut ChameleonCache) -> Parse {
let psi = PsiBuilder::lex_kotlin(text);
let mut sink = TreeSink::for_file(&psi, Some(std::mem::take(cache)));
run_into(psi, |kt_parsing| parse_by_kind(kt_parsing, kind), None, &mut sink);
*cache = sink.take_cache().expect("sink keeps its cache");
sink.finish()
}
fn parse_by_kind(kt_parsing: &mut Parser, kind: FileKind) {
match kind {
FileKind::Source => kt_parsing.parse_file(),
FileKind::Script => kt_parsing.parse_script(),
}
}
pub fn parse_type_code_fragment(text: &str) -> Parse {
run_top_level(text, Parser::parse_type_code_fragment)
}
pub fn parse_expression_code_fragment(text: &str) -> Parse {
run_top_level(text, Parser::parse_expression_code_fragment)
}
pub fn parse_block_code_fragment(text: &str) -> Parse {
run_top_level(text, Parser::parse_block_code_fragment)
}
pub fn parse_lambda_expression(text: &str) -> Parse {
run_top_level(text, Parser::parse_lambda_expression)
}
pub fn parse_block_expression(text: &str) -> Parse {
run_top_level(text, Parser::parse_block_expression)
}
fn run_top_level(text: &str, parse: impl FnOnce(&mut Parser)) -> Parse {
let psi = PsiBuilder::lex_kotlin(text);
let mut sink = TreeSink::for_file(&psi, None);
run_into(psi, parse, None, &mut sink);
sink.finish()
}
fn run_into(psi: PsiBuilder, parse: impl FnOnce(&mut Parser), root_kind: Option<SyntaxKind>, sink: &mut TreeSink) {
let mut kt_parsing = Parser::create_for_top_level(SemanticWhitespaceAwarePsiBuilder::new(psi));
parse(&mut kt_parsing);
kt_parsing.my_builder.psi.build_tree_into(root_kind, sink, &reparse_lazy);
}
pub(crate) fn reparse_lazy(leaf: &LazyLeaf<'_>, sink: &mut TreeSink) -> bool {
let (kind, text) = (leaf.kind, leaf.text);
match kind {
SyntaxKind::BLOCK => sink.chameleon(kind, text, |sink| {
run_into(leaf.relexed_builder(), Parser::parse_block_expression, Some(kind), sink)
}),
SyntaxKind::LAMBDA_EXPRESSION => sink.chameleon(kind, text, |sink| {
run_into(leaf.relexed_builder(), Parser::parse_lambda_expression, Some(kind), sink)
}),
SyntaxKind::DOC_COMMENT => sink.chameleon(kind, text, |sink| crate::kdoc::parse_kdoc_into(text, sink)),
SyntaxKind::KDOC_MARKDOWN_LINK => {
sink.chameleon(kind, text, |sink| crate::kdoc::parse_markdown_link_into(text, sink))
}
_ => return false,
}
true
}