| author | |
| committer | |
| log | e909581f4c8edf90471d89f9cce5abd05a457a46 |
| tree | 91283acb578d6f39c8d44aa9ef40f98171667dc1 |
| parent | 266f616b552eb86530ed664e44aea026cb5820db |
7 files changed, 136 insertions(+), 20 deletions(-)
compiler/src/ast/mod.rs+61-16| ... | ... | @@ -8,12 +8,21 @@ use super::tokenizer::Token; |
| 8 | 8 | use error::AstError; |
| 9 | 9 | use types::{Argument, ParserContext}; |
| 10 | 10 | |
| 11 | pub use types::{Ast, Type}; | |
| 11 | pub use types::{Ast, Block, Type}; | |
| 12 | 12 | |
| 13 | 13 | fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> { |
| 14 | 14 | let left = match tokens.next() { |
| 15 | 15 | Some(token) => match token { |
| 16 | 16 | Token::Number(number) => Ast::Number(number.clone()), |
| 17 | Token::String(string) => Ast::String(string.clone()), | |
| 18 | Token::True => Ast::Bool(true), | |
| 19 | Token::False => Ast::Bool(false), | |
| 20 | Token::OpenBracket => { | |
| 21 | // FRICK we consumed the open bracket | |
| 22 | // we need to put the cursor back | |
| 23 | tokens.cursor -= 1; | |
| 24 | Ast::Block(parse_block(tokens)?) | |
| 25 | } | |
| 17 | 26 | Token::Identifier(name) => match tokens.peek() { |
| 18 | 27 | Some(Token::OpenParanthesis) => { |
| 19 | 28 | tokens.next(); |
| ... | ... | @@ -74,12 +83,60 @@ fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> { |
| 74 | 83 | Ok(left) |
| 75 | 84 | } |
| 76 | 85 | |
| 86 | fn parse_block(tokens: &mut ParserContext) -> Result<Block> { | |
| 87 | match tokens.next() { | |
| 88 | Some(Token::OpenBracket) => (), | |
| 89 | _ => return Err(AstError::new("Expected { when parsing block").into()), | |
| 90 | } | |
| 91 | ||
| 92 | let mut value = Vec::new(); | |
| 93 | let mut implicit_return = false; | |
| 94 | ||
| 95 | loop { | |
| 96 | match tokens.peek() { | |
| 97 | Some(Token::ClosedBracket) => { | |
| 98 | tokens.next(); | |
| 99 | break; | |
| 100 | } | |
| 101 | _ => (), | |
| 102 | } | |
| 103 | ||
| 104 | let current_cursor = tokens.cursor; | |
| 105 | let result = parse_statement(tokens); | |
| 106 | ||
| 107 | match result { | |
| 108 | Ok(ast) => value.push(ast), | |
| 109 | Err(_) => { | |
| 110 | tokens.cursor = current_cursor; | |
| 111 | value.push(parse_expression(tokens)?); | |
| 112 | implicit_return = true; | |
| 113 | match tokens.peek() { | |
| 114 | Some(Token::ClosedBracket) => (), | |
| 115 | _ => { | |
| 116 | return Err(AstError::new( | |
| 117 | "Expected closed bracket after expression in function body", | |
| 118 | ) | |
| 119 | .into()); | |
| 120 | } | |
| 121 | } | |
| 122 | } | |
| 123 | } | |
| 124 | } | |
| 125 | ||
| 126 | Ok(Block { | |
| 127 | value, | |
| 128 | implicit_return, | |
| 129 | }) | |
| 130 | } | |
| 131 | ||
| 77 | 132 | fn parse_type(tokens: &mut ParserContext) -> Result<Type> { |
| 78 | 133 | match tokens.next() { |
| 79 | 134 | Some(Token::Identifier(typ)) => match typ.as_str() { |
| 80 | 135 | "int" => Ok(Type::Int), |
| 81 | 136 | "float" => Ok(Type::Float), |
| 82 | 137 | "bigint" => Ok(Type::Bigint), |
| 138 | "bool" => Ok(Type::Bool), | |
| 139 | "string" => Ok(Type::String), | |
| 83 | 140 | _ => return Err(AstError::new("Expected type").into()), |
| 84 | 141 | }, |
| 85 | 142 | _ => return Err(AstError::new("Expected type").into()), |
| ... | ... | @@ -233,7 +290,7 @@ fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> { |
| 233 | 290 | } |
| 234 | 291 | }; |
| 235 | 292 | |
| 236 | match tokens.next() { | |
| 293 | match tokens.peek() { | |
| 237 | 294 | Some(Token::OpenBracket) => (), |
| 238 | 295 | _ => { |
| 239 | 296 | return Err(AstError::new( |
| ... | ... | @@ -243,25 +300,13 @@ fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> { |
| 243 | 300 | } |
| 244 | 301 | }; |
| 245 | 302 | |
| 246 | let mut value = Vec::new(); | |
| 247 | ||
| 248 | loop { | |
| 249 | match tokens.peek() { | |
| 250 | Some(Token::ClosedBracket) => { | |
| 251 | tokens.next(); | |
| 252 | break; | |
| 253 | } | |
| 254 | _ => (), | |
| 255 | } | |
| 256 | ||
| 257 | value.push(parse_statement(tokens)?); | |
| 258 | } | |
| 303 | let block = parse_block(tokens)?; | |
| 259 | 304 | |
| 260 | 305 | return Ok(Ast::Function { |
| 261 | 306 | name, |
| 262 | 307 | arguments, |
| 263 | 308 | return_type, |
| 264 | value, | |
| 309 | block | |
| 265 | 310 | }); |
| 266 | 311 | } |
| 267 | 312 | Token::Identifier(name) => match tokens.peek() { |
compiler/src/ast/types.rs+14-1| ... | ... | @@ -1,3 +1,5 @@ |
| 1 | // TODO(lino-levan): Split up AST into expressions, statements, etc. | |
| 2 | ||
| 1 | 3 | use crate::tokenizer::Token; |
| 2 | 4 | use crate::util::Operator; |
| 3 | 5 | |
| ... | ... | @@ -40,6 +42,14 @@ pub enum Type { |
| 40 | 42 | Int, |
| 41 | 43 | Float, |
| 42 | 44 | Bigint, |
| 45 | Bool, | |
| 46 | String, | |
| 47 | } | |
| 48 | ||
| 49 | #[derive(Debug)] | |
| 50 | pub struct Block { | |
| 51 | pub value: Vec<Ast>, | |
| 52 | pub implicit_return: bool, | |
| 43 | 53 | } |
| 44 | 54 | |
| 45 | 55 | #[derive(Debug)] |
| ... | ... | @@ -75,13 +85,16 @@ pub enum Ast { |
| 75 | 85 | name: String, |
| 76 | 86 | arguments: Vec<Argument>, |
| 77 | 87 | return_type: Type, |
| 78 | value: Vec<Ast>, | |
| 88 | block: Block | |
| 79 | 89 | }, |
| 80 | 90 | FunctionCall { |
| 81 | 91 | name: String, |
| 82 | 92 | arguments: Vec<Ast>, |
| 83 | 93 | }, |
| 94 | Block(Block), | |
| 84 | 95 | Number(String), |
| 96 | Bool(bool), | |
| 97 | String(String), | |
| 85 | 98 | Identifier(String), |
| 86 | 99 | Comment(String), |
| 87 | 100 | DocComment(String), |
compiler/src/tokenizer.rs+24| ... | ... | @@ -15,12 +15,17 @@ pub enum Token { |
| 15 | 15 | // Literals |
| 16 | 16 | Identifier(String), |
| 17 | 17 | Number(String), |
| 18 | String(String), | |
| 18 | 19 | // Comments |
| 19 | 20 | Comment(String), |
| 20 | 21 | DocComment(String), |
| 21 | 22 | // Keywords |
| 23 | True, | |
| 24 | False, | |
| 22 | 25 | Let, |
| 23 | 26 | Var, |
| 27 | If, | |
| 28 | Else, | |
| 24 | 29 | Return, |
| 25 | 30 | Pub, |
| 26 | 31 | Function, |
| ... | ... | @@ -65,12 +70,31 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> { |
| 65 | 70 | match current_token.as_str() { |
| 66 | 71 | "var" => tokens.push(Token::Var), |
| 67 | 72 | "let" => tokens.push(Token::Let), |
| 73 | "if" => tokens.push(Token::If), | |
| 74 | "else" => tokens.push(Token::Else), | |
| 68 | 75 | "pub" => tokens.push(Token::Pub), |
| 69 | 76 | "fn" => tokens.push(Token::Function), |
| 70 | 77 | "return" => tokens.push(Token::Return), |
| 78 | "true" => tokens.push(Token::True), | |
| 79 | "false" => tokens.push(Token::False), | |
| 71 | 80 | _ => tokens.push(Token::Identifier(current_token)), |
| 72 | 81 | } |
| 73 | 82 | } |
| 83 | '"' => { | |
| 84 | let mut current_token = String::new(); | |
| 85 | loop { | |
| 86 | let c = chars.next(); | |
| 87 | if c.is_none() { | |
| 88 | break; | |
| 89 | } | |
| 90 | let (_, c) = c.unwrap(); | |
| 91 | match c { | |
| 92 | '"' => break, | |
| 93 | _ => current_token.push(c), | |
| 94 | } | |
| 95 | } | |
| 96 | tokens.push(Token::String(current_token)); | |
| 97 | } | |
| 74 | 98 | '0'..='9' => { |
| 75 | 99 | let mut current_token = String::new(); |
| 76 | 100 | current_token.push(c); |
compiler/src/walker.rs+22-2| ... | ... | @@ -6,6 +6,8 @@ fn transpile_helper(tree: &Ast) -> Result<String> { |
| 6 | 6 | Ok(match tree { |
| 7 | 7 | Ast::Number(number) => format!("{}", number), |
| 8 | 8 | Ast::Identifier(name) => format!("{}", name), |
| 9 | Ast::Bool(value) => format!("{}", value), | |
| 10 | Ast::String(value) => format!("\"{}\"", value), | |
| 9 | 11 | Ast::Comment(comment) => format!("// {}\n", comment), |
| 10 | 12 | Ast::DocComment(comment) => format!("/** {} */\n", comment), |
| 11 | 13 | Ast::Operation { |
| ... | ... | @@ -40,7 +42,7 @@ fn transpile_helper(tree: &Ast) -> Result<String> { |
| 40 | 42 | name, |
| 41 | 43 | arguments, |
| 42 | 44 | return_type: _, |
| 43 | value, | |
| 45 | block | |
| 44 | 46 | } => { |
| 45 | 47 | let mut result = format!("function {}(", name); |
| 46 | 48 | |
| ... | ... | @@ -54,7 +56,11 @@ fn transpile_helper(tree: &Ast) -> Result<String> { |
| 54 | 56 | |
| 55 | 57 | result += ") {\n"; |
| 56 | 58 | |
| 57 | for statement in value { | |
| 59 | for (i, statement) in block.value.iter().enumerate() { | |
| 60 | if block.implicit_return && i == block.value.len() - 1 { | |
| 61 | result += format!("return {};\n", transpile_helper(statement)?).as_str(); | |
| 62 | break; | |
| 63 | } | |
| 58 | 64 | result += transpile_helper(statement)?.as_str(); |
| 59 | 65 | } |
| 60 | 66 | |
| ... | ... | @@ -78,6 +84,20 @@ fn transpile_helper(tree: &Ast) -> Result<String> { |
| 78 | 84 | |
| 79 | 85 | result += ")"; |
| 80 | 86 | |
| 87 | result | |
| 88 | } | |
| 89 | Ast::Block(block) => { | |
| 90 | let mut result = String::from("(()=>{"); | |
| 91 | for (i, statement) in block.value.iter().enumerate() { | |
| 92 | if block.implicit_return && i == block.value.len() - 1 { | |
| 93 | result += format!("return {};\n", transpile_helper(statement)?).as_str(); | |
| 94 | break; | |
| 95 | } | |
| 96 | result += transpile_helper(statement)?.as_str(); | |
| 97 | } | |
| 98 | ||
| 99 | result += "})()\n"; | |
| 100 | ||
| 81 | 101 | result |
| 82 | 102 | } |
| 83 | 103 | }) |
examples/basics/control.blight+4| ... | ... | @@ -1 +1,5 @@ |
| 1 | let x: bool = true; | |
| 1 | 2 | |
| 3 | if x { | |
| 4 | print("x is true!"); | |
| 5 | } |
examples/basics/expressions.blight created+10| ... | ... | @@ -0,0 +1,10 @@ |
| 1 | // everything is an expression in blight | |
| 2 | // everything. | |
| 3 | // hehe | |
| 4 | ||
| 5 | let x: int = 5 + { | |
| 6 | let y: int = 5; | |
| 7 | y | |
| 8 | }; | |
| 9 | ||
| 10 | print(x); // 10 |
examples/basics/functions.blight+1-1| ... | ... | @@ -1,5 +1,5 @@ |
| 1 | 1 | fn bingus(x: int, y: int) -> int { |
| 2 | return x * y; | |
| 2 | x * y | |
| 3 | 3 | } |
| 4 | 4 | |
| 5 | 5 | let result: int = bingus(10, 25); |