Add struct indexing parsing

This commit is contained in:
Sofia 2025-07-15 21:28:02 +03:00
parent c83d53ae53
commit d9a1e8456d
3 changed files with 69 additions and 22 deletions

View File

@ -44,12 +44,13 @@ pub enum ExpressionKind {
VariableName(String),
Literal(Literal),
Array(Vec<Expression>),
Index(Box<Expression>, u64),
ArrayIndex(Box<Expression>, u64),
StructIndex(Box<Expression>, String),
Binop(BinaryOperator, Box<Expression>, Box<Expression>),
FunctionCall(Box<FunctionCallExpression>),
BlockExpr(Box<Block>),
IfExpr(Box<IfExpression>),
StructInit(StructInit),
StructExpression(StructExpression),
}
#[derive(Debug, Clone, Copy)]
@ -132,7 +133,7 @@ pub enum ReturnType {
}
#[derive(Debug, Clone)]
pub struct StructInit {
pub struct StructExpression {
name: String,
fields: Vec<(String, Expression)>,
}
@ -150,7 +151,8 @@ pub struct VariableReference(pub VariableReferenceKind, pub TokenRange);
#[derive(Debug, Clone)]
pub enum VariableReferenceKind {
Name(String, TokenRange),
Index(Box<VariableReference>, u64),
ArrayIndex(Box<VariableReference>, u64),
StructIndex(Box<VariableReference>, String),
}
#[derive(Debug, Clone)]

View File

@ -80,7 +80,7 @@ impl Parse for PrimaryExpression {
(stream.peek(), stream.peek2())
{
Expression(
Kind::StructInit(stream.parse()?),
Kind::StructExpression(stream.parse()?),
stream.get_range().unwrap(),
)
} else if let Some(token) = stream.next() {
@ -88,7 +88,7 @@ impl Parse for PrimaryExpression {
Token::Identifier(v) => {
if let Some(Token::BraceOpen) = stream.peek() {
Expression(
Kind::StructInit(stream.parse()?),
Kind::StructExpression(stream.parse()?),
stream.get_range().unwrap(),
)
} else {
@ -134,12 +134,22 @@ impl Parse for PrimaryExpression {
Err(stream.expected_err("expression")?)?
};
while let Ok(ValueIndex(idx)) = stream.parse() {
while let Ok(index) = stream.parse::<ValueIndex>() {
match index {
ValueIndex::Array(ArrayValueIndex(idx)) => {
expr = Expression(
ExpressionKind::Index(Box::new(expr), idx),
ExpressionKind::ArrayIndex(Box::new(expr), idx),
stream.get_range().unwrap(),
);
}
ValueIndex::Struct(StructValueIndex(name)) => {
expr = Expression(
ExpressionKind::StructIndex(Box::new(expr), name),
stream.get_range().unwrap(),
);
}
}
}
Ok(PrimaryExpression(expr))
}
@ -415,9 +425,9 @@ impl Parse for VariableReference {
stream.get_range().unwrap(),
);
while let Ok(ValueIndex(idx)) = stream.parse() {
while let Ok(ArrayValueIndex(idx)) = stream.parse() {
var_ref = VariableReference(
VariableReferenceKind::Index(Box::new(var_ref), idx),
VariableReferenceKind::ArrayIndex(Box::new(var_ref), idx),
stream.get_range().unwrap(),
);
}
@ -429,7 +439,7 @@ impl Parse for VariableReference {
}
}
impl Parse for StructInit {
impl Parse for StructExpression {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
let Some(Token::Identifier(name)) = stream.next() else {
return Err(stream.expected_err("struct identifier")?);
@ -439,9 +449,8 @@ impl Parse for StructInit {
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 })
Ok(StructExpression { name, fields })
}
}
@ -480,21 +489,51 @@ impl<T: Parse + std::fmt::Debug> Parse for NamedField<T> {
}
}
#[derive(Debug, Clone, Copy)]
pub struct ValueIndex(u64);
#[derive(Debug, Clone)]
pub enum ValueIndex {
Array(ArrayValueIndex),
Struct(StructValueIndex),
}
impl Parse for ValueIndex {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
match stream.peek() {
Some(Token::BracketOpen) => Ok(ValueIndex::Array(stream.parse()?)),
Some(Token::Dot) => Ok(ValueIndex::Struct(stream.parse()?)),
_ => Err(stream.expected_err("value or struct index")?),
}
}
}
#[derive(Debug, Clone, Copy)]
pub struct ArrayValueIndex(u64);
impl Parse for ArrayValueIndex {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
stream.expect(Token::BracketOpen)?;
if let Some(Token::DecimalValue(idx)) = stream.next() {
stream.expect(Token::BracketClose)?;
Ok(ValueIndex(idx))
Ok(ArrayValueIndex(idx))
} else {
return Err(stream.expected_err("array index (number)")?);
}
}
}
#[derive(Debug, Clone)]
pub struct StructValueIndex(String);
impl Parse for StructValueIndex {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
stream.expect(Token::Dot)?;
if let Some(Token::Identifier(name)) = stream.next() {
Ok(StructValueIndex(name))
} else {
return Err(stream.expected_err("struct index (number)")?);
}
}
}
impl Parse for BlockLevelStatement {
fn parse(mut stream: TokenStream) -> Result<Self, Error> {
use BlockLevelStatement as Stmt;

View File

@ -152,9 +152,12 @@ impl ast::VariableReferenceKind {
(*range).into(),
))
}
ast::VariableReferenceKind::Index(var_ref, idx) => {
ast::VariableReferenceKind::ArrayIndex(var_ref, idx) => {
mir::IndexedVariableReferenceKind::Index(Box::new(var_ref.process()), *idx)
}
ast::VariableReferenceKind::StructIndex(variable_reference, _) => {
todo!("struct indexing into mir")
}
}
}
}
@ -194,12 +197,15 @@ impl ast::Expression {
ast::ExpressionKind::Array(expressions) => {
mir::ExprKind::Array(expressions.iter().map(|e| e.process()).collect())
}
ast::ExpressionKind::Index(expression, idx) => mir::ExprKind::Index(
ast::ExpressionKind::ArrayIndex(expression, idx) => mir::ExprKind::Index(
Box::new(expression.process()),
mir::TypeKind::Vague(mir::VagueType::Unknown),
*idx,
),
ast::ExpressionKind::StructInit(struct_init) => todo!("implement struct init process"),
ast::ExpressionKind::StructExpression(struct_init) => {
todo!("implement struct init process")
}
ast::ExpressionKind::StructIndex(expression, _) => todo!("struct index expression"),
};
mir::Expression(kind, self.1.into())