From 6ee333291052ae5274c98c7976cd6bc8bb9a8fc5 Mon Sep 17 00:00:00 2001 From: Lucas Date: Wed, 12 Jun 2024 23:41:02 +0200 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8=20(parser):=20Add=20enum=20parsing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit semver: minor --- src/main.rs | 8 +++++++- src/parser/ast.rs | 3 ++- src/parser/lookup.rs | 4 +++- src/parser/statement.rs | 41 ++++++++++++++++++++++++++++++++++++++++- src/transpiler/bend.rs | 9 +++++++++ 5 files changed, 61 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 016aa5e..bee6277 100644 --- a/src/main.rs +++ b/src/main.rs @@ -40,7 +40,13 @@ fn lexeme_range_to_source_range(lexemes: &[Lexeme], diagnostic: &parser::Diagnos fn main() -> Result<()> { let code = " - 1 = (1)); + enum result: success failure; + + struct person: + name: string + age: int + ; + "; let file: SimpleFile<&str, &str> = SimpleFile::new("main", code); diff --git a/src/parser/ast.rs b/src/parser/ast.rs index e5836b2..7d82b8a 100644 --- a/src/parser/ast.rs +++ b/src/parser/ast.rs @@ -1,4 +1,4 @@ -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use crate::scanner::lexeme::Lexeme; @@ -28,6 +28,7 @@ pub enum Statement { Declaration(String, Option, Expression), Expression(Expression), Struct(String, HashMap), + Enum(String, HashSet), } #[derive(Debug, Clone, PartialEq, Eq)] diff --git a/src/parser/lookup.rs b/src/parser/lookup.rs index 5832a81..61a843e 100644 --- a/src/parser/lookup.rs +++ b/src/parser/lookup.rs @@ -221,9 +221,11 @@ 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.add_statement_handler(TokenType::Struct, statement::parse_struct); + lookup.add_statement_handler(TokenType::Enum, statement::parse_enum); + lookup } } diff --git a/src/parser/statement.rs b/src/parser/statement.rs index a963445..2f828cd 100644 --- a/src/parser/statement.rs +++ b/src/parser/statement.rs @@ -1,5 +1,5 @@ use core::panic; -use std::collections::HashMap; +use std::collections::{HashMap, HashSet}; use crate::scanner::lexeme::{Lexeme, Range, TokenType, TokenValue}; @@ -110,3 +110,42 @@ pub fn parse_struct(parser: &Parser, cursor: usize) -> Result<(Statement, usize) Ok((Statement::Struct(name, members), cursor)) } + +pub fn parse_enum(parser: &Parser, cursor: usize) -> Result<(Statement, usize), Diagnostic> { + let (_, cursor) = expect_token!(parser, cursor, TokenType::Enum)?; + let (name, cursor) = expect_token!(parser, cursor, TokenType::Identifier)?; + let name = match &name.value { + TokenValue::Identifier(name) => name.clone(), + _ => panic!("expect_token! should return a valid token and handle the error case"), + }; + let (_, cursor) = expect_token!(parser, cursor, TokenType::Colon)?; + + let mut new_cursor = cursor; + let mut members: HashSet = HashSet::new(); + + while let Some(Lexeme::Valid(token)) = parser.lexemes.get(new_cursor) { + let (member_name, cursor) = match token.token_type { + TokenType::Semicolon => break, + _ => { + 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 return a valid token and handle the error case" + ), + }; + + (field_name, cursor) + } + }; + + new_cursor = cursor; + // TODO: Handle warning for overwritten members + members.insert(member_name); + } + + let (_, cursor) = expect_token!(parser, new_cursor, TokenType::Semicolon)?; + + Ok((Statement::Enum(name, members), cursor)) +} diff --git a/src/transpiler/bend.rs b/src/transpiler/bend.rs index 7255b4b..5b8de2f 100644 --- a/src/transpiler/bend.rs +++ b/src/transpiler/bend.rs @@ -106,6 +106,15 @@ fn transpile_statement(statement: &Statement) -> String { output.push_str("}\n"); output } + Statement::Enum(name, members) => { + let mut output = String::new(); + output.push_str(&format!("enum {} {{\n", name)); + for member in members { + output.push_str(&format!("{},\n", member)); + } + output.push_str("}\n"); + output + } } }