我是靠谱客的博主 平常服饰,这篇文章主要介绍词法分析器的生成器——lex/flex1.词法分析器和语法分析器2.flex,现在分享给大家,希望可以做个参考。

文章目录

  • 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_DECL
  • yywrap():词法分析器遇到文件结尾时会调用yywrap()来决定下一步怎么做:这是一个约束函数。若yywrap()返回0,则继续扫描; 当它返回1时,代表扫描结束,此时结束程序;

以下部分作为了解:

  • yyless(int n):用来送回除了前n个字符外的所有读出标记
  • yymore():告诉lexer将下一个标记符加到当前标记后
  • yymore():将当前识别的词形保留在yytext中,分析器下次扫描时的词形将加追加在yytext中。例模式定义如下
复制代码
1
2
3
4
5
hello {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的全部内容,更多相关词法分析器内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(76)

评论列表共有 0 条评论

立即
投稿
返回
顶部