2 个版本
0.1.1 | 2024 年 1 月 14 日 |
---|---|
0.1.0 | 2024 年 1 月 14 日 |
#17 在 #lexical-analysis
22KB
239 代码行
词法分析器
我个人的词法分析器实现。
原则
词法分析器基于插件。这不是一个 解析器 也不是一个 编译器。
令牌
有 8 种预制的令牌类型(以下示例不是强制的)
TokenKind |
说明 | 示例 |
---|---|---|
KEYWORD |
保留字 | if return ... |
DELIMITER |
成对的分隔符符号 | () [] {} ... |
PUNCTUATION |
标点符号 | ; . ... |
OPERATOR |
操作参数的符号 | + - = ... |
COMMENT |
行或块注释 | // /* ... */ ... |
WHITESPACE |
不可打印的字符 | - |
LITERAL |
数值、逻辑、文本值 | 1 true "true" ... |
IDENTIFIER |
程序中指定的名称 | x temp PRINT ... |
这些令牌类型(除 IDENTIFIER
)应使用可区分相同类型的名称构造。
每个 TokenKind
都可以与一个或多个 Pattern
关联,这些 Pattern
通过 Tokenizer
将它们与字符串匹配,从而生成一个 Token
。
词法分析器
词法分析器应该使用包含几个 Tokenizer
的 LexerBuilder
构造。
示例
简单的数学 Lexer
let plus = Tokenizer::new(TokenKind::OPERATOR("PLUS"), '+');
let minus = Tokenizer::new(TokenKind::OPERATOR("MINUS"), '-');
let star = Tokenizer::new(TokenKind::OPERATOR("STAR"), '*');
let slash = Tokenizer::new(TokenKind::OPERATOR("SLASH"), '/');
let equal = Tokenizer::new(TokenKind::OPERATOR("EQUAL"), '=');
let number = Tokenizer::new(TokenKind::LITERAL("NUMBER"), |s: &str| {
let mut dot_seen = false;
for ch in s.chars() {
if !ch.is_digit(10) && (ch != '.' || dot_seen) {
return false;
} else if ch == '.' {
dot_seen = true;
}
}
true
});
let id_regex = Regex::new(r"[a-zA-Z_$][a-zA-Z_$0-9]*").unwrap();
let id = Tokenizer::new(TokenKind::IDENTIFIER, id_regex);
let whitespace = Tokenizer::new(TokenKind::WHITESPACE("SPACE"), ' ');
let lexer = Lexer::builder()
.extend(vec![plus, minus, star, slash, equal, number, id, whitespace])
.build();
lexer.tokenize("x_4 = 2 + 2 = 4 * 0.5")?;
/* [Token { kind: IDENTIFIER, value: "x_4" },
Token { kind: WHITESPACE("SPACE"), value: " " },
Token { kind: OPERATOR("EQUAL"), value: "=" },
Token { kind: WHITESPACE("SPACE"), value: " " },
Token { kind: LITERAL("NUMBER"), value: "2" },
Token { kind: WHITESPACE("SPACE"), value: " " },
Token { kind: OPERATOR("PLUS"), value: "+" },
Token { kind: WHITESPACE("SPACE"), value: " " },
Token { kind: LITERAL("NUMBER"), value: "2" },
Token { kind: WHITESPACE("SPACE"), value: " " },
Token { kind: OPERATOR("EQUAL"), value: "=" },
Token { kind: WHITESPACE("SPACE"), value: " " },
Token { kind: LITERAL("NUMBER"), value: "4" },
Token { kind: WHITESPACE("SPACE"), value: " " },
Token { kind: OPERATOR("STAR"), value: "*" },
Token { kind: WHITESPACE("SPACE"), value: " " },
Token { kind: LITERAL("NUMBER"), value: "0.5" }] */
依赖项
~2.2–3MB
~55K SLoC