ktrs_parser/parsing/
kotlin_parser.rs1use ktrs_syntax::{Parse, SyntaxKind};
5
6use super::Parser;
7use crate::FileKind;
8use crate::builder::{ChameleonCache, LazyLeaf, PsiBuilder, SemanticWhitespaceAwarePsiBuilder, TreeSink};
9
10pub fn parse(text: &str, kind: FileKind) -> Parse {
12 run_top_level(text, |kt_parsing| parse_by_kind(kt_parsing, kind))
13}
14
15pub fn parse_cached(text: &str, kind: FileKind, cache: &mut ChameleonCache) -> Parse {
17 let psi = PsiBuilder::lex_kotlin(text);
18 let mut sink = TreeSink::for_file(&psi, Some(std::mem::take(cache)));
19 run_into(psi, |kt_parsing| parse_by_kind(kt_parsing, kind), None, &mut sink);
20 *cache = sink.take_cache().expect("sink keeps its cache");
21 sink.finish()
22}
23
24fn parse_by_kind(kt_parsing: &mut Parser, kind: FileKind) {
25 match kind {
26 FileKind::Source => kt_parsing.parse_file(),
27 FileKind::Script => kt_parsing.parse_script(),
28 }
29}
30
31pub fn parse_type_code_fragment(text: &str) -> Parse {
32 run_top_level(text, Parser::parse_type_code_fragment)
33}
34
35pub fn parse_expression_code_fragment(text: &str) -> Parse {
36 run_top_level(text, Parser::parse_expression_code_fragment)
37}
38
39pub fn parse_block_code_fragment(text: &str) -> Parse {
40 run_top_level(text, Parser::parse_block_code_fragment)
41}
42
43pub fn parse_lambda_expression(text: &str) -> Parse {
45 run_top_level(text, Parser::parse_lambda_expression)
46}
47
48pub fn parse_block_expression(text: &str) -> Parse {
50 run_top_level(text, Parser::parse_block_expression)
51}
52
53fn run_top_level(text: &str, parse: impl FnOnce(&mut Parser)) -> Parse {
56 let psi = PsiBuilder::lex_kotlin(text);
57 let mut sink = TreeSink::for_file(&psi, None);
58 run_into(psi, parse, None, &mut sink);
59 sink.finish()
60}
61
62fn run_into(psi: PsiBuilder, parse: impl FnOnce(&mut Parser), root_kind: Option<SyntaxKind>, sink: &mut TreeSink) {
63 let mut kt_parsing = Parser::create_for_top_level(SemanticWhitespaceAwarePsiBuilder::new(psi));
64 parse(&mut kt_parsing);
65 kt_parsing.my_builder.psi.build_tree_into(root_kind, sink, &reparse_lazy);
66}
67
68pub(crate) fn reparse_lazy(leaf: &LazyLeaf<'_>, sink: &mut TreeSink) -> bool {
73 let (kind, text) = (leaf.kind, leaf.text);
74 match kind {
75 SyntaxKind::BLOCK => sink.chameleon(kind, text, |sink| {
76 run_into(leaf.relexed_builder(), Parser::parse_block_expression, Some(kind), sink)
77 }),
78 SyntaxKind::LAMBDA_EXPRESSION => sink.chameleon(kind, text, |sink| {
79 run_into(leaf.relexed_builder(), Parser::parse_lambda_expression, Some(kind), sink)
80 }),
81 SyntaxKind::DOC_COMMENT => sink.chameleon(kind, text, |sink| crate::kdoc::parse_kdoc_into(text, sink)),
82 SyntaxKind::KDOC_MARKDOWN_LINK => {
83 sink.chameleon(kind, text, |sink| crate::kdoc::parse_markdown_link_into(text, sink))
84 }
85 _ => return false,
86 }
87 true
88}