Browse Source

feat: break and continue

github-actions
Garrit Franke 1 year ago
parent
commit
94a3e34776
  1. 2
      TODO
  2. 11
      examples/playground.sb
  3. 2
      src/generator/c.rs
  4. 10
      src/generator/js.rs
  5. 2
      src/lexer/mod.rs
  6. 2
      src/parser/node_type.rs
  7. 12
      src/parser/rules.rs
  8. 40
      src/parser/tests.rs

2
TODO

@ -1,4 +1,5 @@
# Bugs
- Generated nested expressions should include braces
# Cleanups
- Improve error reporting (See ./util/string_util::highlight_position_in_file)
@ -7,7 +8,6 @@
# Features
- Nested arrays like [[1, 2, 3], [1, 2, 3]]
- Break and Continue keywords
- Type inference
- Multi-file support
- Argument overloading

11
examples/playground.sb

@ -1,4 +1,11 @@
fn main() {
let x = (1 + 2 * (3 + 2))
println(x)
let arr = [1, 2, 3]
for x in arr {
if x == 2 {
break
} else {
println(x)
}
}
}

2
src/generator/c.rs

@ -115,6 +115,8 @@ fn generate_statement(statement: Statement) -> String {
Statement::Block(_) => generate_block(statement),
Statement::While(expr, body) => generate_while_loop(expr, *body),
Statement::For(ident, expr, body) => todo!(),
Statement::Continue => todo!(),
Statement::Break => todo!(),
};
format!("{}\n", state)

10
src/generator/js.rs

@ -90,6 +90,8 @@ fn generate_statement(statement: Statement) -> String {
Statement::Block(_) => generate_block(statement, None),
Statement::While(expr, body) => generate_while_loop(expr, *body),
Statement::For(ident, expr, body) => generate_for_loop(ident, expr, *body),
Statement::Continue => generate_continue(),
Statement::Break => generate_break(),
};
format!("{};\n", state)
@ -140,6 +142,14 @@ fn generate_for_loop(ident: Variable, expr: Expression, body: Statement) -> Stri
out_str
}
fn generate_break() -> String {
"break;\n".into()
}
fn generate_continue() -> String {
"continue;\n".into()
}
fn generate_array(elements: Vec<Expression>) -> String {
let mut out_str = String::from("[");

2
src/lexer/mod.rs

@ -335,6 +335,8 @@ impl Cursor<'_> {
c if c == "while" => Keyword::While,
c if c == "for" => Keyword::For,
c if c == "in" => Keyword::In,
c if c == "break" => Keyword::Break,
c if c == "continue" => Keyword::Continue,
_ => Keyword::Unknown,
}
}

2
src/parser/node_type.rs

@ -72,6 +72,8 @@ pub enum Statement {
If(Expression, Box<Statement>, Option<Box<Statement>>),
While(Expression, Box<Statement>),
For(Variable, Expression, Box<Statement>),
Break,
Continue,
Exp(Expression),
}

12
src/parser/rules.rs

@ -122,6 +122,8 @@ impl Parser {
TokenKind::Keyword(Keyword::Return) => self.parse_return(),
TokenKind::Keyword(Keyword::If) => self.parse_conditional_statement(),
TokenKind::Keyword(Keyword::While) => self.parse_while_loop(),
TokenKind::Keyword(Keyword::Break) => self.parse_break(),
TokenKind::Keyword(Keyword::Continue) => self.parse_continue(),
TokenKind::Keyword(Keyword::For) => self.parse_for_loop(),
TokenKind::Identifier(_) => {
let ident = self.match_identifier()?;
@ -305,6 +307,16 @@ impl Parser {
Ok(Statement::While(expr, Box::new(body)))
}
fn parse_break(&mut self) -> Result<Statement, String> {
self.match_keyword(Keyword::Break)?;
Ok(Statement::Break)
}
fn parse_continue(&mut self) -> Result<Statement, String> {
self.match_keyword(Keyword::Continue)?;
Ok(Statement::Continue)
}
fn parse_for_loop(&mut self) -> Result<Statement, String> {
self.match_keyword(Keyword::For)?;

40
src/parser/tests.rs

@ -706,3 +706,43 @@ fn test_simple_nested_expression() {
let tree = parse(tokens, Some(raw.to_string()));
assert!(tree.is_ok());
}
#[test]
fn test_continue() {
let raw = "
fn main() {
let arr = [1, 2, 3]
for x in arr {
if x == 2 {
continue
} else {
println(x)
}
}
}
";
let tokens = tokenize(raw);
let tree = parse(tokens, Some(raw.to_string()));
assert!(tree.is_ok());
}
#[test]
fn test_break() {
let raw = "
fn main() {
let arr = [1, 2, 3]
for x in arr {
if x == 2 {
break
} else {
println(x)
}
}
}
";
let tokens = tokenize(raw);
let tree = parse(tokens, Some(raw.to_string()));
assert!(tree.is_ok());
}

Loading…
Cancel
Save