authorgravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-01-02 14:27:33+01:00
committergravatar for 11367844+lino-levan@users.noreply.github.comLino Le Van <11367844+lino-levan@users.noreply.github.com> 2024-01-02 14:27:33+01:00
logde824b0e32bfb81f03869727ac3ff2006a3492e9
treef07cffa9127dc45d01c2e04fbfcc7fe0efa1e975
parent1d5c7d0343ace11cd5a441a9d59c131181c78dc6

chore: add let support


4 files changed, 52 insertions(+), 0 deletions(-)

examples/easy.blight+4
......@@ -1,3 +1,7 @@
11var x: int = 0;
22var y: float = 0;
33var z: bigint = 0;
4
5let a: int = 0;
6let b: float = 0;
7let c: bigint = 0;
src/transpile/ast.rs+40
......@@ -26,6 +26,11 @@ pub enum Type {
2626
2727#[derive(Debug)]
2828pub enum Ast {
29 ConstantDeclaration {
30 name: String,
31 typ: Type,
32 value: Box<Ast>
33 },
2934 VariableDeclaration {
3035 name: String,
3136 typ: Type,
......@@ -49,6 +54,41 @@ fn parse_expression(tokens: &mut dyn PeekableIterator<Item=&Token>) -> Result<As
4954/// Precondition: There is at least one token in the iterator
5055fn parse_statement(tokens: &mut dyn PeekableIterator<Item=&Token>) -> Result<Ast> {
5156 match tokens.next().unwrap() {
57 Token::Let => {
58 let name = match tokens.next() {
59 Some(Token::Identifier(name)) => name,
60 _ => return Err(AstError::new("Expected identifier after var").into())
61 };
62 let typ = match tokens.next() {
63 Some(Token::Colon) => {
64 match tokens.next() {
65 Some(Token::Identifier(typ)) => {
66 match typ.as_str() {
67 "int" => Type::Int,
68 "float" => Type::Float,
69 "bigint" => Type::Bigint,
70 _ => return Err(AstError::new("Expected type after colon").into())
71 }
72 },
73 _ => return Err(AstError::new("Expected type after colon").into())
74 }
75 },
76 _ => return Err(AstError::new("Expected colon after identifier").into())
77 };
78 let value = match tokens.next() {
79 Some(Token::Equals) => parse_expression(tokens)?,
80 _ => return Err(AstError::new("Expected equals after identifier").into())
81 };
82 match tokens.next() {
83 Some(Token::Semicolon) => (),
84 _ => return Err(AstError::new("Expected semicolon after variable declaration").into())
85 };
86 Ok(Ast::ConstantDeclaration {
87 name: name.clone(),
88 typ,
89 value: Box::new(value),
90 })
91 },
5292 Token::Var => {
5393 let name = match tokens.next() {
5494 Some(Token::Identifier(name)) => name,
src/transpile/tokenizer.rs+2
......@@ -22,6 +22,7 @@ pub enum Token {
2222 Identifier(String),
2323 Number(String),
2424 // Keywords
25 Let,
2526 Var,
2627 Colon,
2728 Equals,
......@@ -58,6 +59,7 @@ pub fn tokenize(content: String) -> Result<Vec<Token>> {
5859
5960 match current_token.as_str() {
6061 "var" => tokens.push(Token::Var),
62 "let" => tokens.push(Token::Let),
6163 _ => tokens.push(Token::Identifier(current_token)),
6264 }
6365 },
src/transpile/walker.rs+6
......@@ -9,6 +9,12 @@ fn transpile_helper(tree: Ast) -> String {
99 _ => format!("let {} = {};\n", name, transpile_helper(*value))
1010 }
1111 },
12 Ast::ConstantDeclaration { name, typ, value } => {
13 match typ {
14 Type::Bigint => format!("const {} = BigInt({});\n", name, transpile_helper(*value)),
15 _ => format!("const {} = {};\n", name, transpile_helper(*value))
16 }
17 }
1218 }
1319}
1420