Browse Source

feat: basic field access

structs
Garrit Franke 3 years ago
parent
commit
1588c0407d
  1. 2
      src/generator/c.rs
  2. 10
      src/generator/js.rs
  3. 3
      src/lexer/mod.rs
  4. 1
      src/parser/node_type.rs
  5. 9
      src/parser/rules.rs
  6. 17
      tests/structs.sb

2
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<Expression>) -> String {
Expression::Array(_) => todo!(),
Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right),
Expression::StructInitialization(_, _) => todo!(),
Expression::FieldAccess(_, _) => todo!(),
})
.collect::<Vec<String>>()
.join(",");

10
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<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),
})
.collect::<Vec<String>>()
.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!(
"{} = {}",

3
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();

1
src/parser/node_type.rs

@ -114,6 +114,7 @@ pub enum Expression {
ArrayAccess(String, Box<Expression>),
BinOp(Box<Expression>, BinOp, Box<Expression>),
StructInitialization(String, HashMap<String, Box<Expression>>),
FieldAccess(Box<Expression>, String)
}
impl TryFrom<Token> for Expression {

9
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),

17
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()
}
Loading…
Cancel
Save