zoukankan      html  css  js  c++  java
  • 编译原理 — 用Flex构造词法分析器

    基于Flex构造词法分析器

    【问题描述】设计c语言常见单词的正规式,编制lex源文件,利用flex编译得到词法分析的.c文件,继而对该文件编译得到词法分析器。

    【输入形式】输入一段c语言程序

    【输出形式】各类单词的token字,或者给出程序中的单词错误。

    【样例输入】

    int main(){

        int a = 10;

        double b = 20.9;

        if(a <= b)

            a+=b;

        else a = 0;

        return a;

    }

    【样例输出】

    line1:(type, int)

    line1:(keyword, main)

    line1:(bracket, ()

    line1:(bracket, ))

    line1:(bracket, {)

    line2:(type, int)

    line2:(identify, a)

    line2:(OPT, =)

    line2:(integer, 10)

    line2:(bracket, ;)

    line3:(type, double)

    line3:(identify, b)

    line3:(OPT, =)

    line3:(decimal, 20.9)

    line3:(bracket, ;)

    line4:(keyword, if)

    line4:(bracket, ()

    line4:(identify, a)

    line4:(OPT, <=)

    line4:(identify, b)

    line4:(bracket, ))

    line5:(identify, a)

    line5:(OPT, +=)

    line5:(identify, b)

    line5:(bracket, ;)

    line6:(keyword, else)

    line6:(identify, a)

    line6:(OPT, =)

    line6:(integer, 0)

    line6:(bracket, ;)

    line7:(keyword, return)

    line7:(identify, a)

    line7:(bracket, ;)

    line8:(bracket, })

    【样例说明】需要识别的关键字包括void, int, main, double, return, float, if, else, do, while, for, scanf, printf, char, sqrt, abs, 运算符(算术、关系、逻辑、位);需要识别的其他单词有标识符, 整数(十进制形式、指数形式),实数(十进制形式、指数形式),字符串;过滤注释及空格。

    【评分标准】根据设计文档的质量、lex文件的正确性,代码的正确性、代码的时间空间复杂度、识别单词的种类等综合评分

    flex就简单学了一下,最后看了别人的代码,模仿着写了一个。

    .I文件

    /*e.l*/
    %option main
    %option yywrap
    %{
        #include <stdio.h>
        #include <string.h> 
    	int Row=1;
    	char *Ans = "";
    %}
    KeyWord("main"|"double"|"return"|"float"|"if"|"else"|"do"|"while"|"for"|"scanf"|"printf"|"char"|"sqrt"|"abs"|"float") 
    OPT ("+"|"-"|"%"|"*"|"/"|"+="|"-="|"*="|"/="|">"|"<"|"<="|">="|"=="|"="|"&"|"|"|"!"|"<<"|">>")
    Identify ({Letter}|_)({Letter}|_|{Digit})*
    Digit [0-9]
    UnsignedInteger [1-9]{Digit}*
    Integer ("+"|"-")?{Digit}+("e"(("+"|"-"){UnsignedInteger})?)?
    Decimal {Integer}.{Digit}+
    Float {Integer}.{Digit}+("e"(("+"|"-"){UnsignedInteger})?)?
    Letter [a-zA-Z] 
    Comment ("/*"|"*").* 
    Type ("int"|"double"|"short"|"char"|"void"|"long")
    Bracket ("("|")"|"{"|"}"|"["|"]"|";"|","|""")
    Typeidentity ("%"|"&")[a-z]
    Next("
    ") 
    %%
    {Type} {
    	AddOutput(Row, "type", yytext);
    }  
    {KeyWord} {
    	AddOutput(Row, "keyword", yytext);
    } 
    {OPT} {
    	AddOutput(Row, "OPT", yytext);
    } 
    {Identify} {
    	AddOutput(Row, "identify", yytext);
    } 
    {Integer} {
    	AddOutput(Row, "integer", yytext);
    } 
    {Decimal} {
    	AddOutput(Row, "decimal", yytext);
    } 
    {Float} { 
    	char *p = strchr(yytext, 'e');
    	if (p && yytext[strlen(yytext)-1] == 'e'){
    		printf("Error at Line %d: Illegal floating point number "%s".
    ",Row,yytext);
    		return;
    	} else {
    		AddOutput(Row, "float", yytext);
    	}
    } 
    {Next} {++Row;} 
    
    {Typeidentity} {
    	AddOutput(Row, "typeidentify", yytext);
    } 
      
    {Bracket} {
    	AddOutput(Row, "bracket", yytext);
    } 
    
    {Comment} {} 
    . {}
    %%
    int yywrap()
    {
    	printf("%s", Ans);
    	return 1;
    } 
    void AddOutput(int Row, char* type, char* text){ 
    	char str[50];
    	sprintf(str, "line%d:(%s, %s)
    ", Row, type, text);
    	char *tmp = Ans; 
    	Ans = (char *) malloc(strlen(tmp) + strlen(str) + 1);
    	sprintf(Ans, "%s%s", tmp, str); 
    	if(strlen(tmp) > 0)
    		free(tmp);
    	return ;
    }
    

      把这个文件拖到  win_flex.exe  生成  lex.yy.c

    第一题(得分1.00)

    一开始没有接触过Flex工具,通过老师推荐的教程《flex与bison》对它有了大致的了解,做了几个书上的案例,结合CSDN上完成词法分析器的教程,完成了第一题。

    Lex源文件很大一部分都是抄书上和教程上的,但因为学Lex的时间太短了,对于这个Lex的一些语句还不是特别理解,只是勉强能解决简单的词法分析任务,并不清楚Lex内函数的实现细节。

    使用Lex来完成词法分析任务能大大减少我们的工作量。源文件仅仅使用了八十多行代码就完成了任务,相对于自己手写的两百行代码,极大的降低了任务的复杂度。更重要的是通过lex生成的代码质量高,可靠性好,比手写词法分析器产生的Bug应该会少一些。

    但这并不意味着手写代码就不如Lex生成的代码。因为Lex生成的lex.yy.c文件有一千九百行,很不方便程序员对代码进一步修改,并且并不是每个人都很清楚函数的实现细节,如果真的出现Bug,对于普通人来说很难解决。  

    虽然通过了四组测试案例,但是还是有一些问题没有解决:

    1.关键字和数据类型的问题没有解决。

    在样例中可以看到,Int属于type类型,而float属于keyword类型。对于这种既是数据类型,又是关键字的词,题干中没有明确说明如何划分。

    2. 我设置的小数类型是这样的

    Decimal {Integer}.{Digit}+,

    但在我自己测试的时候出现了这样的问题,他把20-1识别成了一个小数。

     

    图一 存在的BUG1

    3. 我设置的整数类型是这样的

    Integer ("+"|"-")?{Digit}+("e"(("+"|"-"){UnsignedInteger})?)?

    可是测试的时候把2e3识别成了小数

     

    图一 存在的BUG2

  • 相关阅读:
    HDU 2899 Strange fuction
    HDU 2899 Strange fuction
    HDU 2199 Can you solve this equation?
    HDU 2199 Can you solve this equation?
    Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)
    Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)
    Java实现 LeetCode 700 二叉搜索树中的搜索(遍历树)
    Java实现 LeetCode 699 掉落的方块(线段树?)
    Java实现 LeetCode 699 掉落的方块(线段树?)
    Java实现 LeetCode 699 掉落的方块(线段树?)
  • 原文地址:https://www.cnblogs.com/SunChuangYu/p/13978912.html
Copyright © 2011-2022 走看看