編譯原理實驗
一、實驗目的
-
學習使用詞法分析程式自動構造工具 Flex
-
熟悉LEX源程式語法
-
掌握詞法分析程式的自動構造方法 二、實驗平臺 Windows + Flex 三、基礎內容
-
實現以下步驟, 掌握Flex的工作過程 i. 構造 LEX 源程式, 例如命名為 Test.Lex ii. 編譯 LEX 源程式, 生成C語言詞法分析程式 lex.yy.c, 步驟如下: 在DOS命令提示符下執行編譯 flex Test.Lex 得到目標檔案 lex.yy.c iii. 在VC中編譯 lex.yy.c,產生可執行程式 lex.yy.exe iv. 執行生成的可執行檔案 lex.yy 或 lex.yy < InputFile
-
測試目錄 SRC_FLEX中的範例程式,瞭解其功能及實現。
四、附加內容 ★★ 輸入一個 C源程式檔案, 用FLex 實現以下任務 a) 新增行號。 b) 將檔案中每個非空的空白符號序列替換為單個空格。 c) 將檔案中所有關鍵字轉換為大寫字母。 d) 將檔案中所有識別符號轉換為小寫字母,且以下劃線開頭。 e) 將檔案中所有指數形式的常量轉換為小數形式。 例如: 2.5e3 被轉換為 2500 3.7e-2 被轉換為 0.037 f) 將轉換後的檔案存入另一個檔案。
參考資料
- LEX範例程式:SRC_FLEX
b.lex檔案如下:
%{ #include <stdio.h> FILE *f1; FILE *f2; int hanghao=2; %} keyword auto|break|case|char|const|continue|default|do|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while|AUTO|BREAK|CASE|CHAR|CONST|CONTINUE|DEFAULT|DO|DOUBLE|ELSE|ENUM|EXTERN|FLOAT|FOR|GOTO|IF|INT|LONG|REGISTER|RETURN|SHORT|SIGNED|SIZEOF|STATIC|STRUCT|SWITCH|TYPEDEF|UNION|UNSIGNED|VOID|VOLATILE|WHILE id [A-Za-z]+ digit [0-9] huan {digit}+(\.{digit}+)?(E[+-]?{digit}+)? %% [ ]+ {fprintf(f1," ");} \n {fprintf(f1,"%s%u",yytext,hanghao++);} {keyword} { int i; for(i=0;i<yyleng;i++) { if(yytext[i]>='a'&&yytext[i]<='z') yytext[i]-=32; } fprintf(f1,"%s",yytext); } {id} { int i; for(i=0;i<yyleng;i++) { if(yytext[i]>='A'&&yytext[i]<='Z') yytext[i]+=32; } fprintf(f1,"_%s",yytext); } {huan} { float t=0; t=atof(yytext); fprintf(f1,"%f",t); } . fprintf(f1,"%s",yytext); %% int yywrap(void) { return 1; } main() { f1=fopen("f1.txt","w+"); fprintf(f1,"1"); yylex(); fclose(f1); f1=fopen("f1.txt","r"); f2=fopen("f2.txt","w"); char e; while((e=fgetc(f1) )!= EOF ) {fputc(e,f2);} fclose(f1); fclose(f2); }
一、實驗目的
-
學習使用詞法分析程式自動構造工具Flex
-
熟悉LEX源程式語法
-
掌握詞法分析程式的自動構造方法
二、實驗平臺 Windows+ Flex
三、基礎內容
- 實現以下步驟, 掌握Flex的工作過程
i. 構造 LEX 源程式, 例如命名為 Test.Lex
ii. 編譯 LEX 源程式, 生成 C 語言詞法分析程式 lex.yy.c, 步驟如下:
在 DOS 命令提示符下執行編譯 flex Test.Lex 得到目標檔案 lex.yy.c iii. 在 VC 中編譯lex.yy.c,產生可執行程式lex.yy.exe
iv. 執行生成的可執行檔案 lex.yy 或 lex.yy < InputFile
- 測試目錄SRC_FLEX中的範例程式,瞭解其功能及實現。
四、附加內容 輸入一個 C 源程式檔案, 用 FLex 實現以下任務
a) 新增行號。
b) 將檔案中每個非空的空白符號序列替換為單個空格。
c) 將檔案中所有關鍵字轉換為大寫字母。
d) 將檔案中所有識別符號轉換為小寫字母,且以下劃線開頭。
e) 將檔案中所有指數形式的常量轉換為小數形式。
例如: 2.5e3被轉換為 2500 3.7e-2 被轉換為 0.037 f) 將轉換後的檔案存入另一個檔案。
宣告部分
%%
轉換規則
%%
輔助函式
Lex程式的每個轉換規則的形式如下:
模式{動作}
%{%} 括號中間的所有內容將直接複製到lex.yy.c中。
一個lex程式的結構如下:
yytext 是一個指向詞素開頭的指標 yyleng存放剛找到的詞素的長度 原始碼: Demo.lex
%{
#include<stdio.h>
FILE* f1;
int n =1;
%}
keywords auto|break|case|char|const|continue|defaultdo|double|else|enum|extern|float|for|goto|if|int|long|register|return|short|signed|sizeof|static|struct|switch|typedef|union|unsigned|void|volatile|while
id [a-zA-Z][a-zA-Z0-9]*
number [0-9]
enumber {number}+(\.{number}+)?e([+-])?{number}+
space [\ \t]+
%%
{space} {fprintf(f1," ");}
{keywords} {
int i = 0;
while(i<yyleng && yytext[i]>='a' && yytext[i]<='z')
{
yytext[i]-=32;
i++;
}
fprintf(f1,"%s",yytext);
}
{id} {
int i =0 ;
while(i<yyleng && yytext[i]>='A' && yytext[i]<='Z')
{
yytext[i]+=32;
i++;
}
fprintf(f1,"_%s",yytext);
}
{enumber} {
float f = atof(yytext);
fprintf(f1,"%f",f);
}
[^\n] {fprintf(f1,"%s",yytext);}
\n {
fprintf(f1,"%s%5d ",yytext,n++);
}
%%
int yywrap(void)
{
return 1;
}
main()
{
f1 = fopen("demo.txt","a+");
fprintf(f1,"%5d ",n++);
yylex();
fprintf(f1,"\n");
fclose(f1);
}
執行:
將生成的lex.yy.c編譯
用lex.yy.exe 開啟一個檔案
規則化的檔案: