词法语法分析器
https://blog.csdn.net/weixin_44007632/article/details/108666375
介绍
词法:lex flex
语法:Yacc Bison
lex 是本身有一个 flex.exe,你写。l 文件,这个 flex.exe,给你转为一个。c 文件,这个。c 你自己编译为 exe2,由这个 exe2 来做词法分析
Bison 一般配合 flex 使用,类似于上面,Bison 要求你写一个。y 文件,给你转化为。c 文件,这个。c 结合上面的。c,一起编译(自己用 gcc 编),能够形成一个 exe3,做语法+词法
Lex 新手框架
定义+规则+代码
%{
/*定义*/
%}
/*这里可以定义一些“变量”,变量使用时要拿{}包裹*/
%%
%%
/*上面%%中间是规则,但是 lex 的规则是没有注释的,所有注释本质都是写到 C 语言里的注释*/
/*代码*/
int main(int argc, char **argv)
{
yylex();
yywrap();
return 0;
}
int yywrap()
{
return 1;
}规则
flex 对任何没有匹配到的字符,会自动做原样输出操作。因此,对于那些不需要将其输出,而是需要将其忽略的 pattern,应该进行匹配并做无操作处理。
规则 = 正则表达式 + 空格 + 动作
动作:C 代码、宏(自定义 or 预设)、函数(本质还是 C 代码,不过是调用定义部分定义的函数)
C 代码,一般用{ }包裹住
[a-zA-Z]+ {ECHO;}
"-" {return T_MINUS;}ECHO 是 Flex 自定义的一个宏,等于、#define ECHO fprintf(yyout, "%s", yytext)
return T_MINUS ,这个本质是一个 C 代码作为动作,因为是 return XXX
T_MINUS 是一个 token,这时 flex 必须配合 bison 使用,bison 中定义的 token,能够在
正则表达式这里,使用 "" 来表示精确匹配
即
int {return INT}
"int" {return INT}
应该是一样的,不过建议是下面的
Bison 框架
在与 flex 一起使用时,L 文件的第三部分直接不写
Flex 的第一部分
%{
#include <stdio.h>
#include "y.tab.h"
void yyerror(char *);
%}
NUM [1-9]+[0-9]*|0#include "y.tab.h"
要先编译 Y 文件,而编译 Y 文件后,y.tab.h 自动生成
Flex 的第二部分要变成
{NUM} return NUM;
"+" return ADD;
"-" return SUB;
"*" return MUL;
"/" return DIV;
[a-zA-Z_$]+[a-zA-Z_$0-9]* return VAR;
\n return CR;
[ \t]+ /* ignore whitespace */;右侧 return 的 Token,实际上就在 y.tab.h
Bison 的第一部分
%{
#include <stdio.h>
#include <string.h>
int yylex(void);
void yyerror(char *);
%}
%token NUM ADD SUB MUL DIV VAR CR
%%定义部分
通过%token 定义 token,token 会被翻译到 y.tab.h 中
Bison 的第二部分
expression: expression '+' expression {/*C 代码*/}
| expression '-' expression
| NUM
;通过 BNF 来表示产生式
其中的 : 相当于 产生式里的 →
即格式为
rule -> BNF action
Bison 的第三部分
void yyerror(char *str){
fprintf(stderr,"error:%s\n",str);
}
int yywrap(){
return 1;
}
int main()
{
yyparse();
}新手框架
%{
#include "y.tab.h"
/*有时候不叫 y.tab*/
void yyerror(char *);
%}
%%
%%%{
int yylex(void);
void yyerror(char *);
%}
%token
%%
%%
void yyerror(char *str){
fprintf(stderr,"error:%s\n",str);
}
int yywrap(){
return 1;
}
int main()
{
yyparse();
}计算器
Flex 返回的 token 本质是一个宏定义出的整数
这导致 Flex 无法直接给 Bison 返回一个整数
因此要使用 Bison 的全局变量 yylval
总之,你只要在 Flex 里,每次分析数值时,写入
sscanf(yytext,"%d",&yylval);
把 yylval 改写即可
而值有时是整数有时是小数,因此要在 Bison 定义处把 yylval 定义为 union
%union{
int inum;
double fnum;
char c;
char * string;
//其余类型随意加
}定义和规则补充
之前 Bison 的规则是
%token ADD
但是只能表示终结符
%token <inum> NUM
%type <inum> expression
这种结构表示,后面的符号的值,使用的是这个变量的值
type 提示一个非终结符
father-expression : expression SUB term {$$=$1-$3;}