Browse Source

feat: struct initialization

structs
Garrit Franke 3 years ago
parent
commit
277272e2b7
  1. 2
      src/generator/c.rs
  2. 21
      src/generator/js.rs
  3. 1
      src/parser/node_type.rs
  4. 42
      src/parser/rules.rs

2
src/generator/c.rs

@ -125,6 +125,7 @@ fn generate_expression(expr: Expression) -> String {
Expression::Array(els) => generate_array(els),
Expression::ArrayAccess(name, expr) => generate_array_access(name, *expr),
Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right),
Expression::StructInitialization(_, _) => todo!(),
}
}
@ -217,6 +218,7 @@ fn generate_function_call(func: String, args: Vec<Expression>) -> String {
Expression::Str(s) | Expression::Variable(s) => s,
Expression::Array(_) => todo!(),
Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right),
Expression::StructInitialization(_, _) => todo!(),
})
.collect::<Vec<String>>()
.join(",");

21
src/generator/js.rs

@ -15,6 +15,7 @@
*/
use crate::generator::Generator;
use crate::parser::node_type::*;
use std::collections::HashMap;
pub struct JsGenerator;
@ -116,6 +117,9 @@ fn generate_expression(expr: Expression) -> String {
Expression::Array(els) => generate_array(els),
Expression::ArrayAccess(name, expr) => generate_array_access(name, *expr),
Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right),
Expression::StructInitialization(name, fields) => {
generate_struct_initialization(name, fields)
}
}
}
@ -224,6 +228,9 @@ fn generate_function_call(func: String, args: Vec<Expression>) -> String {
Expression::Str(s) | Expression::Variable(s) => s,
Expression::Array(elements) => generate_array(elements),
Expression::BinOp(left, op, right) => generate_bin_op(*left, op, *right),
Expression::StructInitialization(name, fields) => {
generate_struct_initialization(name, fields)
}
})
.collect::<Vec<String>>()
.join(",");
@ -265,6 +272,20 @@ fn generate_bin_op(left: Expression, op: BinOp, right: Expression) -> String {
)
}
fn generate_struct_initialization(
_name: String,
fields: HashMap<String, Box<Expression>>,
) -> String {
let mut out_str = "{".to_string();
for (key, value) in fields {
out_str += &format!("{}: {},", key, generate_expression(*value));
}
out_str += "}";
out_str.into()
}
fn generate_assign(name: Expression, expr: Expression) -> String {
format!(
"{} = {}",

1
src/parser/node_type.rs

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

42
src/parser/rules.rs

@ -18,6 +18,7 @@ use super::node_type::*;
use super::parser::Parser;
use crate::lexer::Keyword;
use crate::lexer::{TokenKind, Value};
use std::collections::HashMap;
use std::convert::TryFrom;
impl Parser {
@ -305,10 +306,51 @@ impl Parser {
Ok(state)
}
TokenKind::SquareBraceOpen => self.parse_array(),
TokenKind::Keyword(Keyword::Struct) => self.parse_struct_initialization(),
other => Err(format!("Expected Expression, found {:?}", other)),
}
}
/// TODO: Cleanup
fn parse_struct_initialization(&mut self) -> Result<Expression, String> {
let name = self.match_identifier()?;
self.match_token(TokenKind::CurlyBracesOpen)?;
let fields = self.parse_struct_fields()?;
self.match_token(TokenKind::CurlyBracesClose)?;
Ok(Expression::StructInitialization(name, fields))
}
fn parse_struct_fields(&mut self) -> Result<HashMap<String, Box<Expression>>, String> {
let mut map = HashMap::new();
// If there is a field
if let TokenKind::Identifier(_) = self.peek()?.kind {
// Parse first field
let (name, expr) = self.parse_struct_field()?;
map.insert(name, expr);
// Then continue to parse fields
// as long as a comma token is found
while self.peek_token(TokenKind::Comma).is_ok() {
self.match_token(TokenKind::Comma)?;
let (name, expr) = self.parse_struct_field()?;
map.insert(name, expr);
}
}
Ok(map)
}
fn parse_struct_field(&mut self) -> Result<(String, Box<Expression>), String> {
let next = self.next()?;
if let TokenKind::Identifier(name) = next.kind {
self.match_token(TokenKind::Colon)?;
return Ok((name, Box::new(self.parse_expression()?)));
}
Err(format!("Struct field could not be parsed: {}", next.raw))
}
fn parse_array(&mut self) -> Result<Expression, String> {
let mut elements = Vec::new();
loop {

Loading…
Cancel
Save