aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
authornic-gaffney <gaffney_nic@protonmail.com>2023-04-12 20:56:17 -0500
committernic-gaffney <gaffney_nic@protonmail.com>2023-04-12 20:56:17 -0500
commit6449ff2c0582bec9f8289ef643ce867311a18218 (patch)
tree4930e7b8cd5005b23dac358818e16c6a351e500f /crates
parenta6dc77aa4db8aec2593743f058d91d4fe572ab60 (diff)
downloadsloth-6449ff2c0582bec9f8289ef643ce867311a18218.tar.gz
types are done
Diffstat (limited to 'crates')
-rw-r--r--crates/sloth/src/parser/ast.rs4
-rw-r--r--crates/sloth/src/parser/stmt.rs114
2 files changed, 104 insertions, 14 deletions
diff --git a/crates/sloth/src/parser/ast.rs b/crates/sloth/src/parser/ast.rs
index 67bc9da..fb03634 100644
--- a/crates/sloth/src/parser/ast.rs
+++ b/crates/sloth/src/parser/ast.rs
@@ -84,6 +84,10 @@ pub enum Stmt {
value: Expr,
typ: Option<String>,
},
+ AssignVariable {
+ name: String,
+ value: Expr,
+ },
If {
expr: Expr,
body: Vec<Stmt>,
diff --git a/crates/sloth/src/parser/stmt.rs b/crates/sloth/src/parser/stmt.rs
index 94ddec0..6c02f35 100644
--- a/crates/sloth/src/parser/stmt.rs
+++ b/crates/sloth/src/parser/stmt.rs
@@ -59,10 +59,9 @@ impl<'a> AstParser<'a> {
if next == TokenType::Eq {
let value = self.expression();
self.consume(TokenType::SemiColon, "No semi colon for me i guess");
- return Stmt::DefineVariable {
+ return Stmt::AssignVariable {
name: (ident),
value: (value),
- typ: (None),
};
} else if next == TokenType::OpeningParen {
let mut arguments = Vec::<Expr>::new();
@@ -95,7 +94,18 @@ impl<'a> AstParser<'a> {
panic!("Identifier expected after 'var', not {:?}", self.peek());
};
- self.advance(); // Advancing from the identifier TODO: Check for type
+ self.advance();
+
+ let mut typ: Option<String> = None;
+ if self.peek().tt.clone() == TokenType::Colon {
+ self.consume(TokenType::Colon, "How did you even get this error?");
+ let TokenType::Identifier(name) = self.peek().tt.clone() else {
+ panic!("Type expected after identifier, not {:?}", self.peek());
+ };
+ self.advance();
+ typ = Some(name);
+ }
+
self.consume(TokenType::Eq, "Expected '=' after identifier at ");
let value = self.expression();
@@ -105,7 +115,7 @@ impl<'a> AstParser<'a> {
Stmt::DefineVariable {
name: (ident),
value: (value),
- typ: (None),
+ typ: (typ),
}
}
@@ -115,6 +125,17 @@ impl<'a> AstParser<'a> {
};
self.advance(); // Advancing from the identifier
+
+ let mut typ: Option<String> = None;
+ if self.peek().tt.clone() == TokenType::Colon {
+ self.consume(TokenType::Colon, "How did you even get this error?");
+ let TokenType::Identifier(name) = self.peek().tt.clone() else {
+ panic!("Type expected after identifier, not {:?}", self.peek());
+ };
+ self.advance();
+ typ = Some(name);
+ }
+
self.consume(TokenType::Eq, "Expected '=' after identifier");
let value = self.expression();
@@ -124,7 +145,7 @@ impl<'a> AstParser<'a> {
Stmt::DefineValue {
name: (ident),
value: (value),
- typ: (None),
+ typ: (typ),
}
}
@@ -223,15 +244,35 @@ impl<'a> AstParser<'a> {
panic!("Identifier expected after '('");
};
+ let mut typ: Option<String> = None;
+
+ if self.peek().tt.clone() == TokenType::Colon {
+ self.consume(TokenType::Colon, "How did you even get this error?");
+ let TokenType::Identifier(name) = self.peek().tt.clone() else {
+ panic!("Type expected after ':', not {:?}", self.peek());
+ };
+ self.advance();
+ typ = Some(name);
+ }
+
self.advance_if_eq(&TokenType::Comma);
let arg = FuncArgs {
name: (name),
- typ: (None),
+ typ: (typ),
};
args.push(arg);
}
self.advance();
+ let mut typ: Option<String> = None;
+ if self.peek().tt.clone() == TokenType::Arrow {
+ self.advance();
+ let TokenType::Identifier(name) = self.peek().tt.clone() else {
+ panic!("Type expected after ':', not {:?}", self.peek());
+ };
+ typ = Some(name);
+ self.advance();
+ }
self.consume(TokenType::OpeningBrace, "Expected '{' after parameters");
let mut body = Vec::new();
while !self.eof() && self.peek().tt != TokenType::ClosingBrace {
@@ -242,7 +283,7 @@ impl<'a> AstParser<'a> {
ident: (ident),
args: (Some(args)),
body: (body),
- return_type: (None),
+ return_type: (typ),
}
}
@@ -307,7 +348,10 @@ mod tests {
#[test]
fn basic_statement_c() {
- let lexer = Lexer::new("fn test_c (a, b, c) {\nreturn (a + b * c);\n}");
+ let lexer = Lexer::new(
+ "\
+ fn test_c (a, b, c) {\nreturn (a + b * c);\n}",
+ );
let tokens = lexer.collect_vec();
println!("{tokens:?}");
@@ -351,7 +395,10 @@ mod tests {
}
#[test]
fn basic_statement_d() {
- let lexer = Lexer::new("while true {\nprint(\"Hello World\");\n\nprintln(5 + 7/-3);}");
+ let lexer = Lexer::new(
+ "\
+ while true {\nprint(\"Hello World\");\nprintln(5 + 7/-3);\n}",
+ );
let tokens = lexer.collect_vec();
println!("{tokens:?}");
@@ -391,7 +438,8 @@ mod tests {
#[test]
fn basic_statement_e() {
let lexer = Lexer::new(
- "if a+5 > 10 {\nprint(a);\n}\nif a+5 < 10 {\nprintln(10);\n}\nif a+5 == 10 \
+ "\
+ if a+5 > 10 {\nprint(a);\n}\nif a+5 < 10 {\nprintln(10);\n}\nif a+5 == 10 \
{\nprint(toString(10));\na = true;\n}",
);
let tokens = lexer.collect_vec();
@@ -450,10 +498,9 @@ mod tests {
args: vec![Expr::Literal(Literal::Integer(10))],
}]),
}),
- Stmt::DefineVariable {
+ Stmt::AssignVariable {
name: ("a".to_string()),
value: (Expr::Literal(Literal::Bool(true))),
- typ: (None),
},
]),
@@ -476,14 +523,53 @@ mod tests {
let lexer = Lexer::new("test_a = 5 + 3;");
let tokens = lexer.collect_vec();
- let expected_ast = Stmt::DefineVariable {
+ let expected_ast = Stmt::AssignVariable {
name: ("test_a".to_string()),
value: (Expr::BinaryOp {
op: (BinaryOp::Add),
lhs: (Box::new(Expr::Literal(Literal::Integer(5)))),
rhs: (Box::new(Expr::Literal(Literal::Integer(3)))),
}),
- typ: (None),
+ };
+
+ let mut parser = AstParser::new(tokens);
+ let generated_ast = parser.statement();
+
+ println!("Expected AST:\n{expected_ast:#?}\n\n");
+ println!("Generated AST:\n{generated_ast:#?}\n\n");
+
+ assert_eq!(expected_ast, generated_ast);
+ }
+ #[test]
+ fn basic_statement_g() {
+ let lexer = Lexer::new(
+ "\
+ fn times_two(x: int) -> int {\nval y: int = x*2;\nreturn y;\n}",
+ );
+ let tokens = lexer.collect_vec();
+
+ let expected_ast = Stmt::DefineFunction {
+ ident: ("times_two".to_string()),
+ args: (Some(vec![FuncArgs {
+ name: ("x".to_string()),
+ typ: (Some("int".to_string())),
+ }])),
+ body: (vec![
+ Stmt::DefineValue {
+ name: "y".to_string(),
+ value: (Expr::BinaryOp {
+ op: (BinaryOp::Mul),
+ lhs: (Box::new(Expr::Variable("x".to_string()))),
+ rhs: (Box::new(Expr::Literal(Literal::Integer(2)))),
+ }),
+ typ: Some("int".to_string()),
+ },
+ Stmt::Return {
+ value: (Expr::Variable("y".to_string())),
+ },
+ ]),
+
+ return_type: Some("int".to_string()),
};
let mut parser = AstParser::new(tokens);