146 lines
4 KiB
Rust
146 lines
4 KiB
Rust
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct LocatedToken {
|
|
pub start: usize,
|
|
pub end: usize,
|
|
pub token: Token,
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum Token {
|
|
Let,
|
|
Fn,
|
|
Return,
|
|
Equals,
|
|
OpenParen,
|
|
CloseParen,
|
|
OpenBracket,
|
|
CloseBracket,
|
|
OpenCurly,
|
|
CloseCurly,
|
|
Dot,
|
|
Comma,
|
|
Semicolon,
|
|
Colon,
|
|
True,
|
|
False,
|
|
Number(u32),
|
|
String(String),
|
|
Identifier(String),
|
|
}
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub struct Tokens(pub Vec<LocatedToken>);
|
|
|
|
impl From<Vec<LocatedToken>> for Tokens {
|
|
fn from(mut tokens: Vec<LocatedToken>) -> Tokens {
|
|
tokens.reverse();
|
|
Tokens(tokens)
|
|
}
|
|
}
|
|
|
|
impl Tokens {
|
|
pub fn peek(&mut self) -> Option<&LocatedToken> {
|
|
self.0.last()
|
|
}
|
|
pub fn next(&mut self) -> Option<LocatedToken> {
|
|
self.0.pop()
|
|
}
|
|
pub fn next_if(&mut self, token: &Token) -> Option<LocatedToken> {
|
|
self.0.pop_if(|t| match (t.token.clone(), token) {
|
|
(a, b) if a == *b => true,
|
|
(Token::Identifier(_), Token::Identifier(_)) => true,
|
|
(Token::Number(_), Token::Number(_)) => true,
|
|
(Token::String(_), Token::String(_)) => true,
|
|
_ => false,
|
|
})
|
|
}
|
|
pub fn between<T>(&mut self, start: &Token, end: &Token, parser: Parser<T>) -> ParseResult<T> {
|
|
if let Some(_start) = self.next_if(start) {
|
|
if let Some(result) = parser(self)? {
|
|
if let Some(_end) = self.next_if(end) {
|
|
Ok(Some(result))
|
|
} else {
|
|
Err(Error::UnexpectedTokenForParser(
|
|
"between".into(),
|
|
self.next(),
|
|
))
|
|
}
|
|
} else {
|
|
Err(Error::UnexpectedTokenForParser(
|
|
"between".into(),
|
|
self.next(),
|
|
))
|
|
}
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
pub fn one_of<T>(&mut self, parsers: Vec<Parser<T>>) -> ParseResult<T> {
|
|
for parser in parsers {
|
|
if let Some(result) = parser(self)? {
|
|
return Ok(Some(result));
|
|
}
|
|
}
|
|
Ok(None)
|
|
}
|
|
pub fn sep_by<T1, T2>(
|
|
&mut self,
|
|
separator: &Token,
|
|
parser1: Parser<T1>,
|
|
parser2: Parser<T2>,
|
|
) -> ParseResult<(T1, T2)> {
|
|
if let Some(t1) = parser1(self)? {
|
|
let _sep = self
|
|
.next_if(separator)
|
|
.ok_or(Error::UnexpectedEndOfInput("between".into()))?;
|
|
if let Some(t2) = parser2(self)? {
|
|
Ok(Some((t1, t2)))
|
|
} else {
|
|
Err(Error::UnexpectedTokenForParser(
|
|
"sep_by".into(),
|
|
self.next(),
|
|
))
|
|
}
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
pub fn many_sep_by<T>(&mut self, separator: &Token, parser: Parser<T>) -> ParseResult<Vec<T>> {
|
|
if let Some(first) = parser(self)? {
|
|
let mut results = vec![first];
|
|
while let Some(_) = self.next_if(&separator) {
|
|
if let Some(result) = parser(self)? {
|
|
results.push(result);
|
|
} else {
|
|
return Err(Error::UnexpectedTokenForParser(
|
|
"sep_by_many".into(),
|
|
self.next(),
|
|
));
|
|
}
|
|
}
|
|
Ok(Some(results))
|
|
} else {
|
|
Ok(None)
|
|
}
|
|
}
|
|
pub fn many<T>(&mut self, parser: Parser<T>) -> ParseResult<Vec<T>> {
|
|
let mut results = vec![];
|
|
while let Some(result) = parser(self)? {
|
|
results.push(result);
|
|
}
|
|
Ok(Some(results))
|
|
}
|
|
}
|
|
|
|
pub type Parser<T> = fn(&mut Tokens) -> ParseResult<T>;
|
|
pub type ParseResult<T> = Result<Option<T>, Error>;
|
|
|
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
|
pub enum Error {
|
|
UnexpectedToken {
|
|
expected: Token,
|
|
got: Option<LocatedToken>,
|
|
},
|
|
UnexpectedEndOfInput(String),
|
|
UnexpectedTokenForParser(String, Option<LocatedToken>),
|
|
}
|