編譯原理實驗——flex語法實現簡單詞法分析器


一、實驗目的

設計、編制並調試一個詞法分析程序,加深對詞法分析原理的理解。

二、實驗要求

2.1 待分析的簡單的詞法
(1)關鍵字:
begin if then while do end
所有的關鍵字都是小寫。
(2)運算符和界符
:= + - * /
< <= <> > >= =
; ( ) #
(3)其他單詞是標識符(ID)和整型常數(NUM),通過以下正規式定義:
ID = letter (letter | digit)*
NUM = digit digit*
(4)空格有空白、制表符和換行符組成。空格一般用來分隔ID、NUM、運算符、界符和關鍵字,詞法分析階段通常被忽略。

2.2 各種單詞符號對應的種別碼:
表2.1 各種單詞符號對應的種別碼
image

2.3 詞法分析程序的功能:
輸入:所給文法的源程序字符串。
輸出:二元組(syn,token或num)構成的序列。
其中:syn為單詞種別碼;
token為存放的單詞自身字符串;
num為整型常數。
例如:對源程序begin x:=9; if x>9 then x:=2*x+1/3; end #的Pascal源文件,經過詞法分析后輸出如下序列:
(1,begin)(10,x)(18,:=)(11,9)(26,;)(2,if)…

三、實驗過程

  • 首先需要了解flex語法格式

%{
C語言聲明,一般聲明全局變量和函數,以及頭文件包含,會復制進lex.yy.c中
%}
定義正則表達式的名字,可以在規則段中使用
%%
規則段,每一行都是一條規則,每一條規則由匹配模式和動作組成。每當一個模式被匹配到,后面的動作被執行!模式一般使用正則表達式書寫,動作部分為C代碼
%%
用戶自定義過程,直接復制到lex.yy.c末尾

  • 下表列出了部分常用的正則表達式

image

  • flex提供的2個全局變量:
yytext:剛剛匹配到的字符串
yyleng:剛剛匹配到的字符串的長度
  • 代碼段如下(注意:規則行務必沒有縮進,且對應的動作必須在同一行開始):
%{
#include <stdio.h>
#include <string.h>

%}

ALPHA     [a-zA-Z]
ID        {ALPHA}+[a-zA-Z0-9_]*
KEY       begin|if|then|while|do|end
NUM       [\-]?[1-9][0-9]*|0  

%%

{KEY}		{
			if(yytext[0]=='b')
				printf("(1,%s)",yytext);
			else if(yytext[0]=='i')
				printf("(2,%s)",yytext);
			else if(yytext[0]=='t')
				printf("(3,%s)",yytext);
			else if(yytext[0]=='w')
				printf("(4,%s)",yytext);
			else if(yytext[0]=='d')
				printf("(5,%s)",yytext);
			else if(yytext[0]=='e')
				printf("(6,%s)",yytext);
		}
{ID}  	  	 printf("(10,%s)",yytext); 
{NUM}		printf("(11,%s)",yytext);
\+		printf("(13,%s)",yytext);
\-		printf("(14,%s)",yytext);
\*		printf("(15,%s)",yytext);
\/		printf("(16,%s)",yytext);
\:		printf("(17,%s)",yytext);
\:=		printf("(18,%s)",yytext);
\<		printf("(20,%s)",yytext);
\<>		printf("(21,%s)",yytext);
\<=		printf("(22,%s)",yytext);
\>		printf("(23,%s)",yytext);
\>=		printf("(24,%s)",yytext);
\=		printf("(25,%s)",yytext);
;		printf("(26,%s)",yytext);
\(		printf("(27,%s)",yytext);
\)		printf("(28,%s)",yytext);
\#		printf("(0,%s)",yytext);
\n               	printf("\n");
. 

%%

int main(int argc, char **argv)
{
  yylex();
 
  yywrap();
}
int yywrap()
{
	return 1;
}

解釋:

  • ALPHA是字母,ID是標識符,KEY是關鍵字,NUM整型常數
  • 關鍵字比標識符優先,所以要放它前面,不然識別會有錯誤
  • 符號'.'表示除\n外的所有字符
  • 整型常數可以是負數也可以是0
  • 匹配的那些符號,要加上雙引號或者在前面都加上\(轉義字符)

四、實驗結果

  1. 用管理員身份打開cmd窗口
  2. 進入到該代碼文本文件所在的文件夾內
  3. 然后輸入下面兩行命令,完成對代碼的編譯生成。
    flex test.l //此后會生成C文件lex.yy.c
    gcc lex.yy.c //使用gcc編譯成可執行文件
  4. 我這里生成的是a.exe文件,在窗口中輸入a.exe或a回車,運行該文件
    即可輸入字符串來驗證結果。

image

image

image

image

可以看到結果是正確的。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM