lex词法分析过程 编译原理 词法分析

生成*.yy.c

在学习到编译原理的词法分析器阶段,为了学习使用lex做分析,在网上找了一些资料学习。
lex代码来源:https://blog.csdn.net/wang_yr/article/details/106004464,

 AUXILIARY DEFINITION
 letter->A|B||Z
 digit->0|1||9
 RECOGNITION RULES
 1    DIM                     {RETURN(1,-)}
 2    IF                      {RETURN(2,-)}
 3    DO                      {RETURN(3,-)}
 4    STOP                    {RETURN(4,-)}
 5    END                     {RETURN(5,-)}
 6    letter(letter|digit)*   {RETURN(6,TOKEN)}
 7    digit(digit)*           {RETURN(7,DTB)}
 8    =                       {RETURN(8,-)}
 9    +                       {RETURN(9,-)}
 10   *                       {RETURN(10,-)}
 11   **                      {RETURN(11,-)}
 12   ,                       {RETURN(12,-)}
 13   (                       {RETURN(13,-)}
 14   )                       {RETURN(14,-)}

使用win_flex.exe编译,win_flex.exe --wincompat --outfile=yy.c输出位置 .l文件位置,如下

win_flex.exe --wincompat --outfile=D:\lxc\nbu\software\win_flex_bison-latest\my_code_test/a.yy.c D:\lxc\nbu\software\win_flex_bison-latest\my_code_test\a.l

在这里插入图片描述
在这里插入图片描述
但是在使用lex编译时出现了下面的的一些错误:如bad character和error processing section 1、aa.l:19: premature EOF等等。
经过一顿百度之后,在百度词条里面看到了下面这么一段,所以我在想是不是把AUXILIARY DEFINITION、RECOGNITION RULES换成双百分号%%就好了呢,

在这里插入图片描述
新代码如下

 %%
 letter->A|B|...|Z
 digit ->0|1|...|9
 %%
 1 	DIM                     { RETURN (1,-) }
 2 	IF                      { RETURN (2,-) }
 3 	DO                      { RETURN (3,-) }
 4 	STOP                    { RETURN (4,-) }
 5   END                     { RETURN (5,-) }
 6   letter(letter|digit)*   { RETURN (6,TOKEN) }
 7   digit(digit)*           { RETURN (7,DTB) }
 8   =                       { RETURN (8,-) }
 9   +                       { RETURN (9,-) }
 10  *                       { RETURN (10,-) }
 11  **                      { RETURN (11,-) }
 12  ,                       { RETURN (12,-) }
 13  (                       { RETURN (13,-) }
 14  )                       { RETURN (14,-) }

再次编译:D:\lxc\nbu\software\win_flex_bison-latest>win_flex.exe --wincompat --outfile=D:\lxc\nbu\software\win_flex_bison-latest\my_code_test/a.yy.c D:\lxc\nbu\software\win_flex_bison-latest\my_code_test\a.l
在这里插入图片描述

在这里插入图片描述
*.yy.c文件生成之后就是使用MinGW编译c文件成exe了。安装MinGW:https://blog.csdn.net/jiqiren_dasheng/article/details/103775488。

用*.yy.c编译成*.exe

注意,下面的pl.l文件内容和上面的不一样了,
下面来测试使用lex生成PL语言的词法分析器,aa.l文件代码来源:https://blog.csdn.net/JYLCG/article/details/106126107,

/* PL词法分析器 */
/* 功能:能够识别出PL支持的所有单词符号并给出种别值 */
/* 说明:在下面的begin和end之间添加代码,已经实现了标识符和整常量的识别,你需要完成剩下的部分,加油吧! */
/* 提示:因为是顺序匹配,即从上至下依次匹配规则,所以需要合理安排顺序~ */
%{
#include <stdio.h>
%}
/* begin */
OFSYM            of
ARRAYSYM         array
PROGRAMSYM       program
MODSYM           mod
ANDSYM           and
NOTSYM           not
ORSYM            or
BEGINSYM         begin
ENDSYM           end
IFSYM            if
THENSYM          then
ELSESYM          else
WHILESYM         while
DOSYM            do
CALLSYM          call
CONSTSYM         const
VARSYM           var
TYPESYM          type
PROCSYM          procedure
CHARCON			\'[^\']*\'
INTCON			[\-]?[1-9][0-9]*|0
IDENT			[A-Za-z][A-Za-z0-9]*
PLUS			\+
MINUS			\-
TIMES			\*
DIVSYM             \/
EQL              =
NEQ              <>
LSS              <
LEQ              <=
GTR              >
GEQ              >=
LBRACK           \[
RBRACK           \]
LPAREN           \(
RPAREN           \)
COMMA            ,
SEMICOLON       ;
COLON           :
PERIOD          \.
BECOME         :=
ERROR       [^ \t\n]
/* end */

%%


{CHARCON}		{printf("%s: CHARCON\n", yytext);}
{PLUS}			{printf("%s: PLUS\n", yytext);}
{MINUS}			{printf("%s: MINUS\n", yytext);}
{TIMES}			{printf("%s: TIMES\n", yytext);}
{DIVSYM}		{printf("%s: DIVSYM\n", yytext);}
{EQL}			{printf("%s: EQL\n", yytext);}
{NEQ}			{printf("%s: NEQ\n", yytext);}
{LSS}			{printf("%s: LSS\n", yytext);}
{LEQ}			{printf("%s: LEQ\n", yytext);}
{GTR}			{printf("%s: GTR\n", yytext);}
{GEQ}			{printf("%s: GEQ\n", yytext);}
{LBRACK}		{printf("%s: LBRACK\n", yytext);}
{RBRACK}		{printf("%s: RBRACK\n", yytext);}
{LPAREN}		{printf("%s: LPAREN\n", yytext);}
{RPAREN}		{printf("%s: RPAREN\n", yytext);}
{COMMA}			{printf("%s: COMMA\n", yytext);}
{SEMICOLON}		{printf("%s: SEMICOLON\n", yytext);}
{COLON}			{printf("%s: COLON\n", yytext);}
{PERIOD}		{printf("%s: PERIOD\n", yytext);}
{BECOME}		{printf("%s: BECOME\n", yytext);}
{OFSYM}			{printf("%s: OFSYM\n", yytext);}
{ARRAYSYM}		{printf("%s: ARRAYSYM\n", yytext);}
{PROGRAMSYM}	{printf("%s: PROGRAMSYM\n", yytext);}
{MODSYM}		{printf("%s: MODSYM\n", yytext);}
{ANDSYM}		{printf("%s: ANDSYM\n", yytext);}
{NOTSYM}		{printf("%s: NOTSYM\n", yytext);}
{ORSYM}			{printf("%s: ORSYM\n", yytext);}
{BEGINSYM}		{printf("%s: BEGINSYM\n", yytext);}
{ENDSYM}		{printf("%s: ENDSYM\n", yytext);}
{IFSYM}			{printf("%s: IFSYM\n", yytext);}
{THENSYM}		{printf("%s: THENSYM\n", yytext);}
{ELSESYM}		{printf("%s: ELSESYM\n", yytext);}
{WHILESYM}		{printf("%s: WHILESYM\n", yytext);}
{DOSYM}			{printf("%s: DOSYM\n", yytext);}
{CALLSYM}		{printf("%s: CALLSYM\n", yytext);}
{CONSTSYM}		{printf("%s: CONSTSYM\n", yytext);}
{VARSYM}		{printf("%s: VARSYM\n", yytext);}
{TYPESYM}		{printf("%s: TYPESYM\n", yytext);}
{PROCSYM}		{printf("%s: PROCSYM\n", yytext);}
{INTCON}		{printf("%s: INTCON\n", yytext);}
{IDENT}			{printf("%s: IDENT\n", yytext);}
{ERROR}			{printf("%s: ERROR\n", yytext);}
\n				{}
.				{}
%%
int yywrap() { return 1; }
int main(int argc, char **argv)
{
    if (argc > 1) {
        if (!(yyin = fopen(argv[1], "r"))) {
            perror(argv[1]);
            return 1;
        }
    }
    while (yylex());
    return 0;
}

先使用win_flex.exe编译pl.l,win_flex.exe --wincompat --outfile=D:\lxc\nbu\software\win_flex_bison-latest\my_code_test/pl.yy.c D:\lxc\nbu\software\win_flex_bison-latest\my_code_test\pl.l
在这里插入图片描述

使用gcc编译pl.yy.c时出现如下,gcc pl.yy.c -o pl

在这里插入图片描述
在这里插入图片描述

双击运行,pl.exe,简单的测试一下词法分析器的能力
在这里插入图片描述

下面测试一个PL语言的Hello world文件的词法分析,PL语言的HelloWorld如下

program HelloWorld;

procedure PrintHello;
begin
  print("Hello, World!");
end;

begin
  PrintHello;
end.

命令行启动pl.exe,并传入文件D:\lxc\nbu\software\win_flex_bison-latest\my_code_test>pl.exe pl.pl
在这里插入图片描述

整个实验过程完整资源下载:https://download.csdn.net/download/xianchao0127/88103102

本文参考:lex原理:https://www.bwangel.me/2019/12/15/flex/、安装lex:https://zhuanlan.zhihu.com/p/551669070、使用:https://blog.csdn.net/wang_yr/article/details/106004464、b站学习课程:https://www.bilibili.com/video/BV11t411V74n

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
实验二 词法分析器 一、实验目的 掌握词法分析器的构造原理,掌握手工编程或LEX编程方法之一。 二、实验内容 编写一个LEX源程序,使之生成一个词法分析器,能够输入的源程序转换为单词序列输出。 三、实验环境 Flex+VC6.0 四、实验注意 1.Id正则表达式:{letter}({letter}|{digit})* 2.Num正则表达式:{digit}+(\.{digit}+)?(E[+-]?{digit}+)? 3.注释:(\/\*(.)*\*\/) 4.关键字再加上其他字符就又能编程id,所以在词法分析时,id的判断应该放在关键字前面,这样才不会误判 5.由于本程序知识简单的打印数字,因此没有考虑数字的转换 6.">="比">"多一个字符,它应该放在前面判断,其他类似的也应该如此安排 五、实验代码 ******************************************************************************* 实验文件:lex.l、lex.yy.c 实验结果:lex.exe 运行方式:打开lex.exe,弹出input.txt,在其中输入所要测试的程序,保存并关闭,即可在output.txt中看到所得结果 ******************************************************************************* %{ void Install(char *type); %} %option noyywrap delim [ \t] newline [\n] digit [0-9] num {digit}+(\.{digit}+)?(E[+-]?{digit}+)? letter [A-Za-z] id {letter}({letter}|{digit})* key ("if"|"while"|"do"|"break"|"true") basic ("int"|"float"|"bool"|"char") op (">="|""|"<"|"="|"!="|"+"|"-"|"*"|"/") comment (\/\*(.)*\*\/) %% delim {;} newline {printf("\n");} {num} {Install("Num");} {key} {Install("Key");} {basic} {Install("Basic");} {op} {Install("Op");} ";" {Install("Comma");} {id} {Install("ID");} {comment} {Install("Comment");} "(" | "[" | "{" {Install("lbracket");} ")" | "]" | "}" {Install("rbracket");} %% void Install(char *s) { fprintf(yyout, "%s:%s ", s, yytext); } int main() { printf("please input the test program in input.txt\n"); system("input.txt"); yyin = fopen("input.txt", "r"); yyout = fopen("output.txt", "w" ); yylex(); fclose(yyout); fclose(yyin); printf("analysis result in output.txt\n"); system("output.txt"); return 0; } 六、实验小结 本次的实验由于使用了flex,所以代码较短,麻烦的事flex的正则式表达,由于该使用规则只有简单介绍,而网上找的教程难免有比重就轻之嫌,所以得到上述表达式着实费力,且有的没有成功,例如bracket的(\ ((.)*\ ))或者("("(.)*")")使用时都没有成功,所以便单独写出,有点不伦不类。至于其他的,都较为简单,完。
编译原理中的词法分析器是一个重要的组成部分,其作用是将源代码转化为一系列的词法单元(tokens)。其中,词法单元是指编程语言中的最小的、有意义的、不可再分的单词,如关键字、标识符、运算符、常量等。 lex是一种常用的词法分析器生成器,它的工作原理是基于正则表达式匹配规则。使用lex的时候,我们需要使用一种被称为lex源文件的文件,其中包含词法规则描述和对应的动作。 在编写lex源文件时,我们需要定义一系列的正则表达式规则,用于匹配不同类型的词法单元。每个规则通常由两部分组成:模式(pattern)和动作(action)。模式用于描述词法单元的形式,而动作则指定了在匹配到该模式时的处理方式。 lex根据这些规则生成一个有限状态自动机,并用于从输入的源代码中识别和提取出对应的词法单元。生成的词法分析器可以作为编译过程的第一步,将源代码分解为一系列的词法单元,供后续的语法分析器使用。 使用lex可以极大地简化词法分析器的编写工作,同时提高了分析效率。通过定义灵活的正则表达式规则,我们可以轻松地适应不同编程语言的需求。 总结起来,词法分析器在编译原理中起着至关重要的作用。lex作为一种词法分析器生成器,可以帮助我们快速构建词法分析器,从源代码中提取出有意义的词法单元,为后续的编译过程打下基础。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值