skullbrain-parser 0.1.0

Parses skullbrain tokens into a concrete syntax tree (CST).
Documentation
use super::*;

impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
    pub(crate) fn parse_try_catch(&mut self) {
        self.start_node(SyntaxKind::TryCatch);

        self.parse_try_only();
        self.skip_trivia();

        while self
            .peek()
            .is_some_and(|i| i.kind().is(&TokenKind::ControlFlow(ControlFlowKind::Catch)))
        {
            self.parse_catch_only()
        }

        self.finish_node();
    }

    fn parse_try_only(&mut self) {
        let checkpoint = self.checkpoint();
        self.parse_token(SyntaxKind::Keyword);
        self.skip_trivia();
        self.parse_brace_with_expression();

        self.start_node_at(checkpoint, SyntaxKind::Try);
        self.finish_node();
    }

    pub(crate) fn parse_catch_with_missing_try(&mut self) {
        self.start_node(SyntaxKind::TryCatch);

        self.emit_missing_try();
        self.parse_catch_only();
        self.finish_node();
    }

    fn emit_missing_try(&mut self) {
        let diagnostic_details = self.diagnostic_details();
        let error = ParseError::missing_try_block();
        self.emit_diagnostic(error, diagnostic_details);
    }

    fn parse_catch_only(&mut self) {
        self.start_node(SyntaxKind::Catch);
        self.parse_token(SyntaxKind::Keyword);
        self.skip_trivia();

        if self
            .peek_sequence(|peekable| Self::peek_sequence_for_single_function_parameter(peekable))
        {
            self.parse_single_function_parameter();
            self.skip_trivia();
        }

        self.parse_brace_with_expression();
        self.skip_trivia();

        self.finish_node();
    }
}

mod test {
    #[test]
    fn test_try_catch() {
        crate::test::create_parsing_test("try_catch/try_catch*.skull", |state| {
            state.parse_try_catch();
        });
    }

    #[test]
    fn test_missing_catch() {
        crate::test::create_parsing_test("try_catch/missing_try*.skull", |state| {
            state.parse_catch_with_missing_try();
        });
    }
}