Add token matching functions and macros
Signed-off-by: trivernis <trivernis@protonmail.com>develop
parent
1eb5897e4e
commit
3917d4a804
@ -0,0 +1,56 @@
|
||||
use crate::do_match;
|
||||
use crate::matching::MatchResult;
|
||||
use crate::tokenizing::{Token, TokenReader};
|
||||
use std::any::TypeId;
|
||||
|
||||
/// Matches exactly one token
|
||||
pub async fn match_one<T: 'static>(reader: &mut TokenReader) -> MatchResult<&Token> {
|
||||
let token = if reader.peek_is::<T>() {
|
||||
reader.consume()
|
||||
} else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
Ok(Some(token))
|
||||
}
|
||||
|
||||
/// Matches many tokens at once by TypeId
|
||||
pub async fn match_many<'a, I: IntoIterator<Item = &'a TypeId>>(
|
||||
reader: &mut TokenReader,
|
||||
ids: I,
|
||||
) -> MatchResult<&Token> {
|
||||
for id in ids {
|
||||
if &reader.peek().inner_type_id() == id {
|
||||
return Ok(Some(reader.consume()));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
/// Matches many tokens at once by TypeId
|
||||
pub async fn match_many_mul<'a, I: IntoIterator<Item = &'a TypeId> + Clone>(
|
||||
reader: &mut TokenReader,
|
||||
ids: I,
|
||||
) -> MatchResult<usize> {
|
||||
let mut count = 0;
|
||||
while match_many(reader, ids.clone()).await?.is_some() {
|
||||
count += 1;
|
||||
}
|
||||
|
||||
Ok(Some(count))
|
||||
}
|
||||
|
||||
/// Matches many tokens at least once by TypeId
|
||||
pub async fn match_many_mul_plus<'a, I: IntoIterator<Item = &'a TypeId> + Clone>(
|
||||
reader: &mut TokenReader,
|
||||
ids: I,
|
||||
) -> MatchResult<usize> {
|
||||
let count = do_match!(match_many_mul(reader, ids));
|
||||
|
||||
if count > 0 {
|
||||
Ok(Some(count))
|
||||
} else {
|
||||
Ok(None)
|
||||
}
|
||||
}
|
@ -0,0 +1,16 @@
|
||||
use crate::TapeResult;
|
||||
|
||||
mod matchers;
|
||||
|
||||
pub type MatchResult<T> = TapeResult<Option<T>>;
|
||||
pub use matchers::*;
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! do_match {
|
||||
($matcher:expr) => {
|
||||
match $matcher.await? {
|
||||
Some(inner) => inner,
|
||||
None => return Ok(None),
|
||||
}
|
||||
};
|
||||
}
|
@ -1,4 +1,5 @@
|
||||
mod test_input;
|
||||
mod test_lexer;
|
||||
mod test_matching;
|
||||
mod test_token;
|
||||
mod test_token_reader;
|
||||
|
@ -0,0 +1,70 @@
|
||||
use crate::do_match;
|
||||
use crate::matching::{match_many, match_many_mul, match_many_mul_plus, match_one, MatchResult};
|
||||
use crate::tokenizing::TokenReader;
|
||||
use crate::tokenizing::{EOFToken, Token};
|
||||
use std::any::TypeId;
|
||||
|
||||
struct AToken;
|
||||
struct BToken;
|
||||
struct CToken;
|
||||
|
||||
fn get_reader() -> TokenReader {
|
||||
let tokens = vec![
|
||||
Token::new(AToken),
|
||||
Token::new(BToken),
|
||||
Token::new(AToken),
|
||||
Token::new(CToken),
|
||||
Token::new(CToken),
|
||||
Token::new(EOFToken),
|
||||
];
|
||||
|
||||
TokenReader::new(tokens)
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn it_works() {
|
||||
let mut reader = get_reader();
|
||||
assert!(match_one::<AToken>(&mut reader).await.unwrap().is_some());
|
||||
|
||||
assert!(match_many(
|
||||
&mut reader,
|
||||
&[TypeId::of::<AToken>(), TypeId::of::<BToken>()],
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.is_some());
|
||||
|
||||
assert_eq!(
|
||||
match_many_mul(
|
||||
&mut reader,
|
||||
&[TypeId::of::<AToken>(), TypeId::of::<CToken>()],
|
||||
)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap(),
|
||||
3
|
||||
);
|
||||
|
||||
assert!(match_one::<EOFToken>(&mut reader).await.unwrap().is_some())
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn test_macro_matching() {
|
||||
let mut reader = get_reader();
|
||||
assert!(match_with_macro(&mut reader).await.unwrap().is_some());
|
||||
}
|
||||
|
||||
async fn match_with_macro(reader: &mut TokenReader) -> MatchResult<()> {
|
||||
do_match!(match_one::<AToken>(reader));
|
||||
do_match!(match_many(
|
||||
reader,
|
||||
&[TypeId::of::<AToken>(), TypeId::of::<BToken>()]
|
||||
));
|
||||
do_match!(match_many_mul_plus(
|
||||
reader,
|
||||
&[TypeId::of::<CToken>(), TypeId::of::<AToken>()]
|
||||
));
|
||||
do_match!(match_one::<EOFToken>(reader));
|
||||
|
||||
Ok(Some(()))
|
||||
}
|
Loading…
Reference in New Issue