用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;
}



本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!