use skullbrain_diagnostics::{EmitDiagnostics, ParseError};
use skullbrain_lexer::{DeclarationKind, TokenKind};
use crate::{state::ConcreteSyntaxTreeBuilder, Diagnostics, ParserState, SyntaxKind};
impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
pub(super) fn parse_variable(&mut self) {
self.start_node(SyntaxKind::VariableDeclaration);
self.parse_optional_modifiers();
self.parse_variable_keyword();
self.skip_trivia();
self.parse_variable_ident_type();
self.skip_trivia();
self.parse_only_assignable_expression();
self.finish_node();
}
fn parse_variable_ident_type(&mut self) {
if self.peek_sequence(Self::peek_sequence_for_single_function_parameter) {
self.parse_single_function_parameter();
return;
}
if self.peek().is_some_and(|i| i.kind().is_ident()) {
self.parse_ident();
return;
}
let diagnostic_details = self.diagnostic_details();
let error = ParseError::expected_variable_name_before();
self.emit_diagnostic(error, diagnostic_details);
}
fn parse_variable_keyword(&mut self) {
let Some(item) = self.next() else {
unreachable!()
};
match item.kind() {
TokenKind::Declaration(DeclarationKind::VariableDeclaration { is_mutable }) => {
let kind = if *is_mutable {
SyntaxKind::MutableVariableKeyword
} else {
SyntaxKind::ImmutableVariableKeyword
};
self.token(kind, item);
}
_ => unreachable!(),
}
}
}
#[cfg(test)]
mod test {
#[test]
fn test_variable() {
crate::test::create_parsing_test("variable/*.skull", |state| {
state.parse_variable();
});
}
}