authorgravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-01-16 17:42:56-08:00
committergravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-01-16 17:42:56-08:00
logb893e32685ff6a5115a0723b9ebf142578c73416
tree3eaa98e1365dc32efe617d74720dbadbd72bcc0d
parent9d2554595be36b91e8e1e1fde30a4cf993cfab19

chore: split up ast gen


12 files changed, 535 insertions(+), 368 deletions(-)

compiler/src/ast/mod.rs+7-362
...@@ -1,374 +1,19 @@...@@ -1,374 +1,19 @@
1use miette::Result;1use miette::Result;
22
3mod error;3mod error;
4mod parse_block;
5mod parse_expression;
6mod parse_statement;
7mod parse_type;
4mod types;8mod types;
59
6use super::tokenizer::Token;10pub use super::tokenizer::Token;
711
8use error::AstError;12use parse_statement::parse_statement;
9use types::{Argument, ParserContext};13use types::ParserContext;
1014
11pub use types::{Ast, Block, Type};15pub use types::{Ast, Block, Type};
1216
13fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
14 let left = match tokens.next() {
15 Some(token) => match token {
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 }
26 Token::Identifier(name) => match tokens.peek() {
27 Some(Token::OpenParanthesis) => {
28 tokens.next();
29
30 let mut arguments = Vec::new();
31
32 loop {
33 match tokens.peek() {
34 Some(Token::ClosedParanthesis) => {
35 tokens.next();
36 break;
37 }
38 _ => (),
39 }
40 arguments.push(parse_expression(tokens)?);
41
42 match tokens.peek() {
43 Some(Token::Comma) => {
44 tokens.next();
45 }
46 Some(Token::ClosedParanthesis) => (),
47 _ => {
48 return Err(AstError::new(
49 "Expected ) or , but found something else instead.",
50 )
51 .into())
52 }
53 }
54 }
55
56 Ast::FunctionCall {
57 name: name.clone(),
58 arguments,
59 }
60 }
61 _ => Ast::Identifier(name.clone()),
62 },
63 _ => return Err(AstError::new("Expected expression, but did not get it").into()),
64 },
65 None => return Err(AstError::new("Expected expression, but got nothing instead").into()),
66 };
67
68 match tokens.peek() {
69 Some(token) => match token {
70 Token::Operator(operator) => {
71 tokens.next();
72 return Ok(Ast::Operation {
73 operator: operator.clone(),
74 left: Box::new(left),
75 right: Box::new(parse_expression(tokens)?),
76 });
77 }
78 _ => (),
79 },
80 _ => (),
81 }
82
83 Ok(left)
84}
85
86fn 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
132fn parse_type(tokens: &mut ParserContext) -> Result<Type> {
133 match tokens.next() {
134 Some(Token::Identifier(typ)) => match typ.as_str() {
135 "int" => Ok(Type::Int),
136 "float" => Ok(Type::Float),
137 "bigint" => Ok(Type::Bigint),
138 "bool" => Ok(Type::Bool),
139 "string" => Ok(Type::String),
140 _ => return Err(AstError::new("Expected type").into()),
141 },
142 _ => return Err(AstError::new("Expected type").into()),
143 }
144}
145
146/// Precondition: There is at least one token in the iterator
147fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
148 let token = tokens.next().unwrap();
149 match token {
150 Token::Pub => {
151 match tokens.peek() {
152 Some(Token::Let) | Some(Token::Var) | Some(Token::Function) => (),
153 _ => return Err(AstError::new("Expected let, var, or fn after pub").into()),
154 }
155
156 let inner = parse_statement(tokens)?;
157
158 return Ok(Ast::Public {
159 value: Box::new(inner),
160 });
161 }
162 Token::Let => {
163 let name = match tokens.next() {
164 Some(Token::Identifier(name)) => name,
165 _ => return Err(AstError::new("Expected identifier after var").into()),
166 };
167 let return_type = match tokens.next() {
168 Some(Token::Colon) => parse_type(tokens)?,
169 _ => return Err(AstError::new("Expected colon after identifier").into()),
170 };
171 let value = match tokens.next() {
172 Some(Token::Equals) => parse_expression(tokens)?,
173 _ => return Err(AstError::new("Expected equals after identifier").into()),
174 };
175 match tokens.next() {
176 Some(Token::Semicolon) => (),
177 _ => {
178 return Err(
179 AstError::new("Expected semicolon after variable declaration").into(),
180 )
181 }
182 };
183 Ok(Ast::ConstantDeclaration {
184 name: name.clone(),
185 return_type,
186 value: Box::new(value),
187 })
188 }
189 Token::Var => {
190 let name = match tokens.next() {
191 Some(Token::Identifier(name)) => name,
192 _ => return Err(AstError::new("Expected identifier after var").into()),
193 };
194 let return_type = match tokens.next() {
195 Some(Token::Colon) => parse_type(tokens)?,
196 _ => return Err(AstError::new("Expected colon after identifier").into()),
197 };
198 let value = match tokens.next() {
199 Some(Token::Equals) => parse_expression(tokens)?,
200 _ => return Err(AstError::new("Expected equals after identifier").into()),
201 };
202 match tokens.next() {
203 Some(Token::Semicolon) => (),
204 _ => {
205 return Err(
206 AstError::new("Expected semicolon after variable declaration").into(),
207 )
208 }
209 };
210 Ok(Ast::VariableDeclaration {
211 name: name.clone(),
212 return_type,
213 value: Box::new(value),
214 })
215 }
216 Token::Return => {
217 let expression = parse_expression(tokens)?;
218
219 match tokens.next() {
220 Some(Token::Semicolon) => (),
221 _ => return Err(AstError::new("Expected semicolon after return statement").into()),
222 };
223
224 Ok(Ast::Return {
225 return_value: Box::new(expression),
226 })
227 }
228 Token::Function => {
229 let name = match tokens.next() {
230 Some(Token::Identifier(name)) => name.clone(),
231 _ => return Err(AstError::new("Expected identifier after fn").into()),
232 };
233
234 match tokens.next() {
235 Some(Token::OpenParanthesis) => (),
236 _ => {
237 return Err(AstError::new(
238 "Expected open paranthesis after identifier in function",
239 )
240 .into())
241 }
242 };
243
244 let mut arguments = Vec::new();
245
246 loop {
247 match tokens.peek() {
248 Some(Token::ClosedParanthesis) => {
249 tokens.next();
250 break;
251 }
252 _ => (),
253 }
254
255 let argument_name = match tokens.next() {
256 Some(Token::Identifier(name)) => name,
257 _ => {
258 return Err(AstError::new(
259 "Expected identifier for argument name in function",
260 )
261 .into())
262 }
263 };
264
265 let return_type = match tokens.next() {
266 Some(Token::Colon) => parse_type(tokens)?,
267 _ => return Err(AstError::new("Expected colon after identifier").into()),
268 };
269
270 match tokens.peek() {
271 Some(Token::Comma) => {
272 tokens.next();
273 }
274 _ => (),
275 }
276
277 arguments.push(Argument {
278 name: argument_name.clone(),
279 return_type,
280 })
281 }
282
283 let return_type = match tokens.next() {
284 Some(Token::RightArrow) => parse_type(tokens)?,
285 _ => {
286 return Err(AstError::new(
287 "Expected right arrow after argument list in function",
288 )
289 .into())
290 }
291 };
292
293 match tokens.peek() {
294 Some(Token::OpenBracket) => (),
295 _ => {
296 return Err(AstError::new(
297 "Expected open bracket after type in function declaration",
298 )
299 .into())
300 }
301 };
302
303 let block = parse_block(tokens)?;
304
305 return Ok(Ast::Function {
306 name,
307 arguments,
308 return_type,
309 block,
310 });
311 }
312 Token::Identifier(name) => match tokens.peek() {
313 Some(Token::OpenParanthesis) => {
314 tokens.next();
315
316 let mut arguments = Vec::new();
317
318 loop {
319 match tokens.peek() {
320 Some(Token::ClosedParanthesis) => {
321 tokens.next();
322 break;
323 }
324 _ => (),
325 }
326 arguments.push(parse_expression(tokens)?);
327
328 match tokens.peek() {
329 Some(Token::Comma) => {
330 tokens.next();
331 }
332 Some(Token::ClosedParanthesis) => (),
333 _ => {
334 return Err(AstError::new(
335 "Expected ) or , but found something else instead.",
336 )
337 .into())
338 }
339 }
340 }
341
342 match tokens.next() {
343 Some(Token::Semicolon) => (),
344 _ => return Err(AstError::new("Expected semicolon after function call").into()),
345 };
346
347 Ok(Ast::FunctionCall {
348 name: name.clone(),
349 arguments,
350 })
351 }
352 _ => Err(AstError::new("Unexpected identifier").into()),
353 },
354 Token::Comment(comment) => Ok(Ast::Comment(comment.clone())),
355 Token::DocComment(comment) => {
356 let mut concatted_comments = comment.clone();
357 loop {
358 match tokens.peek() {
359 Some(Token::DocComment(comment)) => {
360 concatted_comments.push_str(format!("\n{}", comment).as_str());
361 tokens.next();
362 }
363 _ => break,
364 }
365 }
366 Ok(Ast::DocComment(concatted_comments))
367 }
368 _ => return Err(AstError::new("Unexpected token").into()),
369 }
370}
371
372pub fn parse(tokens: Vec<Token>) -> Result<Vec<Ast>> {17pub fn parse(tokens: Vec<Token>) -> Result<Vec<Ast>> {
373 let mut ctx = ParserContext::new(tokens);18 let mut ctx = ParserContext::new(tokens);
374 let mut ast: Vec<Ast> = Vec::new();19 let mut ast: Vec<Ast> = Vec::new();
compiler/src/ast/parse_block.rs created+54
...@@ -0,0 +1,54 @@
1use miette::Result;
2
3use super::error::AstError;
4use super::parse_expression::parse_expression;
5use super::parse_statement::parse_statement;
6use super::types::Block;
7use super::types::ParserContext;
8use super::Token;
9
10pub fn parse_block(tokens: &mut ParserContext) -> Result<Block> {
11 match tokens.next() {
12 Some(Token::OpenBracket) => (),
13 _ => return Err(AstError::new("Expected { when parsing block").into()),
14 }
15
16 let mut value = Vec::new();
17 let mut implicit_return = false;
18
19 loop {
20 match tokens.peek() {
21 Some(Token::ClosedBracket) => {
22 tokens.next();
23 break;
24 }
25 _ => (),
26 }
27
28 let current_cursor = tokens.cursor;
29 let result = parse_statement(tokens);
30
31 match result {
32 Ok(ast) => value.push(ast),
33 Err(_) => {
34 tokens.cursor = current_cursor;
35 value.push(parse_expression(tokens)?);
36 implicit_return = true;
37 match tokens.peek() {
38 Some(Token::ClosedBracket) => (),
39 _ => {
40 return Err(AstError::new(
41 "Expected closed bracket after expression in function body",
42 )
43 .into());
44 }
45 }
46 }
47 }
48 }
49
50 Ok(Block {
51 value,
52 implicit_return,
53 })
54}
compiler/src/ast/parse_expression.rs created+116
...@@ -0,0 +1,116 @@
1use miette::Result;
2
3use super::error::AstError;
4use super::parse_block::parse_block;
5use super::types::{Ast, ParserContext};
6use super::Token;
7
8pub fn parse_expression(tokens: &mut ParserContext) -> Result<Ast> {
9 let left = match tokens.next() {
10 Some(token) => match token {
11 Token::Number(number) => Ast::Number(number.clone()),
12 Token::String(string) => Ast::String(string.clone()),
13 Token::True => Ast::Bool(true),
14 Token::False => Ast::Bool(false),
15 Token::OpenBracket => {
16 // FRICK we consumed the open bracket
17 // we need to put the cursor back
18 tokens.back();
19 Ast::Block(parse_block(tokens)?)
20 }
21 Token::If => {
22 let condition = parse_expression(tokens)?;
23
24 let value = parse_block(tokens)?;
25
26 let mut else_value = None;
27
28 match tokens.peek() {
29 Some(Token::Else) => {
30 tokens.next();
31 match tokens.peek() {
32 Option::Some(Token::If) => {
33 else_value = Some(Box::new(parse_expression(tokens)?));
34 }
35 Option::Some(Token::OpenBracket) => {
36 else_value = Some(Box::new(Ast::Block(parse_block(tokens)?)));
37 }
38 _ => {
39 return Err(AstError::new(
40 "Expected if or open bracket after else in if statement",
41 )
42 .into())
43 }
44 }
45 }
46 _ => (),
47 }
48
49 return Ok(Ast::If {
50 condition: Box::new(condition),
51 value,
52 else_value,
53 });
54 }
55 Token::Identifier(name) => match tokens.peek() {
56 Some(Token::OpenParanthesis) => {
57 tokens.next();
58
59 let mut arguments = Vec::new();
60
61 loop {
62 match tokens.peek() {
63 Some(Token::ClosedParanthesis) => {
64 tokens.next();
65 break;
66 }
67 _ => (),
68 }
69 arguments.push(parse_expression(tokens)?);
70
71 match tokens.peek() {
72 Some(Token::Comma) => {
73 tokens.next();
74 }
75 Some(Token::ClosedParanthesis) => (),
76 _ => {
77 return Err(AstError::new(
78 "Expected ) or , but found something else instead.",
79 )
80 .into())
81 }
82 }
83 }
84
85 Ast::FunctionCall {
86 name: name.clone(),
87 arguments,
88 }
89 }
90 _ => Ast::Identifier(name.clone()),
91 },
92 _ => {
93 println!("token: {:?}", token);
94 return Err(AstError::new("Expected expression, but did not get it").into());
95 }
96 },
97 None => return Err(AstError::new("Expected expression, but got nothing instead").into()),
98 };
99
100 match tokens.peek() {
101 Some(token) => match token {
102 Token::Operator(operator) => {
103 tokens.next();
104 return Ok(Ast::Operation {
105 operator: operator.clone(),
106 left: Box::new(left),
107 right: Box::new(parse_expression(tokens)?),
108 });
109 }
110 _ => (),
111 },
112 _ => (),
113 }
114
115 Ok(left)
116}
compiler/src/ast/parse_statement.rs created+268
...@@ -0,0 +1,268 @@
1use miette::Result;
2
3use super::error::AstError;
4use super::parse_block::parse_block;
5use super::parse_expression::parse_expression;
6use super::parse_type::parse_type;
7use super::types::{Argument, Ast, ParserContext};
8use super::Token;
9
10/// Precondition: There is at least one token in the iterator
11pub fn parse_statement(tokens: &mut ParserContext) -> Result<Ast> {
12 let token = tokens.next().unwrap();
13 match token {
14 Token::Pub => {
15 match tokens.peek() {
16 Some(Token::Let) | Some(Token::Var) | Some(Token::Function) => (),
17 _ => return Err(AstError::new("Expected let, var, or fn after pub").into()),
18 }
19
20 let inner = parse_statement(tokens)?;
21
22 return Ok(Ast::Public {
23 value: Box::new(inner),
24 });
25 }
26 Token::Let => {
27 let name = match tokens.next() {
28 Some(Token::Identifier(name)) => name,
29 _ => return Err(AstError::new("Expected identifier after var").into()),
30 };
31 let return_type = match tokens.next() {
32 Some(Token::Colon) => parse_type(tokens)?,
33 _ => return Err(AstError::new("Expected colon after identifier").into()),
34 };
35 let value = match tokens.next() {
36 Some(Token::Equals) => parse_expression(tokens)?,
37 _ => return Err(AstError::new("Expected equals after identifier").into()),
38 };
39 match tokens.next() {
40 Some(Token::Semicolon) => (),
41 _ => {
42 return Err(
43 AstError::new("Expected semicolon after variable declaration").into(),
44 )
45 }
46 };
47 Ok(Ast::ConstantDeclaration {
48 name: name.clone(),
49 return_type,
50 value: Box::new(value),
51 })
52 }
53 Token::Var => {
54 let name = match tokens.next() {
55 Some(Token::Identifier(name)) => name,
56 _ => return Err(AstError::new("Expected identifier after var").into()),
57 };
58 let return_type = match tokens.next() {
59 Some(Token::Colon) => parse_type(tokens)?,
60 _ => return Err(AstError::new("Expected colon after identifier").into()),
61 };
62 let value = match tokens.next() {
63 Some(Token::Equals) => parse_expression(tokens)?,
64 _ => return Err(AstError::new("Expected equals after identifier").into()),
65 };
66 match tokens.next() {
67 Some(Token::Semicolon) => (),
68 _ => {
69 return Err(
70 AstError::new("Expected semicolon after variable declaration").into(),
71 )
72 }
73 };
74 Ok(Ast::VariableDeclaration {
75 name: name.clone(),
76 return_type,
77 value: Box::new(value),
78 })
79 }
80 Token::Return => {
81 let expression = parse_expression(tokens)?;
82
83 match tokens.next() {
84 Some(Token::Semicolon) => (),
85 _ => return Err(AstError::new("Expected semicolon after return statement").into()),
86 };
87
88 Ok(Ast::Return {
89 return_value: Box::new(expression),
90 })
91 }
92 Token::Function => {
93 let name = match tokens.next() {
94 Some(Token::Identifier(name)) => name.clone(),
95 _ => return Err(AstError::new("Expected identifier after fn").into()),
96 };
97
98 match tokens.next() {
99 Some(Token::OpenParanthesis) => (),
100 _ => {
101 return Err(AstError::new(
102 "Expected open paranthesis after identifier in function",
103 )
104 .into())
105 }
106 };
107
108 let mut arguments = Vec::new();
109
110 loop {
111 match tokens.peek() {
112 Some(Token::ClosedParanthesis) => {
113 tokens.next();
114 break;
115 }
116 _ => (),
117 }
118
119 let argument_name = match tokens.next() {
120 Some(Token::Identifier(name)) => name,
121 _ => {
122 return Err(AstError::new(
123 "Expected identifier for argument name in function",
124 )
125 .into())
126 }
127 };
128
129 let return_type = match tokens.next() {
130 Some(Token::Colon) => parse_type(tokens)?,
131 _ => return Err(AstError::new("Expected colon after identifier").into()),
132 };
133
134 match tokens.peek() {
135 Some(Token::Comma) => {
136 tokens.next();
137 }
138 _ => (),
139 }
140
141 arguments.push(Argument {
142 name: argument_name.clone(),
143 return_type,
144 })
145 }
146
147 let return_type = match tokens.next() {
148 Some(Token::RightArrow) => parse_type(tokens)?,
149 _ => {
150 return Err(AstError::new(
151 "Expected right arrow after argument list in function",
152 )
153 .into())
154 }
155 };
156
157 match tokens.peek() {
158 Some(Token::OpenBracket) => (),
159 _ => {
160 return Err(AstError::new(
161 "Expected open bracket after type in function declaration",
162 )
163 .into())
164 }
165 };
166
167 let block = parse_block(tokens)?;
168
169 return Ok(Ast::Function {
170 name,
171 arguments,
172 return_type,
173 block,
174 });
175 }
176 Token::If => {
177 let condition = parse_expression(tokens)?;
178
179 let value = parse_block(tokens)?;
180
181 let mut else_value = None;
182
183 match tokens.peek() {
184 Some(Token::Else) => {
185 tokens.next();
186 match tokens.peek() {
187 Option::Some(Token::If) => {
188 else_value = Some(Box::new(parse_expression(tokens)?));
189 }
190 Option::Some(Token::OpenBracket) => {
191 else_value = Some(Box::new(Ast::Block(parse_block(tokens)?)));
192 }
193 _ => {
194 return Err(AstError::new(
195 "Expected if or open bracket after else in if statement",
196 )
197 .into())
198 }
199 }
200 }
201 _ => (),
202 }
203
204 return Ok(Ast::If {
205 condition: Box::new(condition),
206 value,
207 else_value,
208 });
209 }
210 Token::Identifier(name) => match tokens.peek() {
211 Some(Token::OpenParanthesis) => {
212 tokens.next();
213
214 let mut arguments = Vec::new();
215
216 loop {
217 match tokens.peek() {
218 Some(Token::ClosedParanthesis) => {
219 tokens.next();
220 break;
221 }
222 _ => (),
223 }
224 arguments.push(parse_expression(tokens)?);
225
226 match tokens.peek() {
227 Some(Token::Comma) => {
228 tokens.next();
229 }
230 Some(Token::ClosedParanthesis) => (),
231 _ => {
232 return Err(AstError::new(
233 "Expected ) or , but found something else instead.",
234 )
235 .into())
236 }
237 }
238 }
239
240 match tokens.next() {
241 Some(Token::Semicolon) => (),
242 _ => return Err(AstError::new("Expected semicolon after function call").into()),
243 };
244
245 Ok(Ast::FunctionCall {
246 name: name.clone(),
247 arguments,
248 })
249 }
250 _ => Err(AstError::new("Unexpected identifier").into()),
251 },
252 Token::Comment(comment) => Ok(Ast::Comment(comment.clone())),
253 Token::DocComment(comment) => {
254 let mut concatted_comments = comment.clone();
255 loop {
256 match tokens.peek() {
257 Some(Token::DocComment(comment)) => {
258 concatted_comments.push_str(format!("\n{}", comment).as_str());
259 tokens.next();
260 }
261 _ => break,
262 }
263 }
264 Ok(Ast::DocComment(concatted_comments))
265 }
266 _ => return Err(AstError::new("Unexpected token").into()),
267 }
268}
compiler/src/ast/parse_type.rs created+19
...@@ -0,0 +1,19 @@
1use miette::Result;
2
3use super::error::AstError;
4use super::types::{ParserContext, Type};
5use super::Token;
6
7pub fn parse_type(tokens: &mut ParserContext) -> Result<Type> {
8 match tokens.next() {
9 Some(Token::Identifier(typ)) => match typ.as_str() {
10 "int" => Ok(Type::Int),
11 "float" => Ok(Type::Float),
12 "bigint" => Ok(Type::Bigint),
13 "bool" => Ok(Type::Bool),
14 "string" => Ok(Type::String),
15 _ => return Err(AstError::new("Expected type").into()),
16 },
17 _ => return Err(AstError::new("Expected type").into()),
18 }
19}
compiler/src/ast/types.rs+9
...@@ -18,6 +18,10 @@ impl ParserContext {...@@ -18,6 +18,10 @@ impl ParserContext {
18 self.cursor == self.tokens.len()18 self.cursor == self.tokens.len()
19 }19 }
2020
21 pub fn back(&mut self) {
22 self.cursor -= 1;
23 }
24
21 pub fn next(&mut self) -> Option<Token> {25 pub fn next(&mut self) -> Option<Token> {
22 if self.cursor == self.tokens.len() {26 if self.cursor == self.tokens.len() {
23 return None;27 return None;
...@@ -91,6 +95,11 @@ pub enum Ast {...@@ -91,6 +95,11 @@ pub enum Ast {
91 name: String,95 name: String,
92 arguments: Vec<Ast>,96 arguments: Vec<Ast>,
93 },97 },
98 If {
99 condition: Box<Ast>,
100 value: Block,
101 else_value: Option<Box<Ast>>,
102 },
94 Block(Block),103 Block(Block),
95 Number(String),104 Number(String),
96 Bool(bool),105 Bool(bool),
compiler/src/lib.rs+6-4
...@@ -7,12 +7,14 @@ pub mod walker;...@@ -7,12 +7,14 @@ pub mod walker;
7pub mod util;7pub mod util;
88
9pub fn transpile(content: String) -> Result<String> {9pub fn transpile(content: String) -> Result<String> {
10 // // 1. Tokenize the input10 // 1. Tokenize the input
11 let tokens = tokenizer::tokenize(content)?;11 let tokens = tokenizer::tokenize(content)?;
12 // // 2. Parse the tokens into an AST12 // 2. Parse the tokens into an AST
13 let tree = ast::parse(tokens)?;13 let tree = ast::parse(tokens)?;
14 // // 3. Transpile the AST into javascript14 // 3. Type check the AST
15 // type_check(tree.clone())?;
16 // 4. Transpile the AST into javascript
15 let result = walker::transpile(tree)?;17 let result = walker::transpile(tree)?;
16 // 4. Return the javascript18 // 5. Return the javascript
17 return Ok(result);19 return Ok(result);
18}20}
compiler/src/tokenizer.rs+7-1
...@@ -115,7 +115,13 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {...@@ -115,7 +115,13 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {
115 tokens.push(Token::Number(current_token));115 tokens.push(Token::Number(current_token));
116 }116 }
117 ':' => tokens.push(Token::Colon),117 ':' => tokens.push(Token::Colon),
118 '=' => tokens.push(Token::Equals),118 '=' => match chars.peek() {
119 Some((_, '=')) => {
120 chars.next();
121 tokens.push(Token::Operator(Operator::Equals));
122 }
123 _ => tokens.push(Token::Equals),
124 },
119 ';' => tokens.push(Token::Semicolon),125 ';' => tokens.push(Token::Semicolon),
120 '+' => tokens.push(Token::Operator(Operator::Add)),126 '+' => tokens.push(Token::Operator(Operator::Add)),
121 '-' => match chars.peek() {127 '-' => match chars.peek() {
compiler/src/util.rs+2
...@@ -5,6 +5,7 @@ pub enum Operator {...@@ -5,6 +5,7 @@ pub enum Operator {
5 Multiply,5 Multiply,
6 Divide,6 Divide,
7 Power,7 Power,
8 Equals,
8}9}
910
10impl Operator {11impl Operator {
...@@ -15,6 +16,7 @@ impl Operator {...@@ -15,6 +16,7 @@ impl Operator {
15 Self::Divide => "/",16 Self::Divide => "/",
16 Self::Multiply => "*",17 Self::Multiply => "*",
17 Self::Power => "**",18 Self::Power => "**",
19 Self::Equals => "===",
18 })20 })
19 }21 }
20}22}
compiler/src/walker.rs+26-1
...@@ -68,6 +68,31 @@ fn transpile_helper(tree: &Ast) -> Result<String> {...@@ -68,6 +68,31 @@ fn transpile_helper(tree: &Ast) -> Result<String> {
6868
69 result69 result
70 }70 }
71 Ast::If {
72 condition,
73 value,
74 else_value,
75 } => {
76 let mut result = format!("if ({}) {{\n", transpile_helper(condition)?,);
77
78 for (i, statement) in value.value.iter().enumerate() {
79 if value.implicit_return && i == value.value.len() - 1 {
80 result += format!("return {};\n", transpile_helper(statement)?).as_str();
81 break;
82 }
83 result += transpile_helper(statement)?.as_str();
84 }
85
86 result += "}";
87
88 if let Some(val) = else_value {
89 result += format!(" else {{\n{}}}", transpile_helper(val)?).as_str();
90 } else {
91 result += "\n";
92 }
93
94 result
95 }
71 Ast::FunctionCall { name, arguments } => {96 Ast::FunctionCall { name, arguments } => {
72 let mut result = match name.as_str() {97 let mut result = match name.as_str() {
73 "print" => String::from("console.log("),98 "print" => String::from("console.log("),
...@@ -87,7 +112,7 @@ fn transpile_helper(tree: &Ast) -> Result<String> {...@@ -87,7 +112,7 @@ fn transpile_helper(tree: &Ast) -> Result<String> {
87 result112 result
88 }113 }
89 Ast::Block(block) => {114 Ast::Block(block) => {
90 let mut result = String::from("(()=>{");115 let mut result = String::from("(()=>{\n");
91 for (i, statement) in block.value.iter().enumerate() {116 for (i, statement) in block.value.iter().enumerate() {
92 if block.implicit_return && i == block.value.len() - 1 {117 if block.implicit_return && i == block.value.len() - 1 {
93 result += format!("return {};\n", transpile_helper(statement)?).as_str();118 result += format!("return {};\n", transpile_helper(statement)?).as_str();
examples/basics/control.blight+10
...@@ -3,3 +3,13 @@ let x: bool = true;...@@ -3,3 +3,13 @@ let x: bool = true;
3if x {3if x {
4 print("x is true!");4 print("x is true!");
5}5}
6
7let y: int = 3;
8
9if y == 1 {
10 print("y is 1!");
11} else if y == 2 {
12 print("y is 2!");
13} else {
14 print("y is not 1 or 2!");
15}
examples/basics/fib.blight created+11
...@@ -0,0 +1,11 @@
1pub fn fib(n: int) -> int {
2 if n == 0 {
3 return 0;
4 }
5 if n == 1 {
6 return 1;
7 }
8 fib(n - 1) + fib(n - 2)
9}
10
11print(fib(10));