108 lines
2.5 KiB
Rust
108 lines
2.5 KiB
Rust
use std::iter::Peekable;
|
|
|
|
use logos::Logos;
|
|
|
|
use crate::{Ast, Kind};
|
|
|
|
type Error = String;
|
|
|
|
struct Parser<'s> {
|
|
lex: Peekable<Lexer<'s>>,
|
|
errors: Vec<Error>,
|
|
}
|
|
|
|
pub(crate) fn parse(s: &str) -> (Vec<Ast>, Vec<Error>) {
|
|
let lex = Lexer {
|
|
lex: Kind::lexer(s),
|
|
}
|
|
.peekable();
|
|
|
|
let mut parser = Parser {
|
|
lex,
|
|
errors: vec![],
|
|
};
|
|
|
|
let mut trees = Vec::new();
|
|
|
|
while parser.lex.peek().is_some() {
|
|
if let Some(t) = parser.parse() {
|
|
trees.push(t);
|
|
}
|
|
}
|
|
|
|
(trees, parser.errors)
|
|
}
|
|
|
|
impl<'s> Parser<'s> {
|
|
fn parse(&mut self) -> Option<Ast<'s>> {
|
|
let Token { kind, span, src } = self.next()?;
|
|
|
|
// match tok {
|
|
// Token::Lparen => todo!(),
|
|
// Token::Rparen => {
|
|
// self.errors.push(format!("Unexpected lparen "));
|
|
// self.parse()
|
|
// }
|
|
// Token::Symbol => Some(Ast::Leaf(self.lex.str())),
|
|
// Token::String => todo!(),
|
|
// Token::Error => todo!(),
|
|
// }
|
|
Some(match kind {
|
|
Kind::Lparen => {
|
|
let mut bits = Vec::new();
|
|
|
|
while self.lex.peek()?.kind != Kind::Rparen {
|
|
bits.push(self.parse()?);
|
|
}
|
|
|
|
let rp = self.next()?;
|
|
assert_eq!(rp.kind, Kind::Rparen);
|
|
|
|
Ast::Tree(bits)
|
|
}
|
|
Kind::Rparen => {
|
|
self.errors.push(format!("Unexpected `)` at {:?}", span));
|
|
// Keep going from the next token
|
|
return self.parse();
|
|
}
|
|
Kind::Symbol | Kind::String | Kind::Boolean => Ast::Leaf(src),
|
|
Kind::Error => unreachable!("Removed by Parser::next"),
|
|
})
|
|
}
|
|
|
|
fn next(&mut self) -> Option<Token<'s>> {
|
|
for tok in &mut self.lex {
|
|
if tok.kind == crate::Kind::Error {
|
|
self.errors
|
|
.push(format!("Bad token at {:?}: `{}`", tok.span, tok.src))
|
|
} else {
|
|
return Some(tok);
|
|
}
|
|
}
|
|
self.errors.push("Unexpected EOF".to_owned());
|
|
None
|
|
}
|
|
}
|
|
|
|
struct Lexer<'s> {
|
|
lex: logos::Lexer<'s, crate::Kind>,
|
|
}
|
|
|
|
impl<'s> Iterator for Lexer<'s> {
|
|
type Item = Token<'s>;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
self.lex.next().map(|kind| Token {
|
|
kind,
|
|
span: self.lex.span(),
|
|
src: self.lex.slice(),
|
|
})
|
|
}
|
|
}
|
|
|
|
struct Token<'s> {
|
|
kind: Kind,
|
|
span: logos::Span,
|
|
src: &'s str,
|
|
}
|