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_input;
|
||||||
mod test_lexer;
|
mod test_lexer;
|
||||||
|
mod test_matching;
|
||||||
mod test_token;
|
mod test_token;
|
||||||
mod test_token_reader;
|
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