首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
逆向工程
发新帖
1
1
[分享]Lexer简单词法解析器入门
发表于: 2026-4-20 12:17
1231
[分享]Lexer简单词法解析器入门
mb_binusgki
2026-4-20 12:17
1231
# 前言 在上章实现了简单的解释器, 紧接着需要实现将 "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"); } ``` # 总结 此节为实现简单的词法解析器,为后续实现完整编译器做准备,欢迎讨论 如有错漏 请留言!
传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!!
#调试逆向
#系统底层
#软件保护
#VM保护
#加密算法
#问题讨论
#其他内容
收藏
・
1
点赞
・
1
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
我的小拇指啊
感谢你的积极参与,期待更多精彩内容!
2026-4-20 21:09
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
0
)
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
mb_binusgki
29
发帖
6
回帖
0
RANK
关注
私信
他的文章
[分享]注册表回调内核通信
376
[分享]简单编译器实现
1867
[分享]Lexer简单词法解析器入门
1231
[分享]vm解释器入门2
1288
[分享]vm解释器入门
1587
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部