Browse Source

Add while loop

github-actions
Garrit Franke 3 years ago
parent
commit
f43aa36432
  1. 1
      README.md
  2. 4
      TODO
  3. 7
      examples/playground.sb
  4. 11
      src/generator/js.rs
  5. 4
      src/lexer/mod.rs
  6. 9
      src/parser/rules.rs
  7. 15
      src/parser/tests.rs

1
README.md

@ -1,6 +1,7 @@
# The Sabre Programming language # The Sabre Programming language
[![builds.sr.ht status](https://builds.sr.ht/~garritfra/sabre/commits/ci.yml.svg)](https://builds.sr.ht/~garritfra/sabre/commits/ci.yml?) [![builds.sr.ht status](https://builds.sr.ht/~garritfra/sabre/commits/ci.yml.svg)](https://builds.sr.ht/~garritfra/sabre/commits/ci.yml?)
[![docs](https://img.shields.io/badge/docs-mdBook-blue.svg)](https://garritfra.github.io/sabre/latest)
Sabre is a bullshit-free (©) programming language that gets out of your way. Sabre is a bullshit-free (©) programming language that gets out of your way.
It is meant to "just work", without adding unnecessary and bloated language features. It is meant to "just work", without adding unnecessary and bloated language features.

4
TODO

@ -2,8 +2,8 @@
# Features # Features
- Add CLI - Variable reassignment
- Add else/if else branch to conditionals - Array access syntax
- Add while loop - Add while loop
- Add for loop - Add for loop
- Add type system - Add type system

7
examples/playground.sb

@ -1,5 +1,6 @@
// There are no nested expressions yet, so we have to hack a little bit
fn main() { fn main() {
let arr = ["Foo", "Bar", "Baz"] let x = 5 * 2
while x > 0 {
return x
}
} }

11
src/generator/js.rs

@ -73,7 +73,7 @@ fn generate_statement(statement: Statement) -> String {
generate_conditional(expr, *if_state, else_state.map(|x| *x)) generate_conditional(expr, *if_state, else_state.map(|x| *x))
} }
Statement::Block(_) => generate_block(statement), Statement::Block(_) => generate_block(statement),
Statement::While(_, _) => todo!(), Statement::While(expr, body) => generate_while_loop(expr, *body),
} }
} }
@ -89,6 +89,15 @@ fn generate_expression(expr: Expression) -> String {
} }
} }
fn generate_while_loop(expr: Expression, body: Statement) -> String {
let mut out_str = String::from("while (");
out_str += &generate_expression(expr);
out_str += ") ";
out_str += &generate_block(body);
out_str
}
fn generate_array(elements: Vec<Expression>) -> String { fn generate_array(elements: Vec<Expression>) -> String {
let mut out_str = String::from("["); let mut out_str = String::from("[");

4
src/lexer/mod.rs

@ -126,6 +126,9 @@ pub enum Keyword {
If, If,
Else, Else,
Return, Return,
While,
Break,
Continue,
Function, Function,
Boolean, Boolean,
Unknown, Unknown,
@ -323,6 +326,7 @@ impl Cursor<'_> {
c if c == "true" || c == "false" => Keyword::Boolean, c if c == "true" || c == "false" => Keyword::Boolean,
c if c == "let" => Keyword::Let, c if c == "let" => Keyword::Let,
c if c == "return" => Keyword::Return, c if c == "return" => Keyword::Return,
c if c == "while" => Keyword::While,
_ => Keyword::Unknown, _ => Keyword::Unknown,
} }
} }

9
src/parser/rules.rs

@ -94,6 +94,7 @@ impl Parser {
TokenKind::Keyword(Keyword::Let) => self.parse_declare(), TokenKind::Keyword(Keyword::Let) => self.parse_declare(),
TokenKind::Keyword(Keyword::Return) => self.parse_return(), TokenKind::Keyword(Keyword::Return) => self.parse_return(),
TokenKind::Keyword(Keyword::If) => self.parse_conditional_statement(), TokenKind::Keyword(Keyword::If) => self.parse_conditional_statement(),
TokenKind::Keyword(Keyword::While) => self.parse_while_loop(),
TokenKind::Identifier(_) => { TokenKind::Identifier(_) => {
let ident = self.match_identifier()?; let ident = self.match_identifier()?;
if let Ok(_) = self.peek_token(TokenKind::BraceOpen) { if let Ok(_) = self.peek_token(TokenKind::BraceOpen) {
@ -217,6 +218,14 @@ impl Parser {
Ok(Expression::Array(elements)) Ok(Expression::Array(elements))
} }
fn parse_while_loop(&mut self) -> Result<Statement, String> {
self.match_keyword(Keyword::While)?;
let expr = self.parse_expression()?;
let body = self.parse_block()?;
Ok(Statement::While(expr, Box::new(body)))
}
fn parse_conditional_statement(&mut self) -> Result<Statement, String> { fn parse_conditional_statement(&mut self) -> Result<Statement, String> {
self.match_keyword(Keyword::If)?; self.match_keyword(Keyword::If)?;
let condition = self.parse_expression()?; let condition = self.parse_expression()?;

15
src/parser/tests.rs

@ -376,3 +376,18 @@ fn test_string_array() {
let tree = parse(tokens, Some(raw.to_string())); let tree = parse(tokens, Some(raw.to_string()));
assert!(tree.is_ok()) assert!(tree.is_ok())
} }
#[test]
fn test_basic_while_loop() {
let raw = "
fn main() {
let x = 5 * 2
while x > 0 {
return x
}
}
";
let tokens = tokenize(raw);
let tree = parse(tokens, Some(raw.to_string()));
assert!(tree.is_ok())
}

Loading…
Cancel
Save