You need to enable JavaScript to run this app. 如何用Yacc编写最基础的解析器生成器?附Lex/Yacc示例与编译问题排查
优惠活动
大模型
产品
解决方案
定价
更多

如何用Yacc编写最基础的解析器生成器?附Lex/Yacc示例与编译问题排查

极简Lex+Yacc联动程序问题说明
  • 学习Lex/Flex的过程相对轻松,但入门Yacc/Bison时因为缺少足够轻量化的示例,整体理解门槛很高。目前公开的入门级Yacc示例大多为计算器类程序,对新手不够友好,单靠读复杂源码很难理解Yacc的核心工作逻辑,因此动手编写了一个最小化的Lex+Yacc联动程序。

程序核心逻辑非常简单:词法分析器匹配到固定字符串后向Yacc解析器返回对应标记,由Yacc侧的语法规则捕获标记后,打印对应的Caught PRINT或Caught EXIT提示。

项目源文件

test.l(词法规则文件)

%{
#include "y.tab.h"
%}

%%
"PRINT"     { printf("Returning PRINT\n"); return PRINT; }
"EXIT"      { printf("Returning EXIT\n");  return EXIT; }
.       ;
[ \t\n] ;
%%

int yywrap(void) { return 1; }

test.y(语法规则文件)

%{
int yylex();
#include <stdio.h> 
#include <stdlib.h>
//#include "y.tab.h"
%}

%start line
%token PRINT
%token EXIT

%%
line: PRINT {printf("Caught PRINT\n");}
    | EXIT  {printf("Caught EXIT\n");}
    | ;

%%
int main() { yyparse(); }

最初的编译尝试

自行摸索搭建了基础逻辑后,程序始终无法正常运行,最初采用的编译流程为:

  • 执行yacc -d test.y生成语法分析相关文件
  • 执行lex test.l生成词法分析相关文件
  • 执行gcc lex.yy.c y.tab.h -ll尝试生成可执行文件

问题排查与修复

经实际排查,编译流程的错误是程序无法正常运行的核心原因,排查过程中也参考了其他开发者的思路梳理,具体问题和修复方案如下:

  • 原编译命令错误将头文件y.tab.h作为编译输入,完全遗漏了Yacc生成的核心语法实现源码y.tab.c,导致编译链路缺失核心逻辑,程序无法正常运行
  • 正确的编译步骤为:
    1. 运行yacc -d test.y,生成包含语法分析核心逻辑的y.tab.c,以及包含标记常量定义的头文件y.tab.h
    2. 运行lex test.l,生成包含词法分析核心逻辑的lex.yy.c
    3. 运行gcc lex.yy.c y.tab.c -ll,将两个核心源码文件共同编译,链接Lex运行时库-ll,即可生成可正常运行的程序
  • 补充说明:y.tab.h是供源码引用的头文件,不需要直接作为编译单元传给gcc,它的作用是在词法分析器编译时引入Yacc定义的标记值,保证词法侧返回的标记和语法侧的规则定义完全匹配。

内容的提问来源于stack exchange,提问作者HamzaKerem

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.11.04 21:15:03