21 个版本 (4 个稳定)

2.2.0 2021 年 4 月 23 日
2.1.1 2021 年 4 月 23 日
0.3.6 2021 年 1 月 22 日
0.3.3 2020 年 9 月 2 日
0.1.7 2020 年 7 月 29 日

#547异步

Download history 28/week @ 2024-03-11 19/week @ 2024-03-18 29/week @ 2024-03-25 41/week @ 2024-04-01 43/week @ 2024-04-08 32/week @ 2024-04-15 27/week @ 2024-04-22 32/week @ 2024-04-29 38/week @ 2024-05-06 21/week @ 2024-05-13 20/week @ 2024-05-20 25/week @ 2024-05-27 27/week @ 2024-06-03 33/week @ 2024-06-10 23/week @ 2024-06-17 30/week @ 2024-06-24

每月 115 次下载
5 个 Crates 中使用 (2 个直接)

自定义许可

20KB
438 代码行

Charred

此 crate 提供了一个通用的异步词法分析器,该分析器在 tokio 上操作文件。标记使用提供的异步闭包进行解析。

用法

use crate::error::TapeResult;
use crate::input_reader::InputReader;
use crate::lexer::Lexer;
use crate::token::{Token, TokenCheckerFn};
use std::io::Cursor;
use std::sync::Arc;

struct NumberToken(i32);
struct StringToken(String);
struct WhiteSpaceToken;

async fn parse_number_token(reader: &mut InputReader) -> TapeResult<Option<Token>> {
    let mut num = String::new();
    while !reader.check_eof().await && reader.peek().await?.is_numeric() {
        num.push(reader.consume().await?);
    }
    if num.is_empty() {
        Ok(None)
    } else {
        Ok(Some(Token::new(NumberToken(num.parse::<i32>().unwrap()))))
    }
}

async fn parse_whitespace_token(reader: &mut InputReader) -> TapeResult<Option<Token>> {
    let mut count = 0;
    while !reader.check_eof().await && reader.peek().await?.is_whitespace() {
        reader.consume().await?;
        count += 1;
    }
    if count > 0 {
        Ok(Some(Token::new(WhiteSpaceToken)))
    } else {
        Ok(None)
    }
}

async fn parse_string_token(reader: &mut InputReader) -> TapeResult<Option<Token>> {
    let mut value = String::new();
    while !reader.check_eof().await
        && !reader.peek().await?.is_numeric()
        && !reader.peek().await?.is_whitespace()
    {
        value.push(reader.consume().await?);
    }
    if value.is_empty() {
        Ok(None)
    } else {
        Ok(Some(Token::new(StringToken(value))))
    }
}

#[tokio::main]
async fn main() {
    // functions that try to parse the token into an object
    let checkers: Vec<TokenCheckerFn> = vec![
        Arc::new(|reader| Box::pin(parse_number_token(reader))),
        Arc::new(|reader| Box::pin(parse_whitespace_token(reader))),
        Arc::new(|reader| Box::pin(parse_string_token(reader))),
    ];
    // input reader encapsulates (almost) any type that implements AsyncBufRead
    let input_reader = InputReader::new(Cursor::new("Word 12"));
    let mut lexer = Lexer::new(input_reader, checkers);

    // scan starts scanning the provided input
    let tokens = lexer.scan().await.unwrap();
    assert!(!tokens.is_empty());

    let mut tokens = tokens.into_iter();
    // use the is, try_as and try_into methods on the token type to get the underlying value
    assert!(tokens.next().unwrap().is::<StringToken>());
    assert!(tokens.next().unwrap().is::<WhiteSpaceToken>());
    assert!(tokens.next().unwrap().is::<NumberToken>());
}

许可

Apache-2.0

依赖

~2.5–4MB
~69K SLoC