Browse Source

Add integer arrays

github-actions
Garrit Franke 3 years ago
parent
commit
03c71987cd
  1. 14
      examples/playground.sb
  2. 19
      src/generator/js.rs
  3. 23
      src/parser/mod.rs
  4. 1
      src/parser/node_type.rs
  5. 26
      src/parser/tests.rs

14
examples/playground.sb

@ -1,17 +1,5 @@
// There are no nested expressions yet, so we have to hack a little bit
fn main() {
let year = 2020
let divisibleBy4 = year % 4 == 0
let divisibleBy100 = year % 100 != 0
let divisibleBy400 = year % 400 == 0
let ly = divisibleBy4 && divisibleBy100
if ly || divisibleBy400 {
return "Leap year"
} else {
return "Not a leap year"
}
let arr = ["Foo", "Bar", "Baz"]
}

19
src/generator/js.rs

@ -84,10 +84,28 @@ fn generate_expression(expr: Expression) -> String {
Expression::Char(_) => todo!(),
Expression::FunctionCall(name, e) => generate_function_call(name, e),
Expression::Assign(_, _) => todo!(),
Expression::Array(els) => generate_array(els),
Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right),
}
}
fn generate_array(elements: Vec<Expression>) -> String {
let mut out_str = String::from("[");
out_str += &elements
.iter()
.map(|el| match el {
Expression::Int(x) => x.to_string(),
Expression::Str(x) => x.to_string(),
_ => todo!("Not yet implemented"),
})
.collect::<Vec<String>>()
.join(", ");
out_str += "]";
out_str
}
fn generate_conditional(
expr: Expression,
if_state: Statement,
@ -133,6 +151,7 @@ fn generate_function_call(func: String, args: Vec<Expression>) -> String {
Expression::FunctionCall(n, a) => generate_function_call(n, a),
Expression::Str(s) | Expression::Variable(s) => s,
Expression::Assign(_, _) => todo!(),
Expression::Array(_) => todo!(),
Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right),
})
.collect::<Vec<String>>()

23
src/parser/mod.rs

@ -320,10 +320,33 @@ impl Parser {
};
Ok(state)
}
TokenKind::SquareBraceOpen => self.parse_array(),
other => Err(format!("Expected Expression, found {:?}", other)),
}
}
fn parse_array(&mut self) -> Result<Expression, String> {
let mut elements = Vec::new();
loop {
let next = self.next().ok_or_else(|| "Expected identifier")?;
match next.kind {
TokenKind::Literal(Value::Int) => {
let value = next.raw.parse::<u32>().map_err(|e| e.to_string())?;
elements.push(Expression::Int(value));
}
_ => return Err(self.make_error(TokenKind::Identifier("Argument".into()), next)),
};
if self.peek_token(TokenKind::SquareBraceClose).is_ok() {
break;
}
self.match_token(TokenKind::Comma)?;
}
self.match_token(TokenKind::SquareBraceClose)?;
Ok(Expression::Array(elements))
}
fn parse_conditional_statement(&mut self) -> Result<Statement, String> {
self.match_keyword(Keyword::If)?;
let condition = self.parse_expression()?;

1
src/parser/node_type.rs

@ -49,6 +49,7 @@ pub enum Expression {
Int(u32),
Str(String),
Char(u8),
Array(Vec<Expression>),
FunctionCall(String, Vec<Expression>),
Variable(String),
Assign(String, Box<Expression>),

26
src/parser/tests.rs

@ -351,3 +351,29 @@ fn test_parse_conditional_elseif_else_branch() {
let tree = parse(tokens, Some(raw.to_string()));
assert!(tree.is_ok())
}
#[test]
fn test_int_array() {
let raw = "
fn main(n) {
let arr = [1, 2, 3]
return arr
}
";
let tokens = tokenize(raw);
let tree = parse(tokens, Some(raw.to_string()));
assert!(tree.is_ok())
}
#[test]
#[ignore]
fn test_string_array() {
let raw = "
fn main(n) {
return [\"Foo\", \"Bar\", \"Baz\"]
}
";
let tokens = tokenize(raw);
let tree = parse(tokens, Some(raw.to_string()));
assert!(tree.is_ok())
}

Loading…
Cancel
Save