forked from AbleOS/ableos_userland
101 lines
4.0 KiB
Rust
101 lines
4.0 KiB
Rust
use std::collections::HashMap;
|
|
|
|
use crate::{
|
|
ast::{Expr, ExprMake, Literal, MakeStructure, NumberLiteral},
|
|
lexer::{Ident, NumberSuffix, Spanned, Token},
|
|
unwrap_match,
|
|
};
|
|
|
|
use super::{Parser, ParserError};
|
|
|
|
impl<'a> Parser<'a> {
|
|
pub fn ask_expr(&mut self) -> Result<Spanned<Expr>, ParserError> {
|
|
let Spanned(token, _) = self.tokens.peek()?;
|
|
Ok(match token {
|
|
Token::StringLiteral(_) | Token::NumberLiteral(_) | Token::CharLiteral(_) => {
|
|
self._ask_literal()?.map(Expr::Literal)
|
|
}
|
|
Token::Ident(Ident::Make) => {
|
|
self.eat();
|
|
match self.tokens.next()?.0 {
|
|
Token::Ident(Ident::Structure) => self
|
|
._ask_struct_init()?
|
|
.map(Box::new)
|
|
.map(ExprMake::Structure)
|
|
.map(Expr::Make),
|
|
_ => return Err(self.expected("a Make expression")),
|
|
}
|
|
}
|
|
_ => return Err(self.expected("an expression")),
|
|
})
|
|
}
|
|
|
|
fn _ask_literal(&mut self) -> Result<Spanned<Literal>, ParserError> {
|
|
let Spanned(token, mut span) = self.tokens.next()?;
|
|
Ok(match token {
|
|
Token::StringLiteral(string) => Spanned(Literal::String(string), span),
|
|
Token::CharLiteral(chr) => Spanned(Literal::Char(chr), span),
|
|
Token::NumberLiteral(number) => {
|
|
let lit = if let Spanned(Token::NumberSuffix(_), sp) = self.tokens.peek()? {
|
|
span += sp;
|
|
|
|
use NumberLiteral::*;
|
|
Literal::Number(
|
|
match unwrap_match!(
|
|
self.tokens.next()?, Spanned(Token::NumberSuffix(suffering), _) => suffering) // eat suffix
|
|
{
|
|
NumberSuffix::Ptr => Ptr(number as usize),
|
|
NumberSuffix::U8 => U8(number as u8),
|
|
NumberSuffix::I8 => I8(number as i8),
|
|
NumberSuffix::U16 => U16(number as u16),
|
|
NumberSuffix::I16 => I16(number as i16),
|
|
NumberSuffix::U32 => U32(number as u32),
|
|
NumberSuffix::I32 => I32(number as i32),
|
|
NumberSuffix::U64 => U64(number as u64),
|
|
NumberSuffix::I64 => I64(number),
|
|
_ => return Err(self.expected("a non-floating number suffix"))
|
|
},
|
|
)
|
|
} else {
|
|
Literal::Number(NumberLiteral::Infer(number))
|
|
};
|
|
|
|
Spanned(lit, span)
|
|
}
|
|
_ => return Err(self.expected("a literal")),
|
|
})
|
|
}
|
|
|
|
fn _ask_struct_init(&mut self) -> Result<Spanned<MakeStructure>, ParserError> {
|
|
let Spanned(name, nSp) = self.ask_ident()?;
|
|
let Spanned(_, _) = self.get_real(
|
|
|token| matches!(token, Token::LeftCurly),
|
|
"an opening curly brace (`{`)",
|
|
)?;
|
|
|
|
let mut params = HashMap::<String, Expr>::new();
|
|
|
|
loop {
|
|
match self.tokens.peek()?.0 {
|
|
Token::Ident(_) => {
|
|
let Spanned(ident, _) = self.ask_ident().unwrap();
|
|
self.get_real(|token| matches!(token, Token::Colon), "a colon")?;
|
|
let Spanned(value, _) = self.ask_expr()?;
|
|
params.insert(ident, value);
|
|
if let Token::Comma = self.tokens.peek()?.0 {
|
|
self.eat();
|
|
};
|
|
}
|
|
Token::RightCurly => break,
|
|
_ => return Err(self.expected("an identifier or a closing curly brace (`}`)")),
|
|
}
|
|
}
|
|
|
|
if let Spanned(Token::RightCurly, ccSp) = self.tokens.next()? {
|
|
return Ok(Spanned(MakeStructure { name, params }, nSp + ccSp));
|
|
};
|
|
|
|
Err(self.expected("something"))
|
|
}
|
|
}
|