use skullbrain_diagnostics::DiagnosticDetails;
use super::*;
impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
pub(super) fn parse_parathesis_comma_separated_expression(&mut self) {
self.parse_parenthesis_aggressive(|state| {
state.parse_seperated_by_comma(
|_| true,
|state| {
state.parse_repeated_expression(|k| {
Self::parse_parenthesis_with_expression_default_break(k)
|| k.punctuation_ref().is_some_and(|p| p.is_comma())
});
},
);
});
}
}
impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
pub(super) fn parse_name_followed_by_braced_expression(&mut self, error: ParseError) {
self.skip_trivia();
if self.peek().is_some_and(|i| i.kind().is_ident()) {
self.parse_ident();
} else {
let diagnostic_details = self.diagnostic_details();
self.emit_diagnostic(error, diagnostic_details);
}
self.skip_trivia();
self.parse_brace_with_expression();
}
}
impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
pub(super) fn parse_expression_followed_by_braces(&mut self) {
let details_before_block = self.diagnostic_details();
let next_was_block = self
.peek()
.is_some_and(|i| is_open_brace_or_paren(i.kind()));
self.parse_expression();
self.skip_trivia();
if next_was_block {
if self
.peek()
.is_some_and(|i| is_open_brace_or_paren(i.kind()))
{
self.parse_brace_with_expression();
} else {
self.emit_expected_expression_before(details_before_block);
}
} else {
self.parse_brace_with_expression();
}
}
fn emit_expected_expression_before(&mut self, details_before_block: DiagnosticDetails) {
let error = ParseError::expected_expression_before();
self.emit_diagnostic(error, details_before_block);
}
}
impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
pub(super) fn parse_condition_and_body(&mut self) {
self.parse_parenthesis_followed_by_brace_with_expression(
SyntaxKind::Condition,
SyntaxKind::Body,
);
}
pub(super) fn parse_condition_and_body_until(&mut self, until: impl Fn(&TokenKind) -> bool) {
self.parse_parenthesis_followed_by_brace_with_expression_until(
SyntaxKind::Condition,
SyntaxKind::Body,
until,
);
}
fn parse_parenthesis_followed_by_brace_with_expression(
&mut self,
wrap_paren: SyntaxKind,
wrap_brace: SyntaxKind,
) {
let checkpoint = self.checkpoint();
self.parse_parenthesis_with_expression();
self.start_node_at(checkpoint, wrap_paren);
self.finish_node();
self.skip_trivia();
let checkpoint = self.checkpoint();
self.parse_brace_with_expression();
self.start_node_at(checkpoint, wrap_brace);
self.finish_node();
}
fn parse_parenthesis_followed_by_brace_with_expression_until(
&mut self,
wrap_paren: SyntaxKind,
wrap_brace: SyntaxKind,
until: impl Fn(&TokenKind) -> bool,
) {
let checkpoint = self.checkpoint();
self.parse_parenthesis_with_expression_until(&until);
self.start_node_at(checkpoint, wrap_paren);
self.finish_node();
self.skip_trivia();
let checkpoint = self.checkpoint();
self.parse_brace_with_expression_until(until);
self.start_node_at(checkpoint, wrap_brace);
self.finish_node();
}
}
const OPEN_PAREN: TokenKind = TokenKind::Punctuation(PunctuationKind::OpenParen);
const CLOSE_PAREN: TokenKind = TokenKind::Punctuation(PunctuationKind::CloseParen);
pub(super) const OPEN_BRACE: TokenKind = TokenKind::Punctuation(PunctuationKind::OpenBrace);
pub(super) const CLOSE_BRACE: TokenKind = TokenKind::Punctuation(PunctuationKind::CloseBrace);
impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
pub(super) fn parse_parenthesis_with_expression(&mut self) {
self.parse_parenthesis_with_expression_until(|_| false)
}
pub(super) fn parse_brace_with_expression(&mut self) {
self.parse_brace_with_expression_until(|_| false)
}
fn parse_parenthesis_with_expression_until(&mut self, until: impl Fn(&TokenKind) -> bool) {
let _ = self.parse_parenthesis_aggressive(|state| {
state.parse_repeated_expression(|k| {
Self::parse_parenthesis_with_expression_default_break(k)
|| is_open_or_close_brace(k)
|| until(k)
});
});
}
pub(super) fn parse_brace_with_expression_until(&mut self, until: impl Fn(&TokenKind) -> bool) {
self.parse_brace_aggressive(|state| {
state.parse_repeated_expression(|k| k.is(&CLOSE_BRACE) || until(k));
});
}
fn parse_parenthesis_with_expression_default_break(k: &TokenKind) -> bool {
k.is(&CLOSE_PAREN)
}
pub(super) fn parse_repeated_expression(&mut self, should_break: impl Fn(&TokenKind) -> bool) {
loop {
self.skip_trivia();
match self.peek_raw() {
None => break,
Some(item) if is_dot(item.kind()) || should_break(item.kind()) => break,
Some(_) => self.parse_expression(),
}
}
}
}
fn is_open_or_close_brace(kind: &TokenKind) -> bool {
kind.is(&OPEN_BRACE) || kind.is(&CLOSE_BRACE)
}
fn is_open_brace_or_paren(kind: &TokenKind) -> bool {
kind.is(&OPEN_PAREN) || kind.is(&OPEN_BRACE)
}