skullbrain-parser 0.1.0

Parses skullbrain tokens into a concrete syntax tree (CST).
Documentation
use crate::{
    state::ScopeContext,
    syntax::utilities::{CLOSE_BRACE, OPEN_BRACE},
};

use super::*;

impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
    pub(super) fn parse_while_loop(&mut self) {
        self.parse_in_context(ScopeContext::Loop, |state| {
            state.start_node(SyntaxKind::WhileLoop);
            state.parse_token(SyntaxKind::Keyword);
            state.skip_trivia();
            state.parse_condition_and_body();
            state.finish_node();
        })
    }
}

impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
    pub(super) fn parse_for_loop_with_missing_open(&mut self) {
        // Technically the delimited-parser handles this issue
        self.parse_for_loop();
    }

    pub(super) fn parse_for_loop(&mut self) {
        self.parse_in_context(ScopeContext::Loop, |state| {
            state.start_node(SyntaxKind::ForLoop);
            state.parse_delimited_for_loop();
            state.skip_trivia();
            state.parse_expression_followed_by_braces();
            state.finish_node();
        });
    }

    fn parse_delimited_for_loop(&mut self) {
        const OPEN_FOR: TokenKind = TokenKind::ControlFlow(ControlFlowKind::ForLoopOpen);
        const CLOSE_FOR: TokenKind = TokenKind::ControlFlow(ControlFlowKind::ForLoopClose);

        self.parse_delimited_aggressive(
            SyntaxKind::DelimitedRange,
            (OPEN_FOR, SyntaxKind::ForIterOpen),
            (CLOSE_FOR, SyntaxKind::ForIterClose),
            |state| {
                state.parse_repeated_expression(|k| {
                    k.is(&CLOSE_FOR) || k.is(&OPEN_BRACE) || k.is(&CLOSE_BRACE)
                });
            },
        );
    }
}

mod test {
    #[test]
    fn test_while() {
        crate::test::create_parsing_test("loop_while/*.skull", |state| {
            state.parse_while_loop();
        });
    }

    #[test]
    fn test_for_loop() {
        crate::test::create_parsing_test("loop_for/*.skull", |state| {
            state.parse_for_loop();
        });
    }
}