Add token matching functions and macros

Signed-off-by: trivernis <trivernis@protonmail.com>
develop
trivernis 4 years ago
parent 1eb5897e4e
commit 3917d4a804
Signed by: Trivernis
GPG Key ID: DFFFCC2C7A02DB45

@ -1,3 +1,4 @@
#[macro_use]
pub mod matching;
pub mod tokenizing;
mod utils;

@ -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(()))
}

@ -39,7 +39,12 @@ impl Token {
/// Checks if the inner value is of a given concrete type
pub fn is<T: 'static>(&self) -> bool {
self.inner.as_ref().type_id() == TypeId::of::<T>()
self.inner_type_id() == TypeId::of::<T>()
}
/// Returns the TypeID of the inner stored type
pub fn inner_type_id(&self) -> TypeId {
self.inner.as_ref().type_id()
}
}

Loading…
Cancel
Save