文章目录
- 1.词法分析器和语法分析器
- 2.flex
- 1.使用
- 2.文件格式
- 3.条件模式(了解)
1.词法分析器和语法分析器
词法分析器:将文本分解成token
语法分析器:判断token是否符合规定的语法规则
- 可以自己实现词法/语法分析器,分离文本,编写语法规则。但是为了方便和规范的词法语法分析,我们使用flex和bison;
- flex是词法分析器的生成工具,bison是语法分析器的生成工具;
- 使用此工具就让我们脱离了繁琐的代码编写上,只需要关注我们需要什么符号,使用什么规则。
2.flex
1.使用
1.编写好词法规则文件,一般以.l为文件格式(flex对文件格式没要求,不是.l也没关系)
2.flex xxx.l 生成lex.yy.c
3.gcc lex.yy.c -lfl (-lfl带不带都没关系) 可以修改lex.yy.c名字
例子:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24/*flex-wc.l*/ %option noyywrap //option、noyywrap是flex的关键字,语法部分介绍 %{ int chars = 0; //声明 int words = 0; int lines = 0; %} %% [a-zA-z]+ { words++; chars += strlen(yytext); } //规则 n { lines++; chars++; } . { chars++; } %% //以下部分会在lex.yy.c上原地展开 int main() { yylex(); //根据以上规则生成的词法分析函数 printf("%8d %8d %8dn", lines, words, chars); return 0; }
2.文件格式
1
2
3
4
5
6
7
8
9%{ C语言声明,一般声明全局变量和函数,会复制进lex.yy.c中 %} 定义正则表达式的名字,可以在规则段中使用 %% 规则段,每一行都是一条规则,每一条规则由匹配模式和事件组成。每当一个模式被匹配到,后面的事件被执行! %% 用户自定义过程,直接复制到lex.yy.c末尾
flex提供的全局变量:
yytext
:刚刚匹配到的字符串yyleng
:刚刚匹配到的字符串的长度yyin
:FILE*类型yyout
:指向输出的文件,缺省情况下指向标准输入输出yylineno
:当前行数信息yylval
:可由yytext取出数字atoi(yytext)
flex提供的函数:
yylex()
:词法分析器驱动程序,用Lex翻译器生成的lex.yy.c内必然含有这个函数;YY_DECLyywrap()
:词法分析器遇到文件结尾时会调用yywrap()来决定下一步怎么做:这是一个约束函数。若yywrap()返回0,则继续扫描; 当它返回1时,代表扫描结束,此时结束程序;
以下部分作为了解:
yyless(int n)
:用来送回除了前n个字符外的所有读出标记yymore()
:告诉lexer将下一个标记符加到当前标记后yymore()
:将当前识别的词形保留在yytext中,分析器下次扫描时的词形将加追加在yytext中。例模式定义如下
1
2
3
4
5hello {printf(“%s!”,yytext);yymore();} world {printf(“%s!”,yytext);} 12
当输入串为”helloworld”时,将输出”hello!helloworld!”
- REJECT:放弃当前匹配的字符串和当前的模式,让分析器重新扫描当前的字符串,并选择另一个最佳的模式再次进行匹配。
yyless(int n)
:回退当前识别的词形中n个字符到输入中unput(char c)
:回退字符c到输入,它将作为下一次扫描的开始字符input()
:让分析器从输入缓冲区中读取当前字符,并将yyin指向下一字符yyterminate()
:中断对当前文件的分析,将yyin指向EOF。yyrestart(FILE * file)
:重新设置分析器的扫描文件为file- ECHO:
#define ECHO fwrite(yytext, yyleng, 1, yyout)
将当前识别的字符串拷贝到yyout - BEGIN:激活开始条件对应的模式
规则部分的语法:
遵循正则表达式,如一些比较有用的规则:
1
2
3
4
5
6
7[ t] { /*ignore white space*/ } //{}中什么都不做,就是将空格删除 . { printf("unexpected token: (%s)n", yytext); return -1; } //其他情况,一般放在最后,表示意外情况,返回错误
3.条件模式(了解)
LEX提供控制模式在一定状态下使用的功能,称为条件模式。LEX首先在定义部份通过%start来定义条件句。在规则部份可通过宏
BEGIN 条件名 来激活条件。BEGIN INITIAL或BEGIN 0将休眠所有的条件模式,使分析器回到开始状态。
例:将输入文件中的单词”magic” 作如下处理:识别”magic”时,如”magic”所在行行首为字符’a’,则输出”first”;若为’b’,则输出”second”;否则,输出”magic”。如不用条件模式,LEX源文件可这样写:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15%{int flag;}% %% ^a {flag=’a’;ECHO;} ^b {flag=’b’;ECHO;} /n {flag=0;ECHO;} magic { switch(flag) { case ‘a’:printf(“first”);break; case ‘b’:printf(“second”);break; default :ECHO;break; } } %%
如使用条件模式,则上述源文件可简化为
1
2
3
4
5
6
7
8
9
10%start AA BB CC %% ^a {ECHO;BEGIN AA;} ^b {ECHO;BEGIN BB;} /n {ECHO;BEGIN 0;} <AA>magic {printf(“first”);} <BB>magic {printf(“second”);} %% ##
参考文章:
https://blog.csdn.net/damontive/article/details/115289890
https://www.cnblogs.com/wanghetao/archive/2011/11/07/2240193.html
https://blog.csdn.net/liwei_cmg/article/details/1530492
最后
以上就是平常服饰最近收集整理的关于词法分析器的生成器——lex/flex1.词法分析器和语法分析器2.flex的全部内容,更多相关词法分析器内容请搜索靠谱客的其他文章。
发表评论 取消回复