Add struct type and expression parsing

This commit is contained in:
Sofia 2025-07-15 21:19:37 +03:00
parent 5fca72a3f9
commit c83d53ae53
5 changed files with 118 additions and 8 deletions

View File

@ -1,4 +1,4 @@
use std::{env, fs, path::PathBuf}; use std::{env, error::Error, fs, path::PathBuf};
use reid::compile; use reid::compile;
use reid_lib::compile::CompileOutput; use reid_lib::compile::CompileOutput;

View File

@ -49,6 +49,7 @@ pub enum ExpressionKind {
FunctionCall(Box<FunctionCallExpression>), FunctionCall(Box<FunctionCallExpression>),
BlockExpr(Box<Block>), BlockExpr(Box<Block>),
IfExpr(Box<IfExpression>), IfExpr(Box<IfExpression>),
StructInit(StructInit),
} }
#[derive(Debug, Clone, Copy)] #[derive(Debug, Clone, Copy)]
@ -130,6 +131,12 @@ pub enum ReturnType {
Hard, Hard,
} }
#[derive(Debug, Clone)]
pub struct StructInit {
name: String,
fields: Vec<(String, Expression)>,
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct Block( pub struct Block(
pub Vec<BlockLevelStatement>, pub Vec<BlockLevelStatement>,
@ -160,18 +167,18 @@ pub enum BlockLevelStatement {
#[derive(Debug)] #[derive(Debug)]
pub struct TypeDefinition { pub struct TypeDefinition {
range: TokenRange,
name: String, name: String,
kind: TypeDefinitionKind, kind: TypeDefinitionKind,
range: TokenRange,
} }
#[derive(Debug)] #[derive(Debug)]
pub enum TypeDefinitionKind { pub enum TypeDefinitionKind {
Struct(Vec<StructField>), Struct(Vec<StructDefinitionField>),
} }
#[derive(Debug)] #[derive(Debug)]
pub struct StructField { pub struct StructDefinitionField {
name: String, name: String,
ty: Type, ty: Type,
range: TokenRange, range: TokenRange,

View File

@ -76,10 +76,24 @@ impl Parse for PrimaryExpression {
) )
} else if let Ok(ifexpr) = stream.parse() { } else if let Ok(ifexpr) = stream.parse() {
Expression(Kind::IfExpr(Box::new(ifexpr)), stream.get_range().unwrap()) 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() { } else if let Some(token) = stream.next() {
match &token { match &token {
Token::Identifier(v) => { 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( Token::DecimalValue(v) => Expression(
Kind::Literal(Literal::Number(*v)), Kind::Literal(Literal::Number(*v)),
@ -415,6 +429,57 @@ impl Parse for VariableReference {
} }
} }
impl Parse for StructInit {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
let Some(Token::Identifier(name)) = stream.next() else {
return Err(stream.expected_err("struct identifier")?);
};
stream.expect(Token::BraceOpen)?;
let named_list = stream.parse::<NamedFieldList<Expression>>()?;
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<T: Parse + std::fmt::Debug>(Vec<NamedField<T>>);
impl<T: Parse + std::fmt::Debug> Parse for NamedFieldList<T> {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
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<T: Parse + std::fmt::Debug>(String, T, TokenRange);
impl<T: Parse + std::fmt::Debug> Parse for NamedField<T> {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
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)] #[derive(Debug, Clone, Copy)]
pub struct ValueIndex(u64); pub struct ValueIndex(u64);
@ -476,9 +541,30 @@ impl Parse for SetStatement {
} }
} }
impl Parse for TypeDefinition { #[derive(Debug)]
fn parse(stream: TokenStream) -> Result<Self, Error> { pub struct StructDefinition(String, Vec<StructDefinitionField>, TokenRange);
todo!()
impl Parse for StructDefinition {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
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::<NamedFieldList<Type>>()?;
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) => { Some(Token::FnKeyword) | Some(Token::PubKeyword) => {
Stmt::FunctionDefinition(stream.parse()?) Stmt::FunctionDefinition(stream.parse()?)
} }
Some(Token::Struct) => {
let StructDefinition(name, fields, range) = stream.parse::<StructDefinition>()?;
Stmt::TypeDefinition(TypeDefinition {
name,
kind: TypeDefinitionKind::Struct(fields),
range,
})
}
_ => Err(stream.expected_err("import or fn")?)?, _ => Err(stream.expected_err("import or fn")?)?,
}) })
} }

View File

@ -199,6 +199,7 @@ impl ast::Expression {
mir::TypeKind::Vague(mir::VagueType::Unknown), mir::TypeKind::Vague(mir::VagueType::Unknown),
*idx, *idx,
), ),
ast::ExpressionKind::StructInit(struct_init) => todo!("implement struct init process"),
}; };
mir::Expression(kind, self.1.into()) mir::Expression(kind, self.1.into())

View File

@ -63,6 +63,14 @@ impl<'a, 'b> TokenStream<'a, 'b> {
} }
} }
pub fn peek2(&mut self) -> Option<Token> {
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 /// Parse the next value of trait Parse. If the parse succeeded, the related
/// tokens are consumed, otherwise token stream does not advance. /// tokens are consumed, otherwise token stream does not advance.
/// ///