用Flex构造简易C语言词法分析器

Flex构造C语言词法分析器 可以识别大部分的C语言关键字和标识符,可以去除注释(多行单行都可以),可以识别整数和浮点数,可以识别错误的浮点数。

lex文件结构:

 [第一部分:定义段]
/*
 *按照C语言语法,声明文件包含,宏定义,常数定义,全局变量及外部变量定义,函数声明等
 */
 %%
 第二部分:词法规则段
  /*
 *核心部分,正则定义和状态定义(解释见后)
 */
 %%
 第三部分:辅助函数段]
  /*
 * 辅助函数段用C语言语法来写,辅助函数一般是在词法规则段中用到的函数。这一部分一般会被直接拷贝到lex.yy.c中。
 */

状态定义:

"//".* {}
"/*" {BEGIN COMMENT;}
<COMMENT>"*/" {BEGIN INITIAL;}
<COMMENT>. {}

这一部分是根据不同的状态使用不同的规则,比如要识别多行注释,则添加BEGIN COMMENT即可转移到< COMMENT >状态。

代码如下:

在这里插入代码片/*
 *t2.lex 词法分析器
 *班级:计科1604
 *学号:1030416414
 *姓名:wyc(ORION233)
 *时间:2018-11-4
 */
%option pointer
%option noyywrap
%x COMMENT
%{
    #include <stdio.h>
    #include <string.h>
    #define MAXLEN 100
    #define MAXTYPE 10
    #define MAXSTR 15

    char *a[MAXTYPE] = {"type","for","integer","decimal","identify","bracket","QUOTE","OPT","float"};
    struct {
        int line;	//store line numbers
        int id;		// store tag
        char text[MAXSTR];	//store yytext
    }tag[MAXLEN];	//store tags
    int flag = 0;	//error flag
    int cnt = 0;	//array notation counter
    int line=1;		//line counter
%}
DIGIT [0-9]
OINTEGER [1-9]{DIGIT}*
INTEGER ("+"|"-")?{OINTEGER}
DECIMAL {INTEGER}(.{OINTEGER})?
LETTER [a-zA-Z]
ID ({LETTER}|_)({LETTER}|_|{DIGIT})*
OPT ("+="|"-="|"*="|"/="|"+"|"-"|"*"|"/"|"<="|">="|"=="|"=")
INDEX {DIGIT}+(\.{DIGIT}+)?e([+-])?{DIGIT}+
ERROR {DIGIT}+(\.{DIGIT}+)?e

%%
"//".* {}
"/*" {BEGIN COMMENT;}
<COMMENT>"*/" {BEGIN INITIAL;}
<COMMENT>. {}

\n {++line;}
(int|float|double|short) {
    tag[cnt].line = line;
    tag[cnt].id = 0;
    strcpy(tag[cnt].text,yytext); //has bugs--use strcpy is ok,no pointer 
    //printf("%s : %d--%d\n",tag[cnt].text,yyleng,cnt);
    cnt++;
}
for {
    tag[cnt].line = line;
    tag[cnt].id = 1;
    strcpy(tag[cnt].text,""); 
    //printf("%s : %d--%d\n",tag[cnt].text,yyleng,cnt);
    cnt++;
}
{INTEGER} {
    tag[cnt].line = line;
    tag[cnt].id = 2;
    strcpy(tag[cnt].text,yytext); 
    //printf("%s : %d--%d\n",tag[cnt].text,yyleng,cnt);
    cnt++;
}
{DECIMAL} {
    tag[cnt].line = line;
    tag[cnt].id = 3;
    strcpy(tag[cnt].text,yytext); 
    //printf("%s : %d--%d\n",tag[cnt].text,yyleng,cnt);
    cnt++;
}
{ID} {
    tag[cnt].line = line;
    tag[cnt].id = 4;
    strcpy(tag[cnt].text,yytext); 
    //printf("%s : %d--%d\n",tag[cnt].text,yyleng,cnt);
    cnt++;
}
("("|")"|"{"|"}"|"["|"]") {
    tag[cnt].line = line;
    tag[cnt].id = 5;
    strcpy(tag[cnt].text,yytext); 
    //printf("%s : %d--%d\n",tag[cnt].text,yyleng,cnt);
    cnt++;
}
"\"" {
    tag[cnt].line = line;
    tag[cnt].id = 6;
    strcpy(tag[cnt].text,""); 
    //printf("%s : %d--%d\n",tag[cnt].text,yyleng,cnt);
    cnt++;
}
{OPT} {
    tag[cnt].line = line;
    tag[cnt].id = 7;
    strcpy(tag[cnt].text,yytext); 
    //printf("%s : %d--%d\n",tag[cnt].text,yyleng,cnt);
    cnt++;
}
{INDEX} {
    tag[cnt].line = line;
    tag[cnt].id = 8;
    strcpy(tag[cnt].text,yytext); 
    //printf("%s : %d--%d\n",tag[cnt].text,yyleng,cnt);
    cnt++;
}
{ERROR} {
    flag = 1;
    tag[cnt].line = line;
    tag[cnt].id = -1;	//soso
    strcpy(tag[cnt].text,yytext); 
    cnt++;
}
. {}

%%

int main()
{
    /*
     *begin lexical analysis
     *present all the tags
     *but ...
     */
    yylex();

    if(flag) {//print ERRORS
        int i;
        for(i=0;i<cnt;i++){
            if(tag[i].id == -1){
                printf("Error type A at Line %d: Illegal floating point number \"%s\".\n",tag[i].line,tag[i].text);
                break;
            }
        }
        
    } else {
        int i;
        for(i=0;i<cnt;i++){
            if(tag[i].id == 5){//print "QUOTE"
                printf("line%d:(%s, \"%s\")\n",tag[i].line,a[tag[i].id],tag[i].text);
            } else {
                printf("line%d:(%s, %s)\n",tag[i].line,a[tag[i].id],tag[i].text);
            }
        }
    }
    
    return 0;
}

用Flex构造简易C语言词法分析器
https://orion-wyc.github.io/2019/01/14/2019-01-15-用Flex构造简易C语言词法分析器/
作者
Yuchen
发布于
2019年1月15日
许可协议