-
-
[分享]Lexer简单词法解析器入门
-
发表于: 1天前 361
-
前言
在上章实现了简单的解释器, 紧接着需要实现将 "a = 1 + 2" 这样的字符串语法编译成 MOV R0, 1; ADD R0, 2; 这样的代码, 这其中就需要用到词法分析器
将"a = 1 + 2"字符串形式分为{"a", "=", "1", "+", "2"}为第一步, 第二步还需分类{"1", "2"}为数字, {"a"}为变量, {"=", "+"}为操作符
并且还需适配无论是 "a=1+2" 还是 "a = 1 + 2" 又或者 "a =1 +2" 等形式都能正常识别
一、定义类型和结构
定义基础类型,其中包含变量、数字、操作符、结束符等,目前操作符只实现加法 后续可自由添加补充
enum TokenType {
TOK_IDENT, // 变量名:a, b
TOK_NUMBER, // 数字:1, 2
TOK_PLUS, // +
TOK_ASSIGN, // =
TOK_END // 结束
};
定义Token结构,其中包含类型和原始文本
struct Token {
TokenType type;
std::string text; // 原始文本(如 "a", "123")
};
二、定义词法解析函数
此函数为核心解析函数,调用者通过调用Lexer(const std::string& input)构造方法对input和pos进行赋值,再调用std::vector<Token> tokenize()进行词法分析
其中词法分析tokenize函数为单字符循环分析,逻辑为遇到空格跳过,支持对于变量、数字、符号的识别
并且实现了Token readIdent()读取完整变量名,逻辑为变量名由字母+数字组成,循环读取直到遇到空格或其他符号,以及readNumber() 读取完整数字的实现
class Lexer {
public:
Lexer(const std::string& input)
: input(input), pos(0) {
}
std::vector<Token> tokenize() {
std::vector<Token> tokens;
while (pos < input.size()) {
char c = input[pos];
// 1. 跳过空格
if (isspace(c)) {
pos++;
continue;
}
// 2. 标识符(变量名)
if (isalpha(c)) {
tokens.push_back(readIdent());
continue;
}
// 3. 数字
if (isdigit(c)) {
tokens.push_back(readNumber());
continue;
}
// 4. 符号
switch (c) {
case '+':
tokens.push_back({ TOK_PLUS, "+" });
pos++;
break;
case '=':
tokens.push_back({ TOK_ASSIGN, "=" });
pos++;
break;
default:
// 未知字符
pos++;
break;
}
}
//在 token 列表末尾加一个“结束标记”
tokens.push_back({ TOK_END, "" });
return tokens;
}
private:
std::string input;
size_t pos;
//读取一个“变量名”
Token readIdent() {
size_t start = pos;
while (pos < input.size() && isalnum(input[pos])) {//变量名组成: 字母 + 数字
pos++;
}
return { TOK_IDENT, input.substr(start, pos - start) };
}
//读取一个完整数字
Token readNumber() {
size_t start = pos;
while (pos < input.size() && isdigit(input[pos])) {
pos++;
}
return { TOK_NUMBER, input.substr(start, pos - start) };
}
};
三、测试
通过测试不同字符"a = 1 + 2"、"a=1+2"、"a=1+ 2"可正常识别,输入字符串输出token集合,token中又包含已分类好的类型以及字符串,方便后续处理
void Test1(const std::string str)
{
Lexer lexer(str);
auto tokens = lexer.tokenize();
for (auto& t : tokens) {
std::cout << t.text << " ";
}
std::cout << std::endl;
}
int main() {
Test1("a = 1 + 2");
Test1("a= 1 + 2");
Test1("a=1 + 2");
Test1("a=1+ 2");
Test1("a=1+2");
}
总结
此节为实现简单的词法解析器,为后续实现完整编译器做准备,欢迎讨论 如有错漏 请留言!
[培训]《冰与火的战歌:Windows内核攻防实战》!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
赞赏
他的文章
- [分享]简单编译器实现 415
- [分享]Lexer简单词法解析器入门 362
- [分享]vm解释器入门2 478
- [分享]vm解释器入门 708
- [分享]混淆、加密、反沙箱概念介绍 917
赞赏
雪币:
留言: