ableos_userland/programs/aidl/src/parser.rs

209 lines
6.5 KiB
Rust

use logos::{Lexer, Logos, SpannedIter};
use crate::{
ast::{IDLModule, Item, ItemAlias, ItemConstant, ItemInterface, 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_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::Type),
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(name, nSp) = self.ask_ident()?;
Ok(Spanned::new(
UseDecl { module: name },
[kSp, nSp, self.semi()?],
))
}
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,
}