推荐:Tiny Lexer - 一个极简的C语言词法分析器
我推荐一个非常小巧但完整的C语言词法分析器实现 - Tiny Lexer。它具有以下优点:
特点
- 代码量极小(约100行核心代码)
- 纯C实现,无外部依赖
- 易于理解和学习
- 包含完整的功能:标识符、数字、运算符识别等
核心代码实现
#include <stdio.h>
#include <ctype.h>
#include <string.h>
typedef enum {
TOKEN_EOF,
TOKEN_NUMBER,
TOKEN_IDENTIFIER,
TOKEN_OPERATOR,
TOKEN_UNKNOWN
} TokenType;
typedef struct {
TokenType type;
char value[32];
} Token;
Token get_next_token(const char** input) {
Token token = {TOKEN_UNKNOWN, {0}};
// 跳过空白字符
while (isspace(**input)) {
(*input)++;
}
// 检查文件结束
if (**input == '\0') {
token.type = TOKEN_EOF;
return token;
}
// 处理数字
if (isdigit(**input)) {
token.type = TOKEN_NUMBER;
int i = 0;
while (isdigit(**input) && i < sizeof(token.value)-1) {
token.value[i++] = *(*input)++;
}
token.value[i] = '\0';
return token;
}
// 处理标识符(字母开头)
if (isalpha(**input)) {
token.type = TOKEN_IDENTIFIER;
int i = 0;
while ((isalnum(**input) || **input == '_') && i < sizeof(token.value)-1) {
token.value[i++] = *(*input)++;
}
token.value[i] = '\0';
return token;
}
// 处理运算符
if (strchr("+-*/=(){};", **input)) {
token.type = TOKEN_OPERATOR;
token.value[0] = *(*input)++;
token.value[1] = '\0';
return token;
}
// 未知字符
token.value[0] = *(*input)++;
return token;
}
int main() {
const char* input = "int x = 42 + y;";
const char* p = input;
while (1) {
Token token = get_next_token(&p);
if (token.type == TOKEN_EOF) break;
const char* type_str;
switch (token.type) {
case TOKEN_NUMBER: type_str = "NUMBER"; break;
case TOKEN_IDENTIFIER: type_str = "IDENTIFIER"; break;
case TOKEN_OPERATOR: type_str = "OPERATOR"; break;
default: type_str = "UNKNOWN"; break;
}
printf("Token: %-12s Value: %s\n", type_str, token.value);
}
return 0;
}
学习价值
- 词法分析基本原理:展示了如何将输入流分解为token
- 状态机概念:通过条件判断实现了简单的状态转移
- 可扩展性:可以轻松添加更多token类型和规则
- 实用性:虽然简单,但包含了词法分析的核心功能
扩展建议
学习这个基本实现后,你可以尝试:
- 添加更多运算符和关键字识别
- 实现更复杂的数字格式(如浮点数)
- 添加错误处理机制
- 将其扩展为递归下降语法分析器
这个实现去除了所有不必要的复杂性,是学习编译原理前端技术的理想起点。