C/Lex/Yacc - 如何使用 Yacc 编写最基本的解析器生成器

C/Lex/Yacc - How To Write The Most Basic Parser Generator Using Yacc

我发现学习 Lex/Flex 很容易,但是由于缺乏简单的示例程序,学习 Yacc/Bison 似乎更加混乱。根据我的观察,第一个介绍给学生的示例解析器往往是一个计算器,这对初学者来说不太友好。我很难通过查看复杂的源代码来理解 Yacc 的工作原理,因此我决定编写自己的非常简单的程序,其中包含 Lex 和 Yacc。

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

我知道这个程序非常简单,而且 Yacc 有很多例子,我想真诚地向你保证,在寻求帮助之前我试了几个小时。

虽然我认为我已经完成了基础工作,但我无法弄清楚为什么它不起作用,请告诉我如何解决它。我怀疑我可能编译不正确。如有必要,我还可以显示 y.tab.h。谢谢你的时间。

编辑:目标只是让词法分析器 return 将适当的 return 值传递给 yacc 解析器,并让 yacc 解析器“捕获”它并打印“Caught PRINT”或“抓到出口”。

编辑2:我的编译过程确实不正确。我要感谢帮助我了解如何解决问题的人。

你不应该编译 *.h 个文件。 使用 gcc y.tab.c lex.yy.ctest.y 中提供的 yyerror 定义(bison 手册推荐 void yyerror (char const *s) { fprintf (stderr, "%s\n", s); }),它应该构建。