use super::*;
use crate::state::ScopeContext;
impl<'input, D: Diagnostics, C: ConcreteSyntaxTreeBuilder> ParserState<'input, D, C> {
pub(super) fn parse_break_stmt(&mut self) {
self.start_node(SyntaxKind::LoopBreak);
let is_in_loop = self.is_directly_in_ctx(ScopeContext::Loop);
if !is_in_loop {
let diagnostic_details = self.diagnostic_details();
let error = ParseError::invalid_use_of_break_stmt();
self.emit_diagnostic(error, diagnostic_details);
}
self.parse_token(SyntaxKind::Keyword);
self.skip_trivia();
self.parse_optional_expression();
self.finish_node();
}
pub(super) fn parse_continue_stmt(&mut self) {
self.start_node(SyntaxKind::LoopContinue);
let is_in_loop = self.is_directly_in_ctx(ScopeContext::Loop);
if !is_in_loop {
let diagnostic_details = self.diagnostic_details();
let error = ParseError::invalid_use_of_continue_stmt();
self.emit_diagnostic(error, diagnostic_details);
}
self.parse_token(SyntaxKind::Keyword);
self.finish_node();
}
pub(super) fn parse_return_stmt(&mut self) {
self.start_node(SyntaxKind::Return);
self.parse_token(SyntaxKind::Keyword);
self.skip_trivia();
self.parse_optional_expression();
self.finish_node();
}
}
mod test {
#[test]
fn test_break() {
crate::test::create_parsing_test("break/*.skull", |state| {
state.parse_break_stmt();
});
}
#[test]
fn test_continue() {
crate::test::create_parsing_test("continue/*.skull", |state| {
state.parse_expression();
});
}
#[test]
fn test_return() {
crate::test::create_parsing_test("return/*.skull", |state| {
state.parse_return_stmt();
});
}
}