skullbrain-parser 0.1.0

Parses skullbrain tokens into a concrete syntax tree (CST).
Documentation
use skullbrain_diagnostics::{EmitDiagnostics, ParseError};
use skullbrain_lexer::{PunctuationKind, TokenKind};

use crate::{
    state::{ConcreteSyntaxTreeBuilder, PeekSequence},
    Diagnostics, ParserState, SyntaxKind,
};

impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
    pub(crate) fn parse_type(&mut self) {
        if self.try_possibilites() {
            self.recover();

            if self.try_possibilites() {
                let diagnostic_details = self.diagnostic_details();

                self.emit_diagnostic(ParseError::expected_type_before(), diagnostic_details);
            }
        }
    }

    /// Creates a predicate function for type parsing
    pub(super) fn peek_sequence_for_type<'a>(peekable: &mut PeekSequence) -> bool {
        peekable.peek_next_is(&TokenKind::Ident) || {
            peekable.revert_by_one();
            Self::peek_sequence_for_function_signature(peekable)
        }
    }
}
impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
    fn try_possibilites(&mut self) -> bool {
        self.skip_trivia();

        match self.peek() {
            None => {
                let diagnostic_details_eof = self.diagnostic_details();

                self.emit_diagnostic(ParseError::expected_type_at(), diagnostic_details_eof);
                false
            }
            Some(item) if item.kind().is_ident() => {
                let Some(item) = self.next() else {
                    unreachable!()
                };

                self.token(SyntaxKind::Type, item);
                false
            }

            Some(item)
                if matches!(
                    item.kind(),
                    TokenKind::Punctuation(PunctuationKind::OpenParen)
                ) =>
            {
                self.start_node(SyntaxKind::Type);
                self.parse_function_signature();
                self.finish_node();
                false
            }
            Some(_) => true,
        }
    }
}

#[cfg(test)]
mod test {
    #[test]
    fn test_type() {
        crate::test::create_parsing_test("types/*.skull", |state| {
            state.parse_type();
        });
    }
}