From c83d53ae53a3fa9acd2f59261f2ca0e4caf030d4 Mon Sep 17 00:00:00 2001 From: sofia Date: Tue, 15 Jul 2025 21:19:37 +0300 Subject: [PATCH] Add struct type and expression parsing --- reid/examples/cli.rs | 2 +- reid/src/ast/mod.rs | 13 +++-- reid/src/ast/parse.rs | 102 +++++++++++++++++++++++++++++++++++++-- reid/src/ast/process.rs | 1 + reid/src/token_stream.rs | 8 +++ 5 files changed, 118 insertions(+), 8 deletions(-) diff --git a/reid/examples/cli.rs b/reid/examples/cli.rs index abf53df..4231410 100644 --- a/reid/examples/cli.rs +++ b/reid/examples/cli.rs @@ -1,4 +1,4 @@ -use std::{env, fs, path::PathBuf}; +use std::{env, error::Error, fs, path::PathBuf}; use reid::compile; use reid_lib::compile::CompileOutput; diff --git a/reid/src/ast/mod.rs b/reid/src/ast/mod.rs index 6800d73..ad95cf6 100644 --- a/reid/src/ast/mod.rs +++ b/reid/src/ast/mod.rs @@ -49,6 +49,7 @@ pub enum ExpressionKind { FunctionCall(Box), BlockExpr(Box), IfExpr(Box), + StructInit(StructInit), } #[derive(Debug, Clone, Copy)] @@ -130,6 +131,12 @@ pub enum ReturnType { Hard, } +#[derive(Debug, Clone)] +pub struct StructInit { + name: String, + fields: Vec<(String, Expression)>, +} + #[derive(Debug, Clone)] pub struct Block( pub Vec, @@ -160,18 +167,18 @@ pub enum BlockLevelStatement { #[derive(Debug)] pub struct TypeDefinition { - range: TokenRange, name: String, kind: TypeDefinitionKind, + range: TokenRange, } #[derive(Debug)] pub enum TypeDefinitionKind { - Struct(Vec), + Struct(Vec), } #[derive(Debug)] -pub struct StructField { +pub struct StructDefinitionField { name: String, ty: Type, range: TokenRange, diff --git a/reid/src/ast/parse.rs b/reid/src/ast/parse.rs index 3236db9..ddfd58a 100644 --- a/reid/src/ast/parse.rs +++ b/reid/src/ast/parse.rs @@ -76,10 +76,24 @@ impl Parse for PrimaryExpression { ) } else if let Ok(ifexpr) = stream.parse() { Expression(Kind::IfExpr(Box::new(ifexpr)), stream.get_range().unwrap()) + } else if let (Some(Token::Identifier(_)), Some(Token::BraceOpen)) = + (stream.peek(), stream.peek2()) + { + Expression( + Kind::StructInit(stream.parse()?), + stream.get_range().unwrap(), + ) } else if let Some(token) = stream.next() { match &token { Token::Identifier(v) => { - Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap()) + if let Some(Token::BraceOpen) = stream.peek() { + Expression( + Kind::StructInit(stream.parse()?), + stream.get_range().unwrap(), + ) + } else { + Expression(Kind::VariableName(v.clone()), stream.get_range().unwrap()) + } } Token::DecimalValue(v) => Expression( Kind::Literal(Literal::Number(*v)), @@ -415,6 +429,57 @@ impl Parse for VariableReference { } } +impl Parse for StructInit { + fn parse(mut stream: TokenStream) -> Result { + let Some(Token::Identifier(name)) = stream.next() else { + return Err(stream.expected_err("struct identifier")?); + }; + stream.expect(Token::BraceOpen)?; + let named_list = stream.parse::>()?; + let fields = named_list.0.into_iter().map(|f| (f.0, f.1)).collect(); + + stream.expect(Token::BraceClose)?; + stream.expect(Token::Semi)?; + + Ok(StructInit { name, fields }) + } +} + +#[derive(Debug)] +pub struct NamedFieldList(Vec>); + +impl Parse for NamedFieldList { + fn parse(mut stream: TokenStream) -> Result { + let mut fields = Vec::new(); + while let Ok(field) = stream.parse() { + fields.push(field); + match stream.peek() { + Some(Token::Comma) => { + stream.next(); + } // Consume comma + Some(Token::BraceClose) => break, + Some(_) | None => Err(stream.expected_err("another field or closing brace")?)?, + } + } + Ok(NamedFieldList(fields)) + } +} + +#[derive(Debug)] +pub struct NamedField(String, T, TokenRange); + +impl Parse for NamedField { + fn parse(mut stream: TokenStream) -> Result { + let Some(Token::Identifier(field_name)) = stream.next() else { + return Err(stream.expected_err("type name")?); + }; + stream.expect(Token::Colon)?; + let value = stream.parse()?; + + Ok(NamedField(field_name, value, stream.get_range().unwrap())) + } +} + #[derive(Debug, Clone, Copy)] pub struct ValueIndex(u64); @@ -476,9 +541,30 @@ impl Parse for SetStatement { } } -impl Parse for TypeDefinition { - fn parse(stream: TokenStream) -> Result { - todo!() +#[derive(Debug)] +pub struct StructDefinition(String, Vec, TokenRange); + +impl Parse for StructDefinition { + fn parse(mut stream: TokenStream) -> Result { + stream.expect(Token::Struct)?; + + let Some(Token::Identifier(name)) = stream.next() else { + return Err(stream.expected_err("identifier")?); + }; + + stream.expect(Token::BraceOpen)?; + let named_fields = stream.parse::>()?; + let fields = named_fields + .0 + .into_iter() + .map(|f| StructDefinitionField { + name: f.0, + ty: f.1, + range: f.2, + }) + .collect(); + stream.expect(Token::BraceClose)?; + Ok(StructDefinition(name, fields, stream.get_range().unwrap())) } } @@ -497,6 +583,14 @@ impl Parse for TopLevelStatement { Some(Token::FnKeyword) | Some(Token::PubKeyword) => { Stmt::FunctionDefinition(stream.parse()?) } + Some(Token::Struct) => { + let StructDefinition(name, fields, range) = stream.parse::()?; + Stmt::TypeDefinition(TypeDefinition { + name, + kind: TypeDefinitionKind::Struct(fields), + range, + }) + } _ => Err(stream.expected_err("import or fn")?)?, }) } diff --git a/reid/src/ast/process.rs b/reid/src/ast/process.rs index aaf7043..9c7d7c4 100644 --- a/reid/src/ast/process.rs +++ b/reid/src/ast/process.rs @@ -199,6 +199,7 @@ impl ast::Expression { mir::TypeKind::Vague(mir::VagueType::Unknown), *idx, ), + ast::ExpressionKind::StructInit(struct_init) => todo!("implement struct init process"), }; mir::Expression(kind, self.1.into()) diff --git a/reid/src/token_stream.rs b/reid/src/token_stream.rs index 4f0ebd0..7f9853b 100644 --- a/reid/src/token_stream.rs +++ b/reid/src/token_stream.rs @@ -63,6 +63,14 @@ impl<'a, 'b> TokenStream<'a, 'b> { } } + pub fn peek2(&mut self) -> Option { + if self.tokens.len() < (self.position + 1) { + None + } else { + Some(self.tokens[self.position + 1].token.clone()) + } + } + /// Parse the next value of trait Parse. If the parse succeeded, the related /// tokens are consumed, otherwise token stream does not advance. ///