use ktrs_syntax::SyntaxKind::*;
use super::{EQ_RPAR_SET, WHEN_CONDITION_RECOVERY_SET, WHEN_CONDITION_RECOVERY_SET_WITH_ARROW};
use crate::builder::EdgeBinder;
use crate::parsing::Parser;
use crate::parsing::declarations::DeclarationParsingMode;
use crate::token_set::TokenSet;
impl Parser {
pub(crate) fn parse_when(&mut self) {
debug_assert!(self._at(WHEN_KEYWORD));
let when = self.mark();
self.advance();
self.my_builder.disable_newlines();
if self.at(LPAR) {
self.advance_at(LPAR);
let at_when_start = self.mark();
self.parse_annotations_list(EQ_RPAR_SET);
if self.at(VAL_KEYWORD) || self.at(VAR_KEYWORD) {
let decl_type = self.parse_property(DeclarationParsingMode::Local);
at_when_start.done(self, decl_type);
at_when_start.set_custom_edge_token_binders(
self,
Some(EdgeBinder::PrecedingDocComments),
Some(EdgeBinder::TrailingComments),
);
} else {
at_when_start.rollback_to(self);
self.parse_expression();
}
self.expect_2(RPAR, "Expecting ')'");
}
self.my_builder.restore_newlines_state();
self.my_builder.enable_newlines();
if self.expect_2(LBRACE, "Expecting '{'") {
while !self.eof() && !self.at(RBRACE) {
self.parse_when_entry();
}
self.expect_2(RBRACE, "Expecting '}'");
}
self.my_builder.restore_newlines_state();
when.done(self, WHEN);
}
pub(crate) fn parse_when_entry(&mut self) {
let entry = self.mark();
if self.at(ELSE_KEYWORD) {
self.advance();
self.parse_when_entry_guard_or_suggest();
if !self.at(ARROW) {
self.error_until("Expecting '->'", TokenSet::create(&[ARROW, LBRACE, RBRACE, EOL_OR_SEMICOLON]));
}
if self.at(ARROW) {
self.advance();
if self.at_set(WHEN_CONDITION_RECOVERY_SET) {
self.error("Expecting an element");
} else {
self.parse_control_structure_body();
}
} else if self.at(LBRACE) {
self.parse_control_structure_body();
} else if !self.at_set(WHEN_CONDITION_RECOVERY_SET) {
self.error_and_advance("Expecting '->'");
}
} else {
self.parse_when_entry_not_else();
}
entry.done(self, WHEN_ENTRY);
self.consume_if(SEMICOLON);
}
pub(crate) fn parse_when_entry_not_else(&mut self) {
loop {
while self.at(COMMA) {
self.error_and_advance("Expecting a when-condition");
}
self.parse_when_condition();
if !self.at(COMMA) {
break;
}
self.advance(); if self.at(ARROW) {
break;
}
}
self.parse_when_entry_guard_or_suggest();
self.expect_3(ARROW, "Expecting '->'", Some(WHEN_CONDITION_RECOVERY_SET));
if self.at_set(WHEN_CONDITION_RECOVERY_SET) {
self.error("Expecting an element");
} else {
self.parse_control_structure_body();
}
}
pub(crate) fn parse_when_condition(&mut self) {
let condition = self.mark();
self.my_builder.disable_newlines();
match self.get_token_id() {
Some(IN_KEYWORD | NOT_IN) => {
let mark = self.mark();
self.advance(); mark.done(self, OPERATION_REFERENCE);
if self.at_set(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW) {
self.error("Expecting an element");
} else {
self.parse_expression();
}
condition.done(self, WHEN_CONDITION_IN_RANGE);
}
Some(IS_KEYWORD | NOT_IS) => {
self.advance();
if self.at_set(WHEN_CONDITION_RECOVERY_SET_WITH_ARROW) {
self.error("Expecting a type");
} else {
self.parse_type_ref();
}
condition.done(self, WHEN_CONDITION_IS_PATTERN);
}
Some(RBRACE | ELSE_KEYWORD | ARROW | DOT) => {
self.error("Expecting an expression, is-condition or in-condition");
condition.done(self, WHEN_CONDITION_EXPRESSION);
}
_ => {
self.parse_expression();
condition.done(self, WHEN_CONDITION_EXPRESSION);
}
}
self.my_builder.restore_newlines_state();
}
pub(crate) fn parse_when_entry_guard_or_suggest(&mut self) {
if self.at(ANDAND) {
self.error_until(
"Unexpected '&&', use 'if' to introduce additional conditions; see https://kotl.in/guards-in-when",
TokenSet::create(&[LBRACE, RBRACE, ARROW]),
);
} else if self.at(IF_KEYWORD) {
self.parse_when_entry_guard();
}
}
pub(crate) fn parse_when_entry_guard(&mut self) {
debug_assert!(self._at(IF_KEYWORD));
let guard = self.mark();
self.advance(); self.parse_expression();
guard.done(self, WHEN_ENTRY_GUARD);
}
}