From 1588c0407d7cd649cadec7e71c16c2073afa3b63 Mon Sep 17 00:00:00 2001 From: Garrit Franke Date: Mon, 15 Feb 2021 20:38:33 +0100 Subject: [PATCH] feat: basic field access --- src/generator/c.rs | 2 ++ src/generator/js.rs | 10 ++++++++-- src/lexer/mod.rs | 3 +++ src/parser/node_type.rs | 1 + src/parser/rules.rs | 9 +++++++++ tests/structs.sb | 17 +++++++++++++++++ 6 files changed, 40 insertions(+), 2 deletions(-) create mode 100644 tests/structs.sb diff --git a/src/generator/c.rs b/src/generator/c.rs index d921940..02da8ea 100644 --- a/src/generator/c.rs +++ b/src/generator/c.rs @@ -127,6 +127,7 @@ fn generate_expression(expr: Expression) -> String { Expression::ArrayAccess(name, expr) => generate_array_access(name, *expr), Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right), Expression::StructInitialization(_, _) => todo!(), + Expression::FieldAccess(_, _) => todo!(), } } @@ -220,6 +221,7 @@ fn generate_function_call(func: String, args: Vec) -> String { Expression::Array(_) => todo!(), Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right), Expression::StructInitialization(_, _) => todo!(), + Expression::FieldAccess(_, _) => todo!(), }) .collect::>() .join(","); diff --git a/src/generator/js.rs b/src/generator/js.rs index 5f64717..0a05cc2 100644 --- a/src/generator/js.rs +++ b/src/generator/js.rs @@ -119,7 +119,8 @@ fn generate_expression(expr: Expression) -> String { Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right), Expression::StructInitialization(name, fields) => { generate_struct_initialization(name, fields) - } + }, + Expression::FieldAccess(expr, field) => generate_field_access(*expr, field), } } @@ -230,7 +231,8 @@ fn generate_function_call(func: String, args: Vec) -> String { Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right), Expression::StructInitialization(name, fields) => { generate_struct_initialization(name, fields) - } + }, + Expression::FieldAccess(expr, field) => generate_field_access(*expr, field), }) .collect::>() .join(","); @@ -286,6 +288,10 @@ fn generate_struct_initialization( out_str } +fn generate_field_access(expr: Expression, field: String) -> String { + format!("{}.{}", generate_expression(expr), field) +} + fn generate_assign(name: Expression, expr: Expression) -> String { format!( "{} = {}", diff --git a/src/lexer/mod.rs b/src/lexer/mod.rs index e71eef5..14586e4 100644 --- a/src/lexer/mod.rs +++ b/src/lexer/mod.rs @@ -72,6 +72,8 @@ pub enum TokenKind { Colon, /// ";" SemiColon, + /// "." + Dot, /// "!" Exclamation, /// "," @@ -203,6 +205,7 @@ impl Cursor<'_> { c if is_whitespace(c) => self.whitespace(), '0'..='9' => self.number(), '"' | '\'' => self.string(), + '.' => Dot, '+' => match self.first() { '=' => { self.bump(); diff --git a/src/parser/node_type.rs b/src/parser/node_type.rs index f9bcc67..5b2a716 100644 --- a/src/parser/node_type.rs +++ b/src/parser/node_type.rs @@ -114,6 +114,7 @@ pub enum Expression { ArrayAccess(String, Box), BinOp(Box, BinOp, Box), StructInitialization(String, HashMap>), + FieldAccess(Box, String) } impl TryFrom for Expression { diff --git a/src/parser/rules.rs b/src/parser/rules.rs index cd45bf9..024cb76 100644 --- a/src/parser/rules.rs +++ b/src/parser/rules.rs @@ -298,6 +298,15 @@ impl Parser { Err(_) => arr, } } + TokenKind::Dot => { + let subject = Expression::Variable(token.raw); + self.match_token(TokenKind::Dot)?; + let field = self.match_identifier()?; + match BinOp::try_from(self.peek()?.kind) { + Ok(_) => self.parse_bin_op(Some(Expression::Variable(field)))?, + Err(_) => return Ok(Expression::FieldAccess(Box::new(subject), field)), + } + } _ => match BinOp::try_from(self.peek()?.kind) { Ok(_) => self.parse_bin_op(Some(Expression::Variable(token.raw)))?, Err(_) => Expression::Variable(val), diff --git a/tests/structs.sb b/tests/structs.sb new file mode 100644 index 0000000..ae4469a --- /dev/null +++ b/tests/structs.sb @@ -0,0 +1,17 @@ +struct User { + username: string, + first_name: string, + last_name: string +} + +fn test_initialization() { + let foo = new User { + username: "Foo Bar", + first_name: "Bar", + last_name: "Foo Bar" + } +} + +fn main() { + test_initialization() +} \ No newline at end of file