use crate::{ ast::{Type, TypeArguments, INFER_TYPE}, lexer::{Spanned, Token}, }; use super::{Parser, ParserError}; impl<'a> Parser<'a> { pub fn ask_type(&mut self) -> Result, ParserError> { if let Spanned(Token::NumberLiteral(_), _) = self.tokens.peek()? { let Spanned(number, span) = self._ask_number_literal()?; return Ok(Spanned( Type { name: number.to_string(), arguments: TypeArguments::None, }, span, )); }; let Spanned(name, span) = self.ask_ident()?; if name == INFER_TYPE { return Ok(Spanned(Type::infer(), span)); } let mut arguments = TypeArguments::None; if let Spanned(crate::lexer::Token::LeftArrow, _) = self.tokens.peek()? { self.eat(); // eat `<` let mut args = vec![]; args.push(Box::new(self.ask_type()?.0)); match self.tokens.peek()?.0 { Token::Comma => self.eat(), Token::RightArrow => {} _ => return Err(self.expected("a comma or closing angle brackets")), }; loop { match self.tokens.peek()? { Spanned(Token::Ident(_) | Token::NumberLiteral(_), _) => { args.push(Box::new(self.ask_type()?.0)); match self.tokens.peek()?.0 { Token::Comma => self.eat(), Token::RightArrow => {} _ => return Err(self.expected("a comma or closing angle brackets")), } } Spanned(Token::RightArrow, _) => { self.eat(); break; } _ => return Err(self.expected("closing angle brackets or a type name")), } } arguments = TypeArguments::AngleBracketed(args); }; Ok(Spanned(Type { name, arguments }, span + self.tokens.span())) } }