3个版本
0.1.2 | 2024年1月19日 |
---|---|
0.1.1 | 2024年1月18日 |
0.1.0 | 2024年1月17日 |
187 在 编程语言
每月 25次下载
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,
...,
},
...,
);
它生成包含Token
、LexerError
、LexerResult
和Lexer
的模块gen
。
现在您可以调用Token::tokenize
来对字符串进行标记,它应返回一个实现Iterator
的Lexer
实例。
每次迭代,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