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
74 lines
2.6 KiB
Rust
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))
|
|
}
|