forked from AbleOS/ableos_userland
241 lines
7.7 KiB
Rust
241 lines
7.7 KiB
Rust
use logos::{Lexer, Logos, SpannedIter};
|
|
|
|
use crate::{
|
|
ast::{IDLModule, Item, ItemAlias, ItemConstant, ItemInterface, ModulePath, UseDecl},
|
|
lexer::{Ident, Span, Spanned, Token},
|
|
};
|
|
use std::iter::{Filter, Iterator, Peekable};
|
|
|
|
type Wtf<'a> = Peekable<Filter<&'a mut Lexer<'a, Token>, Box<dyn Fn(&Result<Token, ()>) -> bool>>>;
|
|
|
|
struct TokenIterator<'a> {
|
|
lexer: Lexer<'a, Token>,
|
|
peeked: Option<Option<Token>>,
|
|
}
|
|
|
|
fn token_is_not_comment(a: &Result<Token, ()>) -> bool {
|
|
!matches!(a, Err(_) | Ok(Token::Comment(..)))
|
|
}
|
|
|
|
impl<'a> TokenIterator<'a> {
|
|
pub fn new(src: &'a str) -> Self {
|
|
let lexer = Token::lexer(src);
|
|
|
|
Self {
|
|
lexer,
|
|
peeked: None,
|
|
}
|
|
}
|
|
pub fn next(&mut self) -> Result<Spanned<Token>, ParserError> {
|
|
let n = match self.peeked.take() {
|
|
Some(thing) => thing,
|
|
None => self.lexer.find(token_is_not_comment).and_then(Result::ok),
|
|
};
|
|
let nxt = n.map(|token| Spanned(token, Span(self.lexer.span())));
|
|
println!("[NEXT] {:#?}", nxt);
|
|
nxt.ok_or(ParserError::UnexpectedEOF)
|
|
}
|
|
|
|
fn _peek(&mut self) -> Option<&Token> {
|
|
self.peeked
|
|
.get_or_insert_with(|| self.lexer.find(token_is_not_comment).and_then(Result::ok))
|
|
.as_ref()
|
|
}
|
|
|
|
pub fn peek(&mut self) -> Result<Spanned<&Token>, ParserError> {
|
|
let span = Span(self.lexer.span());
|
|
let peek = self._peek().map(|token| Spanned(token, span));
|
|
println!("[PEEK] {:#?}", peek);
|
|
peek.ok_or(ParserError::UnexpectedEOF)
|
|
}
|
|
|
|
pub fn current(&self) -> Spanned<String> {
|
|
Spanned(self.lexer.slice().to_owned(), Span(self.lexer.span()))
|
|
}
|
|
}
|
|
|
|
pub struct Parser<'a> {
|
|
tokens: TokenIterator<'a>,
|
|
}
|
|
|
|
impl<'a> Parser<'a> {
|
|
pub fn new(src: &'a str) -> Self {
|
|
Self {
|
|
tokens: TokenIterator::new(src),
|
|
}
|
|
}
|
|
|
|
fn get_real(
|
|
&mut self,
|
|
matcher: impl Fn(&Token) -> bool,
|
|
expected: &'static str,
|
|
) -> Result<Spanned<Token>, ParserError> {
|
|
if matcher(self.tokens.peek()?.0) {
|
|
self.tokens.next()
|
|
} else {
|
|
Err(self.unexpected(expected))
|
|
}
|
|
}
|
|
|
|
fn unexpected(&self, expected: &'static str) -> ParserError {
|
|
ParserError::Unexpected(expected.to_owned(), self.tokens.current())
|
|
}
|
|
|
|
fn semi(&mut self) -> Result<Span, ParserError> {
|
|
Ok(self
|
|
.get_real(|token| matches!(token, Token::Semicolon), "a semicolon")?
|
|
.1)
|
|
}
|
|
|
|
fn ask_ident(&mut self) -> Result<Spanned<String>, ParserError> {
|
|
Ok(crate::unwrap_match!(
|
|
self.get_real(|token| matches!(token, Token::Ident(Ident::Other(_))), "an identifier")?,
|
|
Spanned(Token::Ident(Ident::Other(ident)), span) =>
|
|
Spanned(ident, span)
|
|
))
|
|
}
|
|
|
|
fn ask_modpath(
|
|
&mut self,
|
|
end: impl Fn(&Token) -> bool,
|
|
) -> Result<Spanned<ModulePath>, ParserError> {
|
|
let mut segments = vec![];
|
|
let mut in_path_seg = false;
|
|
let mut waiting_next_seg = true;
|
|
let mut span = Span::ZERO;
|
|
|
|
loop {
|
|
match self.tokens.next()? {
|
|
Spanned(Token::Ident(Ident::Other(ident)), span_span)
|
|
if !in_path_seg && waiting_next_seg =>
|
|
{
|
|
span = span + span_span;
|
|
segments.push(ident);
|
|
in_path_seg = true;
|
|
waiting_next_seg = false;
|
|
}
|
|
Spanned(Token::Dot, span_span) if in_path_seg && !waiting_next_seg => {
|
|
span = span + span_span;
|
|
waiting_next_seg = true;
|
|
in_path_seg = false;
|
|
}
|
|
v if end(&v.0) && (in_path_seg || !waiting_next_seg) => {
|
|
span = span + v.1;
|
|
break;
|
|
}
|
|
_ => return Err(self.unexpected("a path segment")),
|
|
}
|
|
}
|
|
|
|
Ok(Spanned(ModulePath { segments }, span))
|
|
}
|
|
|
|
fn _ask_interface(&mut self) -> Result<Spanned<ItemInterface>, ParserError> {
|
|
let Spanned(_, kSp) = self.get_real(
|
|
|token| matches!(token, Token::Ident(Ident::Interface)),
|
|
"`Interface`",
|
|
)?;
|
|
let Spanned(ident, iSp) = self.ask_ident()?;
|
|
|
|
Ok(Spanned::new(
|
|
ItemInterface {
|
|
name: ident,
|
|
functions: vec![],
|
|
},
|
|
[kSp, iSp, self.semi()?],
|
|
))
|
|
}
|
|
|
|
fn ask_alias(&mut self) -> Result<Spanned<ItemAlias>, ParserError> {
|
|
let Spanned(_, kSp) = self.get_real(
|
|
|token| matches!(token, Token::Ident(Ident::Alias)),
|
|
"`Alias`",
|
|
)?;
|
|
let Spanned(name, nSp) = self.ask_ident()?;
|
|
|
|
let Spanned(_, eqSp) = self.get_real(|token| matches!(token, Token::Equals), "`=`")?;
|
|
let Spanned(referree, rSp) = self.ask_ident()?;
|
|
|
|
Ok(Spanned::new(
|
|
ItemAlias { name, referree },
|
|
[kSp, nSp, eqSp, rSp, self.semi()?],
|
|
))
|
|
}
|
|
|
|
fn ask_constant(&mut self) -> Result<Spanned<ItemConstant>, ParserError> {
|
|
Err(self.unexpected(""))
|
|
}
|
|
|
|
fn ask_item(&mut self) -> Result<Spanned<Item>, ParserError> {
|
|
Ok(match self.tokens.peek()?.0 {
|
|
Token::Ident(Ident::Other(_)) => {
|
|
Err(self.unexpected("a keyword, not just an identifier"))?
|
|
}
|
|
Token::Ident(keyword) => match keyword {
|
|
//Ident::Interface => self.ask_interface()?.map(Item::Interface),
|
|
Ident::Alias => self.ask_alias()?.map(Item::Alias),
|
|
Ident::Constant => self.ask_constant()?.map(Item::Constant),
|
|
_ => Err(self.unexpected("`Alias` or `Constant`"))?,
|
|
},
|
|
_ => Err(self.unexpected("a keyword"))?,
|
|
})
|
|
}
|
|
|
|
fn ask_use(&mut self) -> Result<Spanned<UseDecl>, ParserError> {
|
|
let Spanned(_, kSp) = {
|
|
match self.tokens.peek()? {
|
|
Spanned(Token::Ident(Ident::Use), _) => Ok(self.tokens.next()?),
|
|
_ => Err(ParserError::PleaseStopParsingUse),
|
|
}
|
|
}?;
|
|
let Spanned(module, nSp) = self.ask_modpath(|token| matches!(token, Token::Semicolon))?;
|
|
|
|
Ok(Spanned::new(UseDecl { module }, [kSp, nSp]))
|
|
}
|
|
|
|
pub fn parse(mut self) -> Result<IDLModule, ParserError> {
|
|
Ok(IDLModule {
|
|
uses: {
|
|
let mut real = vec![];
|
|
loop {
|
|
let r = self.ask_use();
|
|
match r {
|
|
Ok(Spanned(a, _)) => real.push(a),
|
|
Err(ParserError::UnexpectedEOF) => return Err(ParserError::UnexpectedEOF),
|
|
Err(ParserError::PleaseStopParsingUse) => break,
|
|
Err(unexpected @ ParserError::Unexpected(..)) => return Err(unexpected),
|
|
}
|
|
}
|
|
Ok(real)
|
|
}?,
|
|
items: fill_while(|| self.ask_item())?,
|
|
})
|
|
}
|
|
}
|
|
|
|
fn fill_while<T>(
|
|
mut f: impl FnMut() -> Result<Spanned<T>, ParserError>,
|
|
) -> Result<Vec<T>, ParserError> {
|
|
let mut real = vec![];
|
|
loop {
|
|
match f() {
|
|
Ok(Spanned(next, _)) => real.push(next),
|
|
Err(unexpected @ ParserError::Unexpected(..)) => return Err(unexpected),
|
|
Err(ParserError::UnexpectedEOF) => break,
|
|
Err(ParserError::PleaseStopParsingUse) => unreachable!(),
|
|
}
|
|
}
|
|
Ok(real)
|
|
}
|
|
|
|
#[derive(thiserror::Error, Debug)]
|
|
pub enum ParserError {
|
|
// expected, got
|
|
#[error("Unexpected `{_1}`, expected {_0}")]
|
|
Unexpected(String, Spanned<String>),
|
|
#[error("Unexpected end of file")]
|
|
UnexpectedEOF,
|
|
#[error("please stop.")]
|
|
PleaseStopParsingUse,
|
|
}
|