词法与语法分析器介绍
概述词法和语法可以使用正则表达式和BNF范式表达而最终描述文法含义的事状态转换图Lex与YACC词法分析器Lex词法分析词Lex是一种生成词法分析的工具描述器是识别文本中词汇模式的程序这些词汇模式是在特殊的句子结构中定义的Lex 接收到文件或文本形式的输入时会将文本与常规表达式进行匹配一次读入一个输入字符直到找到一个匹配的模式如果能够找到一个匹配的模式Lex就执行相关的动作(比如返回一个标记Token)。另外如果没有可以匹配的常规表达式将会停止停止进一步的处理Lex将显示一个错误信息Lex 和 C语言是强耦合的一个.lex文件通过Lex解析并生成C的输出文件这些文件被编译为词法分析器的可执行版本lex 或 .l 文件在格式上分为以下3段全局变量声明部分词法规则部分函数定义部分Lex 变量表变量名详细解释yyinFILE* 类型。它指向lexer 正在解析的当前文件yyoutFILE* 类型。它指向记录lexer输出的位置。默认情况下yyin 和 yyout 都指向标准输入和输出yytext匹配模式的文本存储在这一变量中(char*)yyleng给出匹配模式的长度yylineno提供当前的行数信息(lexer不一定支持)Lex 函数表函数名详细解释yylex()这一函数开始分析。它由Lex自动生成yywrap()这一函数在文件(或输入)的末尾调用。如果函数的返回值是1就停止解析。它可以用来解析多个文件yyless(int)这一函数可以用来输出除来前n个字符外的所有读出标记yymore()这一函数告诉Lexer将下一个标记附加到当前标记后代码文件 a.l%{ #include stdio.h extern char *yytext; extern FILE *yyin; int count 0; %} %%// 两个百分号标记指出了 Lex 程序中这一段的结束和第二段的开始 \$[a-zA-Z][a-zA-Z0-9]* {count; printf( 变量%s, yytext);} [0-9\/.-] printf(数字%s, yytext); printf(被赋值为); \n printf(\n); [ \t] /* 忽略空格 */; %% // 函数定义部分 int main(int avgs, char *avgr[]) { yyin fopen(avgr[1], r); if (!yyin) { return 0; } yylex(); printf(变量总数为:%d\n, count); fclose(yyin); return 1; }对于以上代码解释如下全局变量声明部分: 声明了一个int型全局变量count用来记录变量的个数规则部分: 第1个规则是找符号开头、第 2 个符号为字母且后面为字符或数字的变量类似于 符号开头、第2个符号为字母且后面为字符或数字的变量类似于符号开头、第2个符号为字母且后面为字符或数字的变量类似于a,并计数加1. 同时将满足条件的yytext输出第2个规则是找数字第3个规则是找 号第4个规则是输出\n; 第5个规则是忽略空格函数定义部分: 打开一个文件然后调用yylex 函数进行词法解析输出变量的技术最后调用fclose关闭文件lex 代码编译lex a.l gcc lex.yy.c -o test -ll测试文件 file$a 1 $b 2执行如下命令./test file 变量$a被赋值为数字1 变量$b被赋值为数字2 变量总数为:2语法分析词YACCYACC(Yet Another Compiler-Compiler) 是 UNIX/Linux 上一个用来生成编译器的编译器(编译器代码生成器). YACC使用BNF范式定义语法能处理上下文无关文法YACC 语法规则YACC 语法包括3部分即定义段、规则段和用户代码段… 定义段 …%%… 规则段 …%%… 用户代码段 …代码词法分析文件: cal.l%{ #include y.tab.h #include math.h %} %% ([0-9]|([0-9]*\.[0-9])([eE][-]?[0-9])?) { yylval.dval atof(yytext); return NUMBER; } [ \t] ; \n | . return yytext[0]; %%语法分析文件: calc.y%{ #include stdio.h #include string.h #include math.h int yylex(void); void yyerror(char *); %} %union { double dval; } %token dval NUMBER %left - %left * / %nonassoc UMINUS %type dval expression %% statement_list: statement \n | statement_list statement \n ; statement: expression { printf( %g\n, $1); } ; expression: expression expression {$$ $1 $3;} | expression - expression { $$ $1 - $3; } | expression * expression { $$ $1 * $3; } | expression / expression { if ($3 0.0) yyerror(divide by zero); else $$ $1 / $3; } | - expression %prec UMINUS { $$ -$2; } | ( expression ) { $$ $2; } | NUMBER { $$ $1; } %% void yyerror(char *str) { fprintf(stderr, error:%s\n, str); } int yywrap() { return 1; } int main() { yyparse(); }从代码中可以看出规则部分使用BNF范式expression 最终是NUMBER以及使用、-、* 、/ 和 ()的组合对加、减、乘、除、括号、负号进行表达statement 是由expression 组合而成的可以输出计算结果statement 是由expression 组合而成的可以输出计算结果statement_list 是statement的组合lex 编译lex cal.l通过这个命令会生成lex.yy.c,里面维护了NUMBER这个Token的有穷自动机使用 YACC对 calc.yyacc -d calc.y会生成y.tab.c、y.tab.h最终执行结果gcc -o calc y.tab.c lex.yy.c ./calc 12 3 36 9Re2C 与 Bison词法分析器 Re2cRe2c 是一个词法编译器可以将符合Re2c规范的生成高效的C/C代码Re2c会将正则表达式生成对应的有穷状态机代码num.l#include stdio.h enum num_t {ERR, DEC}; static num_t lex(const char *YYCURSOR) { const char *YYMARKER; /*!re2c re2c:define:YYCTYPE char; re2c:yyfill:enable 0; end \x00; dec [1-9][0-9]*; * {return ERR;} dec end {return DEC;} */ } int main(int argc, char **argv) { for (int i 1; i argc; i) { switch (lex(argv[i])) { case ERR: printf(error\n); break; case DEC: printf(十进制表示\n); break; } } return 0; }执行以下命令转换成c代码re2c num.l -o num.cnum.c/* Generated by re2c 3.0 on Sun May 26 21:58:19 2024 */ #line 1 num.l #include stdio.h enum num_t {ERR, DEC}; static num_t lex(const char *YYCURSOR) { const char *YYMARKER; #line 11 num.c { char yych; yych *YYCURSOR; switch (yych) { case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: goto yy3; default: goto yy1; } yy1: YYCURSOR; yy2: #line 14 num.l {return ERR;} #line 32 num.c yy3: yych *(YYMARKER YYCURSOR); switch (yych) { case 0x00: goto yy4; case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: goto yy5; default: goto yy2; } yy4: YYCURSOR; #line 15 num.l {return DEC;} #line 53 num.c yy5: yych *YYCURSOR; switch (yych) { case 0x00: goto yy4; case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7: case 8: case 9: goto yy5; default: goto yy6; } yy6: YYCURSOR YYMARKER; goto yy2; } #line 16 num.l } int main(int argc, char **argv) { for (int i 1; i argc; i) { switch (lex(argv[i])) { case ERR: printf(error\n); break; case DEC: printf(十进制表示\n); break; } } return 0; }从上面代码中可以看出这个状态机一共有8种状态分别是开始状态、yy3至yy9状态其中yy3状态是错误输出返回ERRyy5 状态是对应的正则匹配状态返回DECYYCURSOR 是指向输入的指针根据状态的流转指针加1语法编译器Bison对于一条BNF文法规则其左边是一个非终结符(symbol 或者 non-terminal)其右边则定义该非终结符是如何构成的也称为产生式(production)产生式可能包含非终结符也可能包含终结符(terminal)还可能二者都有利用BNF文来分析目标文本比较流行的算法有LL分析(自顶向下的分析,top-down parsing),LR分析(自底向上的分析bottom-up parsing或者叫移进-归约分析, shift-down parsing)其中LR算法有很多不同的变种按照复杂度和能力递增的顺序依次是LR(0)、SLR、SLR、LALR和LR(1)Bison是基于LALR分析法实现的适合上下文无关文法当Bison读入一个终结符TOKEN时会将该终结符及其语意值一起压榨其中这个栈叫做分析器栈(parse stack)把一个TOKEN压入栈叫作移进。举个例子对于计算12 * 3, 假设现已经读入来1 2 * 那么下一个准备读入的是3这个栈当前就有4个元素即1、、2和*当已经移进的后n个终结符和组(grouping)与一个文法规则相匹配时它们会根据该规则结合起来这叫归约(reduction)栈中哪些终结符和组会被单个的组(grouping)替换。同样以1 2 * 3为例最后一个输入的字符为分号表示结束那么按照下面的规则进行归约expression * expression { $$ $1 * $3 }代码bcalc.y 文件%{ #define YYSTYPE double #include math.h #include ctype.h #include stdio.h %} /* 定义部分 */ %token NUM %left - %left * / %left NEG %right ^ /* 语法部分 */ %% input: /* empty string*/ | input line ; line: \n | exp \n {printf(\t%.10g\n, $1);} exp: NUM { $$ $1; } | exp exp { $$ $1 $3; } | exp - exp { $$ $1 $3; } | exp * exp { $$ $1 $3; } | exp / exp { $$ $1 $3; } | - exp %prec NEG { $$ -$2; } | exp ^ exp { $$ pow($1, $3); } | ( exp ) { $$ $2; } ; /* 代码部分 */ %% yylen() { int c; /* 跳过空格 */ while ((c getchar()) || c \t) ; if (c . || isdigit(c)) { ungetc(c, stdin); scanf(%lf, yylval); return NUM; } if (c EOF) return 0; return c; } yyerror (char *s) /* 错误是被 yyparse 调用 */ { printf(%s\n, s); } main() { yyparse(); }通过Bison 对 bcalc.y进行编译bison -d bcalc.y执行下面的命令可以生成对应的可以执行文件gcc -o bcalc bcalc.tab.c bcalc.tab.h -lm参考资料手把手教程-lex与yacc/flex与bison入门一使用windows环境

相关新闻

Win11Debloat终极指南:一键清理让你的Windows 11性能飙升51%

Win11Debloat终极指南:一键清理让你的Windows 11性能飙升51%

Win11Debloat终极指南:一键清理让你的Windows 11性能飙升51% 【免费下载链接】Win11Debloat A simple, lightweight PowerShell script that allows you to remove pre-installed apps, disable telemetry, as well as perform various other changes to declutter …

2026/7/31 18:07:36阅读更多 →
打破前端动效开发黑盒:基于Web组态引擎的虚拟变量与动画免代码绑定机制

打破前端动效开发黑盒:基于Web组态引擎的虚拟变量与动画免代码绑定机制

工业可视化大屏的核心灵魂在于“动”:管道中流淌的液体、旋转的风机叶片、越限报警的闪烁信号,这些动态效果让深色科技主题的工业数据焕发出生机。但在传统的 Web 前端开发中,实现这些工业级动效往往伴随着复杂的 JavaScript 逻辑判断和渲染性…

2026/7/31 18:05:36阅读更多 →
如何使用PolyPartition进行高效多边形三角化?3种算法对比与实战

如何使用PolyPartition进行高效多边形三角化?3种算法对比与实战

如何使用PolyPartition进行高效多边形三角化?3种算法对比与实战 【免费下载链接】polypartition Tiny Polygon Partitioning and Triangulation Library 项目地址: https://gitcode.com/gh_mirrors/po/polypartition PolyPartition是一款轻量级的多边形分割与…

2026/7/31 18:05:36阅读更多 →
磁悬浮鼓风机配啥变频器?四方电气 DX500 表示:这活儿我熟

磁悬浮鼓风机配啥变频器?四方电气 DX500 表示:这活儿我熟

直接说结论:给磁悬浮鼓风机挑变频器,四方电气 DX500 属于那种 “上手就知道可靠” 的选手,不是花哨的,但相对是干活儿很稳的那一档。 一、先唠唠:鼓风机这玩意儿为啥这么费电? 各位厂长、工程师朋友们&…

2026/7/31 19:26:18阅读更多 →
碧蓝幻想Relink数据分析工具:GBFR-Logs完整实用指南

碧蓝幻想Relink数据分析工具:GBFR-Logs完整实用指南

碧蓝幻想Relink数据分析工具:GBFR-Logs完整实用指南 【免费下载链接】gbfr-logs GBFR Logs lets you track damage statistics with a nice overlay DPS meter for Granblue Fantasy: Relink. 项目地址: https://gitcode.com/gh_mirrors/gb/gbfr-logs 想要在…

2026/7/31 19:26:18阅读更多 →
扣子错误处理节点最佳实践白皮书(仅限首批内测团队获取的12条黄金规则)

扣子错误处理节点最佳实践白皮书(仅限首批内测团队获取的12条黄金规则)

更多请点击: https://codechina.net 第一章:扣子错误处理节点的核心价值与定位 扣子(Coze)平台中的错误处理节点并非简单的异常兜底机制,而是工作流健壮性与用户体验一致性的关键设计锚点。它将原本分散在各节点内部的…

2026/7/31 19:26:18阅读更多 →
七月深夜代码终章:玄学不是逃避,是保持探索的好奇心

七月深夜代码终章:玄学不是逃避,是保持探索的好奇心

七月深夜代码终章:玄学不是逃避,是保持探索的好奇心 一、个性化深度引言 凌晨一点,GPU的风扇声是房间里唯一的背景音。屏幕上第七次修改的训练配置仍然没有带来提升。这种情况下,很容易产生一种冲动——用玄学解释一切&#xff…

2026/7/31 19:26:18阅读更多 →
七月 AI 工程实践终章:技术不重要,解决问题才重要

七月 AI 工程实践终章:技术不重要,解决问题才重要

七月 AI 工程实践终章:技术不重要,解决问题才重要 一、个性化深度引言 七月接到一个需求:用户希望在智能客服系统中增加"问题预判"功能——在用户开口之前,根据其历史行为预测可能遇到的问题并主动提供解决方案。 第…

2026/7/31 19:26:18阅读更多 →
告别设计焦虑!Guizang Social Card Skill:零基础制作杂志级社交媒体封面图的终极指南

告别设计焦虑!Guizang Social Card Skill:零基础制作杂志级社交媒体封面图的终极指南

告别设计焦虑!Guizang Social Card Skill:零基础制作杂志级社交媒体封面图的终极指南 【免费下载链接】guizang-social-card-skill 🪧 Claude Code / Codex skill — generate Xiaohongshu carousels & WeChat 21:91:1 cover pairs. Edit…

2026/7/31 19:24:17阅读更多 →
覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

覆盖国产 + 海外 + 开源模型,OpenClaw 2.7.9 Windows/Mac 双端部署详解

🔹 工具基础介绍 OpenClaw 是开源生态中一款实用性较强的本地智能工具,凭借本地离线运行、可视化图形操作和任务自动化三大核心特性,赢得了众多用户的青睐。与普通在线对话AI工具不同,它属于能够直接操控本机软硬件的智能数字员工…

2026/7/30 15:03:16阅读更多 →
伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

伺服阀焊完微漏毁整机?精密激光焊接三关锁住高压

所谓液压伺服阀体的精密激光焊接,是用激光束对阀座壳体(通常为不锈钢或铝合金)进行密封焊接,使阀体在21-35MPa的高压液压油或压缩气体中长期运行而不发生介质泄漏。液压伺服阀是高端液压系统的"大脑"。从航空航天飞行控…

2026/7/31 17:41:43阅读更多 →
D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南

D2DX:三步实现《暗黑破坏神2》高清宽屏体验的终极指南 【免费下载链接】d2dx D2DX is a complete solution to make Diablo II run well on modern PCs, with high fps and better resolutions. 项目地址: https://gitcode.com/gh_mirrors/d2/d2dx 你是否还在…

2026/7/30 15:13:02阅读更多 →
物理复制比逻辑复制好在哪?数据库复制原理详解

物理复制比逻辑复制好在哪?数据库复制原理详解

数据库复制是把主库数据同步到备库的机制,分为逻辑复制和物理复制两种。逻辑复制传输的是 SQL 语句或行变更事件,物理复制传输的是存储引擎底层的物理日志。阿里云 PolarDB(云原生数据库)采用物理复制,在同步延迟、数据…

2026/7/31 0:00:40阅读更多 →
BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南

BilibiliDown:3分钟学会B站视频下载的终极指南 【免费下载链接】BilibiliDown (GUI-多平台支持) B站 哔哩哔哩 视频下载器。支持稍后再看、收藏夹、UP主视频批量下载|Bilibili Video Downloader 😳 项目地址: https://gitcode.com/gh_mirrors/bi/Bilib…

2026/7/31 0:00:41阅读更多 →
有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

有哪些游戏数据AI平台?游戏行业Data+AI融合方案盘点

当前,游戏行业的“DataAI融合”已从概念验证进入价值落地阶段。根据IDC 2025年数据,中国AI游戏云市场规模已达18.6亿元;同时,游戏研发环节AI渗透率高达86%,生成式AI内容普及率超过50%。面对庞大的市场,游戏…

2026/7/31 0:00:41阅读更多 →
YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

YOLOv8推理性能优化:从1.2FPS到35FPS的全链路加速实践

如果你在部署 YOLOv8 时,发现推理速度只有可怜的 1-2 FPS,而别人的演示视频却能跑到 30 FPS 以上,那么问题很可能不在模型本身,而在于你的整个处理链路。很多开发者拿到一个训练好的 YOLOv8 模型后,会直接使用官方示例…

2026/7/31 0:49:33阅读更多 →
Coze与Dify对比指南:低代码AI应用开发从入门到实战

Coze与Dify对比指南:低代码AI应用开发从入门到实战

1. 从零到一:为什么你需要了解 Coze 和 Dify?如果你对 AI 应用开发感兴趣,但一看到“大模型”、“智能体”、“工作流”这些词就头疼,觉得门槛太高,那这篇文章就是为你准备的。很多开发者,包括我自己&#…

2026/7/31 5:08:18阅读更多 →
AI生图工具怎么选?2026年6月版实测对比

AI生图工具怎么选?2026年6月版实测对比

做自媒体的朋友应该都有体会:配图一直是个让人头疼的问题。2026年,AI生图工具已经非常成熟了,但工具太多反而不知道怎么选。以下是截至2026年6月我对主流AI生图工具的实测对比。Midjourney V8.1:速度之王2026年6月11日&#xff0c…

2026/7/31 16:02:17阅读更多 →