diff --git a/trunk_lexer/src/lexer.rs b/trunk_lexer/src/lexer.rs index 03f3e10..eca5601 100644 --- a/trunk_lexer/src/lexer.rs +++ b/trunk_lexer/src/lexer.rs @@ -621,6 +621,7 @@ fn identifier_to_keyword(ident: &str) -> Option { Some(match ident { "abstract" => TokenKind::Abstract, "as" => TokenKind::As, + "break" => TokenKind::Break, "class" => TokenKind::Class, "const" => TokenKind::Const, "declare" => TokenKind::Declare, diff --git a/trunk_parser/src/ast.rs b/trunk_parser/src/ast.rs index 2d58966..1551aac 100644 --- a/trunk_parser/src/ast.rs +++ b/trunk_parser/src/ast.rs @@ -184,6 +184,9 @@ pub enum Statement { Return { value: Option, }, + Break { + num: Option, + }, Echo { values: Vec, }, diff --git a/trunk_parser/src/parser/mod.rs b/trunk_parser/src/parser/mod.rs index 3d2ee64..740ff0e 100644 --- a/trunk_parser/src/parser/mod.rs +++ b/trunk_parser/src/parser/mod.rs @@ -361,6 +361,20 @@ impl Parser { expect!(self, TokenKind::SemiColon, "expected semi-colon at the end of an echo statement"); Statement::Echo { values } }, + TokenKind::Break => { + self.next(); + + let mut num = None; + if self.current.kind != TokenKind::SemiColon { + num = Some(self.expression(0)?); + } + + dbg!(&self.current.kind); + + expect!(self, TokenKind::SemiColon, "expected semi-colon"); + + Statement::Break { num } + }, TokenKind::Return => { self.next(); @@ -982,6 +996,17 @@ mod tests { ]); } + #[test] + fn breaks() { + assert_ast("