forked from AbleOS/ableos_userland
151 lines
4.2 KiB
Rust
151 lines
4.2 KiB
Rust
use logos::{Logos, SpannedIter};
|
|
|
|
use crate::{
|
|
ast::{IDLModule, Item, ItemInterface, ItemType, UseDecl},
|
|
lexer::{Span, Spanned, Token, Ident},
|
|
};
|
|
use std::{
|
|
iter::{Iterator, Peekable, Filter},
|
|
ops::Range,
|
|
};
|
|
|
|
type Wtf<'a> = Peekable<
|
|
Filter<SpannedIter<'a, Token>, Box<dyn Fn(&(Result<Token, ()>, Range<usize>)) -> bool>>,
|
|
>;
|
|
|
|
struct TokenIterator<'a> {
|
|
spanned: Wtf<'a>,
|
|
}
|
|
|
|
fn token_is_not_comment((ref a, ..): &(Result<Token, ()>, Range<usize>)) -> bool {
|
|
!matches!(a, Err(_) | Ok(Token::Comment(..)))
|
|
}
|
|
|
|
impl<'a> TokenIterator<'a> {
|
|
pub fn new(src: &'a str) -> Self {
|
|
let spanned = Token::lexer(src)
|
|
.spanned()
|
|
.filter(
|
|
Box::new(token_is_not_comment) as Box<dyn Fn(&(Result<Token, ()>, Range<usize>)) -> bool>,
|
|
)
|
|
.peekable();
|
|
|
|
Self { spanned }
|
|
}
|
|
pub fn next(&mut self) -> Option<Spanned<Token>> {
|
|
let nxt = self
|
|
.spanned
|
|
.next()
|
|
.and_then(|(token, span)| Some(Spanned(token.ok()?, Span(span))));
|
|
println!("[NEXT] {:#?}", nxt);
|
|
nxt
|
|
}
|
|
|
|
pub fn peek(&mut self) -> Option<Spanned<&Token>> {
|
|
let peek = self
|
|
.spanned
|
|
.peek()
|
|
.and_then(|(token, span)| Some(Spanned(token.as_ref().ok()?, Span(span.clone()))));
|
|
println!("[PEEK] {:#?}", peek);
|
|
peek
|
|
}
|
|
}
|
|
|
|
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) -> Option<Spanned<Token>> {
|
|
if matcher(self.tokens.peek()?.0) {
|
|
self.tokens.next()
|
|
} else {
|
|
None
|
|
}
|
|
}
|
|
|
|
fn semi(&mut self) -> Option<Span> {
|
|
Some(self.get_real(|token| matches!(token, Token::Semicolon))?.1)
|
|
}
|
|
|
|
fn ask_ident(&mut self) -> Option<Spanned<String>> {
|
|
Some(crate::unwrap_match!(
|
|
self.get_real(|token| matches!(token, Token::Ident(Ident::Other(_))))?,
|
|
Spanned(Token::Ident(Ident::Other(ident)), span) =>
|
|
Spanned(ident, span)
|
|
))
|
|
}
|
|
|
|
fn ask_interface(&mut self) -> Option<Spanned<ItemInterface>> {
|
|
let Spanned(_, kSp) =
|
|
self.get_real(|token| matches!(token, Token::Ident(Ident::Interface)))?;
|
|
let Spanned(ident, iSp) = self.ask_ident()?;
|
|
|
|
Some(Spanned::new(
|
|
ItemInterface {
|
|
name: ident,
|
|
functions: vec![],
|
|
},
|
|
[kSp, iSp, self.semi()?],
|
|
))
|
|
}
|
|
|
|
fn ask_typealias(&mut self) -> Option<Spanned<ItemType>> {
|
|
let Spanned(_, kSp) =
|
|
self.get_real(|token| matches!(token, Token::Ident(Ident::Type)))?;
|
|
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()?;
|
|
|
|
Some(Spanned::new(
|
|
ItemType { name, referree },
|
|
[kSp, nSp, eqSp, rSp, self.semi()?],
|
|
))
|
|
}
|
|
|
|
fn ask_item(&mut self) -> Option<Spanned<Item>> {
|
|
Some(match self.tokens.peek()?.0 {
|
|
Token::Ident(Ident::Other(_)) => None?,
|
|
Token::Ident(keyword) => match keyword {
|
|
Ident::Interface => self.ask_interface()?.map(Item::Interface),
|
|
Ident::Type => self.ask_typealias()?.map(Item::Type),
|
|
_ => None?,
|
|
},
|
|
_ => None?,
|
|
})
|
|
}
|
|
|
|
fn ask_use(&mut self) -> Option<Spanned<UseDecl>> {
|
|
let Spanned(_, kSp) =
|
|
self.get_real(|token| matches!(token, Token::Ident(Ident::Use)))?;
|
|
let Spanned(name, nSp) = self.ask_ident()?;
|
|
|
|
Some(Spanned::new(
|
|
UseDecl { module: name },
|
|
[kSp, nSp, self.semi()?],
|
|
))
|
|
}
|
|
|
|
pub fn parse(mut self) -> IDLModule {
|
|
IDLModule {
|
|
uses: fill_while(|| self.ask_use()),
|
|
items: fill_while(|| self.ask_item()),
|
|
}
|
|
}
|
|
}
|
|
|
|
fn fill_while<T>(mut f: impl FnMut() -> Option<Spanned<T>>) -> Vec<T> {
|
|
let mut real = vec![];
|
|
while let Some(Spanned(t, _)) = f() {
|
|
real.push(t);
|
|
}
|
|
real
|
|
}
|