Browse Source

Add variable assignment

github-actions
Garrit Franke 3 years ago
parent
commit
0d213f33e9
  1. 3
      examples/playground.sb
  2. 7
      src/generator/js.rs
  3. 2
      src/parser/node_type.rs
  4. 17
      src/parser/rules.rs
  5. 14
      src/parser/tests.rs

3
examples/playground.sb

@ -1,4 +1,5 @@
fn main() {
let x = 10
return x + 10
x = 5
return x
}

7
src/generator/js.rs

@ -72,6 +72,7 @@ fn generate_statement(statement: Statement) -> String {
Statement::If(expr, if_state, else_state) => {
generate_conditional(expr, *if_state, else_state.map(|x| *x))
}
Statement::Assign(name, state) => generate_assign(name, *state),
Statement::Block(_) => generate_block(statement),
Statement::While(expr, body) => generate_while_loop(expr, *body),
}
@ -84,7 +85,6 @@ fn generate_expression(expr: Expression) -> String {
Expression::Char(_) => todo!(),
Expression::Bool(b) => b.to_string(),
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),
}
@ -161,7 +161,6 @@ fn generate_function_call(func: String, args: Vec<Expression>) -> String {
Expression::Bool(v) => v.to_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),
})
@ -200,3 +199,7 @@ fn generate_bin_op(left: Expression, op: BinOp, right: Expression) -> String {
r = generate_expression(right)
)
}
fn generate_assign(name: String, expr: Expression) -> String {
format!("{} = {};\n", name, generate_expression(expr))
}

2
src/parser/node_type.rs

@ -38,6 +38,7 @@ pub struct Variable {
pub enum Statement {
Block(Vec<Statement>),
Declare(Variable, Option<Expression>),
Assign(String, Box<Expression>),
Return(Option<Expression>),
If(Expression, Box<Statement>, Option<Box<Statement>>),
While(Expression, Box<Statement>),
@ -53,7 +54,6 @@ pub enum Expression {
Array(Vec<Expression>),
FunctionCall(String, Vec<Expression>),
Variable(String),
Assign(String, Box<Expression>),
BinOp(Box<Expression>, BinOp, Box<Expression>),
}

17
src/parser/rules.rs

@ -97,9 +97,13 @@ impl Parser {
TokenKind::Keyword(Keyword::While) => self.parse_while_loop(),
TokenKind::Identifier(_) => {
let ident = self.match_identifier()?;
if let Ok(_) = self.peek_token(TokenKind::BraceOpen) {
let state = self.parse_function_call(Some(ident))?;
Ok(Statement::Exp(state))
} else if let Ok(_) = self.peek_token(TokenKind::Assign) {
let state = self.parse_assignent(Some(ident))?;
Ok(state)
} else {
let state = Statement::Exp(Expression::Variable(ident.into()));
Ok(state)
@ -309,4 +313,17 @@ impl Parser {
other => Err(format!("Expected identifier, found {:?}", other)),
}
}
fn parse_assignent(&mut self, name: Option<String>) -> Result<Statement, String> {
let name = match name {
Some(name) => name,
None => self.match_identifier()?,
};
self.match_token(TokenKind::Assign)?;
let expr = self.parse_expression()?;
Ok(Statement::Assign(name, Box::new(expr)))
}
}

14
src/parser/tests.rs

@ -89,6 +89,20 @@ fn test_parse_variable_declaration() {
assert!(tree.is_ok())
}
#[test]
fn test_parse_variable_reassignment() {
let raw = "
fn main() {
let x = 1
x = x + 1
return x
}
";
let tokens = tokenize(raw);
let tree = parse(tokens, Some(raw.to_string()));
assert!(tree.is_ok())
}
#[test]
fn test_parse_variable_declaration_added() {
let raw = "

Loading…
Cancel
Save