mod assignable;
mod basic;
mod class;
mod control_flow;
mod enumz;
mod func;
mod if_else;
mod import;
mod loops;
mod matchz;
mod modifier;
mod possible_call;
mod pratt;
mod throw_error;
mod traits;
mod try_catch;
mod ty;
mod type_alias;
mod utilities;
mod variable;
use skullbrain_diagnostics::{EmitDiagnostics, ParseError};
use skullbrain_lexer::{ControlFlowKind, DeclarationKind, PunctuationKind, TokenKind};
use crate::{
state::{ConcreteSyntaxTreeBuilder, PeekSequence, ScopeContext},
Diagnostics, ParserState, SyntaxKind,
};
impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
fn parse_optional_expression(&mut self) {
if self.peek().is_some() {
self.parse_expression();
}
}
pub(crate) fn parse_expression(&mut self) {
self.parse_with_binding_power(0);
if self.peek_raw().is_some_and(|i| is_dot(i.kind())) {
self.parse_raw_token(SyntaxKind::SemiColon);
}
}
fn __parse_actual_expression(&mut self) {
self.skip_trivia();
match self.peek() {
None => self.emit_expected_expression_eof(),
Some(item) => match item.kind() {
TokenKind::Unknown => self.parse_unknown(),
TokenKind::Literial(_) => self.parse_literal(),
TokenKind::Ident => self.parse_possible_call_expr_or_ident_only(),
TokenKind::ControlFlow(ControlFlowKind::Throw) => self.parse_throw_error(),
TokenKind::ControlFlow(ControlFlowKind::Break) => self.parse_break_stmt(),
TokenKind::ControlFlow(ControlFlowKind::Continue) => self.parse_continue_stmt(),
TokenKind::ControlFlow(ControlFlowKind::Return) => self.parse_return_stmt(),
TokenKind::ControlFlow(ControlFlowKind::While) => self.parse_while_loop(),
TokenKind::ControlFlow(ControlFlowKind::Try) => self.parse_try_catch(),
TokenKind::ControlFlow(ControlFlowKind::Catch) => {
self.parse_catch_with_missing_try()
}
TokenKind::ControlFlow(ControlFlowKind::If) => self.parse_if_else(),
TokenKind::ControlFlow(ControlFlowKind::Else) => self.parse_else_with_missing_if(),
TokenKind::ControlFlow(ControlFlowKind::ForLoopOpen) => self.parse_for_loop(),
TokenKind::ControlFlow(ControlFlowKind::ForLoopClose) => {
self.parse_for_loop_with_missing_open()
}
TokenKind::ControlFlow(ControlFlowKind::Match) => self.parse_match(),
TokenKind::ControlFlow(ControlFlowKind::MatchArmCondition) => {
self.parse_match_cond()
}
TokenKind::ControlFlow(ControlFlowKind::MatchArmDefault) => {
self.parse_match_default_cond()
}
TokenKind::Declaration(DeclarationKind::VariableDeclaration { .. }) => {
self.parse_variable()
}
TokenKind::Punctuation(PunctuationKind::OpenBrace) => {
self.parse_brace_with_expression()
}
TokenKind::Punctuation(PunctuationKind::CloseBrace) => {
self.parse_brace_with_expression()
}
TokenKind::Punctuation(PunctuationKind::OpenParen) => {
self.parse_parenthesis_with_expression()
}
TokenKind::Punctuation(PunctuationKind::CloseParen) => {
self.parse_parenthesis_with_expression()
}
TokenKind::Punctuation(PunctuationKind::Arrow) => {
self.parse_token(SyntaxKind::Arrow);
}
TokenKind::Punctuation(PunctuationKind::Colon) => {
self.parse_token(SyntaxKind::Colon);
}
TokenKind::Punctuation(PunctuationKind::Comma) => {
self.parse_token(SyntaxKind::Comma);
}
TokenKind::Declaration(DeclarationKind::Import) => self.parse_import_expression(),
TokenKind::Declaration(DeclarationKind::Alias) => self.parse_type_alias(),
TokenKind::Declaration(DeclarationKind::Function) => self.parse_function_delc(),
TokenKind::Declaration(DeclarationKind::Trait) => self.parse_trait_delc(),
TokenKind::Declaration(DeclarationKind::TraitImpl) => self.parse_trait_impl(),
TokenKind::Declaration(DeclarationKind::Class) => self.parse_class_delc(),
TokenKind::Declaration(DeclarationKind::Enum) => self.parse_enum_delc(),
TokenKind::Declaration(DeclarationKind::EnumVariant) => self.parse_enum_variant(),
TokenKind::Modifier(_) => self.wrap_modifiers_if_needed(),
TokenKind::Whitespace
| TokenKind::SingleLineComment
| TokenKind::MultiLineComment { .. }
| TokenKind::Punctuation(PunctuationKind::Dot)
| TokenKind::Operator(_) => unreachable!(),
},
}
}
fn wrap_modifiers_if_needed(&mut self) {
let accepts_modifiers = self.peek_sequence(|peekable| {
skip_modifier_tokens(peekable);
peekable
.peek_next()
.and_then(|i| next_token_accepts_modifiers(i))
});
match accepts_modifiers {
Some(delc) => match delc {
DeclarationKind::Alias => self.parse_type_alias(),
DeclarationKind::Function => self.parse_function_delc(),
DeclarationKind::Trait => self.parse_trait_delc(),
DeclarationKind::Class => self.parse_class_delc(),
DeclarationKind::Enum => self.parse_enum_delc(),
_ => unreachable!(),
},
None => {
self.parse_optional_modifiers();
}
}
}
}
fn next_token_accepts_modifiers(i: &crate::state::PositionedToken) -> Option<DeclarationKind> {
match i.kind().declaration_ref() {
Some(d)
if d.is_alias() || d.is_function() || d.is_trait() || d.is_class() || d.is_enum() =>
{
Some(d.clone())
}
_ => None,
}
}
fn skip_modifier_tokens(peekable: &mut PeekSequence) {
while peekable.peek_next().is_some_and(|i| i.kind().is_modifier()) {}
}
impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
fn emit_expected_expression_eof(&mut self) {
let diagnostic_details = self.diagnostic_details();
let error = ParseError::expected_expression_at();
self.emit_diagnostic(error, diagnostic_details);
}
}
fn is_dot(kind: &TokenKind) -> bool {
kind.punctuation_ref().is_some_and(|k| k.is_dot())
}