78 lines
2.8 KiB
Rust
78 lines
2.8 KiB
Rust
use anyhow::{Result, bail};
|
|
|
|
use crate::{cli::CliArgs, common::loc::LocBox, lerror, parser::{Delimiter, ast::{Ident, Program, expr::Expr, literal::Literal}}, tokeniser::Token, validator::predefined::get_builtin_from_name};
|
|
|
|
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(), &mut Program::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")?;
|
|
if let Some(t) = get_builtin_from_name(&ident.tt().unwrap_ident().0) {
|
|
typ = t;
|
|
} else {
|
|
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))
|
|
}
|