Skip to content

Commit

Permalink
✨ (parser): Add tuples
Browse files Browse the repository at this point in the history
semver: minor
  • Loading branch information
Somfic committed Jun 12, 2024
1 parent 474c106 commit 15f6918
Show file tree
Hide file tree
Showing 4 changed files with 71 additions and 3 deletions.
1 change: 1 addition & 0 deletions src/parser/ast.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,4 +47,5 @@ pub enum BinaryOperation {
pub enum Type {
Symbol(String),
Array(Box<Type>),
Tuple(HashMap<String, Type>),
}
1 change: 1 addition & 0 deletions src/parser/lookup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,7 @@ impl Default for Lookup {
lookup.add_type_handler(TokenType::Identifier, typing::parse_symbol);
lookup.add_type_handler(TokenType::SquareOpen, typing::parse_array);
lookup.add_statement_handler(TokenType::Struct, statement::parse_struct);
lookup.add_type_handler(TokenType::CurlyOpen, typing::parse_tuple);

lookup
}
Expand Down
59 changes: 58 additions & 1 deletion src/parser/typing.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
use std::collections::HashMap;

use super::{
ast::Type,
lookup::BindingPower,
macros::{expect_token, expect_type, expect_valid_token},
macros::{expect_optional_token, expect_token, expect_type, expect_valid_token},
Diagnostic, Parser,
};
use crate::scanner::lexeme::{Lexeme, TokenType, TokenValue};
Expand Down Expand Up @@ -68,3 +70,58 @@ pub fn parse_array(parser: &Parser, cursor: usize) -> Result<(Type, usize), Diag
let (_, cursor) = expect_token!(parser, cursor, TokenType::SquareClose)?;
Ok((Type::Array(Box::new(element_type)), cursor))
}

pub fn parse_tuple(parser: &Parser, cursor: usize) -> Result<(Type, usize), Diagnostic> {
let (_, cursor) = expect_token!(parser, cursor, TokenType::CurlyOpen)?;
let mut new_cursor = cursor;
let mut members: HashMap<String, Type> = HashMap::new();

while let Some(Lexeme::Valid(token)) = parser.lexemes.get(new_cursor) {
let (member_name, member_type, cursor) = match token.token_type {
TokenType::CurlyClose => break,
_ => {
if !members.is_empty() {
let (_, cursor) = expect_token!(parser, new_cursor, TokenType::Comma)?;
new_cursor = cursor;
}

// { number, string }
// { tires: number, color: string }
println!("Checking for optional token");
let (colon, _) = expect_optional_token!(parser, new_cursor + 1, TokenType::Colon)?;

match colon {
Some(_) => {
let (field_name, cursor) =
expect_token!(parser, new_cursor, TokenType::Identifier)?;
let field_name = match &field_name.value {
TokenValue::Identifier(field_name) => field_name.clone(),
_ => panic!("expect_token! should only return identifiers"),
};

let (_, cursor) = expect_token!(parser, cursor, TokenType::Colon)?;
let (field_type, cursor) =
expect_type!(parser, cursor, BindingPower::None)?;

(field_name, field_type, cursor)
}
None => {
let field_name = members.len().to_string();
let (field_type, cursor) =
expect_type!(parser, new_cursor, BindingPower::None)?;
(field_name, field_type, cursor)
}
}
}
};

// TODO: Check for duplicate member names
members.insert(member_name, member_type);

new_cursor = cursor;
}

let (_, cursor) = expect_token!(parser, new_cursor, TokenType::CurlyClose)?;

Ok((Type::Tuple(members), cursor))
}
13 changes: 11 additions & 2 deletions src/transpiler/bend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,9 @@ fn transpile_statement(statement: &Statement) -> String {
let mut output = String::new();
output.push_str(&format!("struct {} {{\n", name));
for (member, typing) in members {
output.push_str(&format!(" {}: {},\n", member, transpile_type(typing)));
output.push_str(&format!(" {}: {};\n", member, transpile_type(typing)));
}
output.push_str("}\n");
output.push_str(" }\n");
output
}
}
Expand All @@ -100,5 +100,14 @@ fn transpile_type(typing: &Type) -> String {
match typing {
Type::Symbol(symbol) => symbol.clone(),
Type::Array(typing) => format!("{}[]", transpile_type(typing)),
Type::Tuple(members) => {
let mut output = String::new();
output.push('(');
for (member, typing) in members {
output.push_str(&format!("{}: {}, ", member, transpile_type(typing)));
}
output.push(')');
output
}
}
}

0 comments on commit 15f6918

Please sign in to comment.