Parser - Prevent return from being used outside of functions

This commit is contained in:
Emmanuel BENOîT 2023-01-02 20:29:32 +01:00
parent 0edabd4a48
commit 3bd3c31210

View file

@ -440,15 +440,22 @@ impl Parser {
/// return_statement := "return" expression? ";" /// return_statement := "return" expression? ";"
/// ``` /// ```
fn parse_return_statement(&mut self, ret_token: &Token) -> ParserResult<ast::StmtNode> { fn parse_return_statement(&mut self, ret_token: &Token) -> ParserResult<ast::StmtNode> {
let value = if self.check(&TokenType::Semicolon) { if self.can_use_return() {
None let value = if self.check(&TokenType::Semicolon) {
None
} else {
Some(self.parse_expression()?)
};
Ok(ast::StmtNode::Return {
token: ret_token.clone(),
value,
})
} else { } else {
Some(self.parse_expression()?) Err(ParserError::new(
}; ret_token,
Ok(ast::StmtNode::Return { "'return' found outside of function",
token: ret_token.clone(), ))
value, }
})
} }
/// Parse the following rule: /// Parse the following rule:
@ -758,4 +765,17 @@ impl Parser {
} }
false false
} }
/// Check whether the `return` keyword can be used. This is true whenever
/// the first `LoopParsingState::None` found in the loop parsing state is
/// not the one at position 0.
fn can_use_return(&self) -> bool {
let mut pos = self.loop_state.len() - 1;
loop {
if self.loop_state[pos] == LoopParsingState::None {
return pos == 0;
}
pos -= 1;
}
}
} }