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);
}
}
}
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();
});
}
}