mclangc/src/parser/typ.rs
MCorange 081ff9a27a Add external functions (both import and export), make includes work
still need to fix literal arrays, it has the same problem as struct
literals had with moving the literal into memory and modifying the
memory with variables
2026-01-29 22:37:04 +02:00

74 lines
2.6 KiB
Rust

use anyhow::{Result, bail};
use crate::{cli::CliArgs, common::loc::LocBox, lerror, parser::{Delimiter, ast::{expr::Expr, literal::Literal}}, tokeniser::Token};
use super::{ast::{typ::Type, TokenType}, expr::parse_expr, utils, Keyword, Punctuation};
pub fn parse_type(tokens: &mut Vec<Token>) -> Result<LocBox<Type>> {
let mut ref_cnt = Vec::new();
let mut loc = None;
while let Some(tok) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Ampersand)) {
if let None = loc {
loc = Some(tok.loc().clone());
}
if let Some(tok) = utils::check_consume(tokens, TokenType::Keyword(Keyword::Mut)) {
ref_cnt.push(tok.clone());
} else {
ref_cnt.push(tok.clone());
}
}
let mut typ;
if let Some(start) = utils::check_consume(tokens, TokenType::Delim(super::Delimiter::SquareL)) {
if let None = loc {
loc = Some(start.loc().clone());
}
let itm_typ = parse_type(tokens)?;
if let Some(_) = utils::check_consume(tokens, TokenType::Punct(Punctuation::Semi)) {
let count = parse_expr(tokens, 0, false, &CliArgs::default())?.unwrap();
match count.inner() {
Expr::Literal(_, Literal::Number(_)) |
Expr::Path(_) => (),
_ => {
lerror!(count.loc(), "Only literal numbers are allowed in sized arrays");
bail!("")
}
}
typ = Type::SizedArray {
inner: Box::new(itm_typ.inner().clone()),
count: count
};
} else {
typ = Type::UnsizedArray {
inner: Box::new(itm_typ.inner().clone()),
};
}
_ = utils::check_consume_or_err(tokens, TokenType::Delim(Delimiter::SquareR), "")?;
} else {
let ident = utils::check_consume_or_err(tokens, TokenType::ident(""), "a")?;
typ = Type::Owned(ident.tt().unwrap_ident());
if let None = loc {
loc = Some(ident.loc().clone());
}
}
while let Some(reft) = ref_cnt.pop() {
match reft.tt() {
TokenType::Keyword(Keyword::Mut) => {
typ = Type::Ref {
inner: Box::new(typ),
mutable: true
}
},
TokenType::Punct(Punctuation::Ampersand) => {
typ = Type::Ref {
inner: Box::new(typ),
mutable: false
}
}
_ => unreachable!()
}
}
Ok(LocBox::new(&loc.unwrap(), typ))
}