【编译原理】Lex词法分析器

一、实验目的

设计并实现一个词法分析器,深刻理解编译原理中词法分析器的原理。

 

二、实验内容

通过使用自己熟悉的语言设计并实现一个词法分析器,是此法分析器按要求的格式输出经过分析的程序段。

要求分析一下程序片段:

[delphi]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. const a=10;  
  2. var b,c;  
  3. procedure p;  
  4.   begin  
  5.     c:=b+a;  
  6.   end;  
  7.   
  8. begin  
  9.  read(b);  
  10.  while b#0 do  
  11.   begin  
  12.    call p;writeln(2*c);read(b);  
  13.   end  
  14. end.  

该程序片段存放在 example.txt 中。


三、实验步骤

 1、对PL\0文法中各类单词分类:

  (1)保留字:const、var、procedure、begin、end、if、then、while、do、read、call、write、writeln

  (2)常数:由0-----9这几个数字组成

  (3)标识符:由字母打头的字母和数字的字符串

  (4)运算符:+,-,*,/,:=,>=,<=,#

  (5)分界符:,、.、(、)、;

  2、将各类单词对应到lex中:

  (1)保留字:

reservedWord [const|var|procedure|begin|end|if|then|while|do|read|call|write|writeln],由于在lex中不区分大小写,所以将保留字写成:

reservedWord [cC][oO][nN][sS][tT]|[vV][aA][rR]|[pP][rR][oO][cC][eE][dD][uU][rR][eE]|

[bB][eE][gG][iI][nN]|[eE][nN][dD]|[iI][fF]|[tT][hH][eE][nN]|[wW][hH][iI]

[lL][eE]|[dD][oO]|[rR][eE][aA][dD]|[cC][aA][lL][lL]|[wW][rR][iI][tT][eE]

[wW][rR][iI][tT][eE][lL][nN]

  (2)常数:

constant ([0-9])+  /*0---9这几个数字可以重复*/

  (3)标识符:

      identfier [A-Za-z]([A-Za-z][0-9])*

  (4)运算符:

      operator \+|-|\*|\/|:=|>=|<=|#|=  /*在lex中,有特殊意义的运算符要加转义字符\,如+、*及*、/

  (5)分界符:

      delimiter [,\.;\(\)]

  3、PL/0的语言的词法分析器要求跳过分隔符(如空格,回车,制表符),对应的lex定义为:

     delim [""\n\t]

whitespace{delim}+

  4、为lex制定一些规则:

     {reservedWord}{count++;printf("\t%d\t(1,‘%s’)\n",count,yytext);}   /*对保留字定规则,输出设置*/

     {operator} {count++;printf("\t%d\t(2,‘%s’)\n",count,yytext); }

     {delimiter}{count++;printf("\t%d\t(3,‘%s’)\n",count,yytext);}

{constant}{count++;printf("\t%d\t(4,‘%s’)\n",count,yytext);}

{identfier}{count++;printf("\t%d\t(5,‘%s’)\n",count,yytext);}

{whitespace} {/* do    nothing*/ }         /*遇到空格,什么都不做*/

  5、写子程序:

   voidmain()

{

   printf("词法分析器输出类型说明:\n");

         printf("1:保留字\n");

         printf("2:运算符\n");

         printf("3:分界符\n");

         printf("4:常  数\n");

         printf("5:标识符\n");

         printf("\n");

         yyin=fopen("example.txt","r");

             yylex(); /* start the analysis*/

         fclose(yyin);

         system("PAUSE");/*暂停*/

}

 intyywrap()

 {

        return 1;

}

当lex 读完输入文件之后就会调用函数 yywrap 。如果返回1 表示程序的工作已经完成了,否则,返回 0。


四、实现的源代码

[cpp]  view plain copy 在CODE上查看代码片 派生到我的代码片
  1. %{  
  2.     #include <stdio.h>  
  3.     #include <stdlib.h>   
  4.     int count = 0;  
  5. %}   
  6.   
  7. delim [" "\n\t]   
  8. whitespace {delim}+   
  9. operator \+|-|\*|\/|:=|>=|<=|#|=  
  10. reservedWord [cC][oO][nN][sS][tT]|[vV][aA][rR]|[pP][rR][oO][cC][eE][dD][uU][rR][eE]|[bB][eE][gG][iI][nN]|[eE][nN][dD]|[iI][fF]|[tT][hH][eE][nN]|[wW][hH][iI][lL][eE]|[dD][oO]|[rR][eE][aA][dD]|[cC][aA][lL][lL]|[wW][rR][iI][tT][eE]|[wW][rR][iI][tT][eE][lL][nN]  
  11. delimiter [,\.;\(\)]  
  12. constant ([0-9])+  
  13. identfier [A-Za-z]([A-Za-z][0-9])*  
  14. %%   
  15. {reservedWord} {count++;printf("%d\t(1,‘%s’)\n",count,yytext);}  
  16. {operator} { count++;printf("%d\t(2,‘%s’)\n",count,yytext); }  
  17. {delimiter} {count++;printf("%d\t(3,‘%s’)\n",count,yytext);}  
  18. {constant} {count++;printf("%d\t(4,‘%s’)\n",count,yytext);}  
  19. {identfier} {count++;printf("%d\t(5,‘%s’)\n",count,yytext);}   
  20. {whitespace} { /* do    nothing*/ }   
  21.   
  22. %%   
  23. void main()   
  24. {  
  25.     printf("词法分析器输出类型说明:\n");  
  26.     printf("1:保留字\n");  
  27.     printf("2:运算符\n");  
  28.     printf("3:分界符\n");  
  29.     printf("4:常  数\n");  
  30.     printf("5:标识符\n");  
  31.     printf("\n");  
  32.     yyin=fopen("example.txt","r");   
  33.         yylex(); /* start the analysis*/   
  34.     fclose(yyin);  
  35.     system("PAUSE");/*暂停停,  使DOS窗口停住*/  
  36. }   
  37.  int yywrap()   
  38.  {   
  39.     return 1;   
  40.  }   

五、实操作

将源代码存储为a.l,然后用flex(Lex)进行编译,输入flex a.l,编译后生成lex.yy.c文件,用c编译器打开(确保example.txt存储在相同目录下),编译运行即可!


六、运行结果


Lex与yacc确实是很不错的工具!如果单用编程语言,如C,C++,Java写的话,代码就多了不少。


  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
编译原理词法分析器一个重要的组成部分,其作用是将源代码转化为一系列的词法单元(tokens)。其,词法单元是指编程语言的最小的、有意义的、不可再分的单词,如关键字、标识符、运算符、常量等。 lex是一种常用的词法分析器生成器,它的工作原理是基于正则表达式匹配规则。使用lex的时候,我们需要使用一种被称为lex源文件的文件,其包含词法规则描述和对应的动作。 在编写lex源文件时,我们需要定义一系列的正则表达式规则,用于匹配不同类型的词法单元。每个规则通常由两部分组成:模式(pattern)和动作(action)。模式用于描述词法单元的形式,而动作则指定了在匹配到该模式时的处理方式。 lex根据这些规则生成一个有限状态自动机,并用于从输入的源代码识别和提取出对应的词法单元。生成的词法分析器可以作为编译过程的第一步,将源代码分解为一系列的词法单元,供后续的语法分析器使用。 使用lex可以极大地简化词法分析器的编写工作,同时提高了分析效率。通过定义灵活的正则表达式规则,我们可以轻松地适应不同编程语言的需求。 总结起来,词法分析器编译原理起着至关重要的作用。lex作为一种词法分析器生成器,可以帮助我们快速构建词法分析器,从源代码提取出有意义的词法单元,为后续的编译过程打下基础。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值