3个版本

0.1.2 2024年1月19日
0.1.1 2024年1月18日
0.1.0 2024年1月17日

187编程语言

每月 25次下载

MIT 许可证

20KB
203

模式词法分析器

我个人的词法分析器实现。

原理

此词法分析器利用Pattern特质来查找标记。
想法是创建Tokens,解释如何使用Pattern进行匹配,并从匹配的String值构建它们。

模式

字符串Pattern特质。

实现此特质类型的类型可以用作&str的模式,默认情况下,它实现了以下类型。

模式类型 匹配条件
char 包含在字符串中
&str 子串
String 子串
&[char] 任何字符匹配
&[&str] 任何字符串匹配
F: Fn(&str) -> bool F返回true表示子串(慢速)
Regex Regex匹配子串

用法

lexer!宏匹配以下语法。

lexer!(
    // Ordered by priority
    NAME(optional types, ...) {
        impl Pattern => |value: String| -> Token,
        ...,
    },
    ...,
);

它生成包含TokenLexerErrorLexerResultLexer的模块gen

现在您可以调用Token::tokenize来对字符串进行标记,它应返回一个实现IteratorLexer实例。
每次迭代,Lexer都会尝试匹配给定的一个Pattern,并返回一个从最佳匹配构建的LexerResult<Token>

示例

以下是一个简单数学词法分析器的示例。

lexer!(
    // Different operators
    OPERATOR(char) {
        '+' => |_| Token::OPERATOR('+'),
        '-' => |_| Token::OPERATOR('-'),
        '*' => |_| Token::OPERATOR('*'),
        '/' => |_| Token::OPERATOR('/'),
        '=' => |_| Token::OPERATOR('='),
    },
    // Integer numbers
    NUMBER(usize) {
        |s: &str| s.chars().all(|c| c.is_digit(10))
            => |v: String| Token::NUMBER(v.parse().unwrap()),
    },
    // Variable names
    IDENTIFIER(String) {
        regex!(r"[a-zA-Z_$][a-zA-Z_$0-9]*")
            => |v: String| Token::IDENTIFIER(v),
    },
    WHITESPACE {
        [' ', '\n'] => |_| Token::WHITESPACE,
    },
);

这会展开成以下枚举和结构。

mod gen {
    pub enum Token {
        OPERATOR(char),
        NUMBER(usize),
        IDENTIFIER(String),
        WHITESPACE,
    }

    pub struct Lexer {...}
    pub struct LexerError {...}
    pub type LexerResult<T> = Result<T, LexerError>;
}

之后您也可以使用它们。

use gen::*;

let mut lex = Token::tokenize("x_4 = 1 + 3 = 2 * 2");
assert_eq!(lex.nth(2), Some(Ok(Token::OPERATOR('='))));
assert_eq!(lex.nth(5), Some(Ok(Token::NUMBER(3))));

// Our lexer doesn't handle parenthesis...
let mut err = Token::tokenize("x_4 = (1 + 3)");
assert!(err.nth(4).is_some_and(|res| res.is_err()));

依赖项

约2-3MB
约53K SLoC