#token #tokenize #inner #parse

tokenate

一个用于编写标记化器的一些繁琐工作的工具

1 个不稳定版本

0.1.0 2022年4月15日

解析工具 中排名第 216


3 个crate中使用(通过 card_format

MIT 许可证

17KB
326

Tokenate

一个使字符串标记化更简单的库,它是惰性评估的,并且只会按需返回下一个标记。

您的起点是InnerTokenizer,它旨在成为您实际标记化器的子类,提供索引实用工具,因此您可以关注字符的消耗。您将需要的最主要的方法是 "start_token" "next" "peek" 和 "unpeek",然后最后是 "token_res",它将构建带有行号和值的Token。其他方法如 "follow"、"follow_fn" 和 "take_while" 是用于更轻松地获取字符串和数字的帮助程序

Token::value 是泛型的,允许您选择定义您语言中的标记的外观。

use tokenate::*;

// Define the Tokens you will want to recieve
#[derive(Clone, Debug, PartialEq)]
pub enum TKind {
    GreaterEqual,
    Ident(String),
    Num(String),
}

//Crate your tokenizer include the inner
struct TestTok<'a> {
    tk: InnerTokenizer<'a>,
}

//A util method for checking we have a char
fn num_digit(c: char) -> bool {
    c >= '0' && c <= '9'
}


impl<'a> TestTok<'a> {
    // When created initialize the InnerTokenizer
    pub fn new(s: &'a str) -> Self {
        TestTok {
            tk: InnerTokenizer::new(s),
        }
    }


    // TokenRes<T> is Result<Option<Token<T>>,TErr>
    pub fn next(&mut self) -> TokenRes<'a, TKind> {
        //Skip characters we don't care about
        self.tk.skip(char::is_whitespace);
        //Begin the token
        self.tk.start_token();
        // Use peek_char to decide wich kind of token to make
        match self.tk.peek_char() {
            Some(c) if num_digit(c) => self.tk.take_while(num_digit, |s| Ok(TKind::Num(s.to_string()))),
            Some('>') => self.tk.follow('=', TKind::GreaterEqual),
            Some(c) if char::is_alphabetic(c) => self
                .tk
                .take_while(char::is_alphabetic, |s| Ok(TKind::Ident(s.to_string()))),

            _ => self.tk.expected("A legal token".to_string()),
        }
    }
}


//A test function
fn main() {
    let s = "a >= 54";
    let mut tt = TestTok::new(s);
    assert_eq!(
        tt.next().unwrap().unwrap().value,
        TKind::Ident("a".to_string())
    );
    assert_eq!(tt.next().unwrap().unwrap().value, TKind::GreaterEqual,);
    assert_eq!(
        tt.next().unwrap().unwrap().value,
        TKind::Num("54".to_string())
    );
}

没有运行时依赖