實驗一 簡單詞法分析程式設計
一、實驗目的
了解詞法分析程式的基本構造原理,掌握詞法分析程式的手工構造方法。
二、實驗内容
1、了解編譯程式的詞法分析過程。
2、根據pascal語言的說明語句形式,用手工方法構造一個對說明語句進行詞法分析的程式。該程式能對從鍵盤輸入或從檔案讀入的形如:
“const count=10,sum=81.5,char1=’f’,string1=”hj”, max=169;”
的常量說明串進行處理,分析常量說明串中各常量名、常量類型及常量值,并統計各種類型常量個數。
三、實驗要求
1、輸入的常量說明串,要求最後以分号作結束标志;
2、根據輸入串或讀入的文本檔案中第一個單詞是否為“const”判斷輸入串或文本檔案是否為常量說明内容;
3、識别輸入串或打開的文本檔案中的常量名。常量名必須是辨別符,定義為字母開頭,後跟若幹個字母,數字或下劃線;
4、根據各常量名緊跟等号“=”後面的内容判斷常量的類型。其中:字元型常量定義為放在單引号内的一個字元;字元串常量定義為放在雙引号内所有内容;整型常量定義為帶或不帶+、-
号,不以0開頭的若幹數字的組合;實型常量定義為帶或不帶+、-
号,不以0開頭的若幹數字加上小數點再後跟若幹數字的組合;
5、統計并輸出串或檔案中包含的各種類型的常量個數;
6、以二進制組(類型,值)的形式輸出各常量的類型和值;
7、根據常量說明串置于進階語言源程式中時可能出現的錯誤情況,模仿進階語言編譯器對不同錯誤情況做出相應處理。
四、運作結果
1、輸入如下正确的常量說明串:
const count=10,sum=81.5,char1=‘f’,max=169,str1=“h*54 2..4s!aasj”, char2=‘@’,str2=“aa!+h”;
輸出:
count(integer,10)
sum(float,81.5)
char1(char, ‘f’)
max(integer,169)
str1(string,“h*54
2..4s!aasj”)
char2(char, ‘@’)
str2(string,“aa!+h”)
int_num=2;
char_num=2; string_num=2; float_num=1.
2、輸入類似如下的保留字const錯誤的常量說明串:
aconstt count=10,sum=81.5,char1=‘f’;
輸出類似下面的錯誤提示資訊:
it is not a constant declaration statement!
please input a string again!
3、輸入類似如下含常量名或常量值錯誤的常量說明串:
const count=10,12sum=81.5,char1=‘ff’,max=0016;
12sum(wrong! it is not a identifier!)
char1(wrong! there are
more than one char in ‘’.)
max(wrong! the integer can’t be started with ‘0’.)
int_num=1;
char_num=0; string_num=0; float_num=0.
4、其他類型的錯誤處理情況(略)。
五、提示
本實驗重點有三個:一是作為常量名的辨別符的識别;二是如何根據“=”後出現的内容來判斷常量類型;三是對各種錯誤的處理。難點是對整型和實型常量的判斷必須綜合考慮多種可能情況。
建議:1、用指針或數組與指針相結合來處理輸入的常量說明串;2、對整型和實型常量處理時,重點考慮常數中‘0’的位置。
六、分析與讨論
1、若考慮用e或e的科學計數法來表示整數和實數,應該如何實作?
2、若考慮布爾型常量,且規定其值隻能為true或false,應該如何實作?
3、如何對手工構造的詞法分析程式做進一步的優化,以提高代碼品質和運作效率?
#include<ctype.h>
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#define n 80
#define m 16
void check_const();
void measure_iden();
void measure_string();
void measure_digit();
void measure_char();
char cha;
int ci=0,cf=0,cc=0,cs=0;
char *p0,*t0,*p1,*t1, *p2,*str,*p3,*t3="const",*digi,*flo;
void main()
{
printf("please input string: \n");
p0=(char *)malloc(n*sizeof(char));
p1=(char *)malloc(m*sizeof(char));
p2=(char *)malloc(m*sizeof(char));
p3=(char *)malloc(m*sizeof(char));
gets(p0);
printf("\n");
check_const();
/* 開始處理輸入串 p0 */
while(*(p0)==' '||*(p0)==',') /*從串p0中取辨別符,并将其作為常量名存放到串p1中 */
{
p0++;
if(*(p0)==' '||*(p0)==',')
continue;
else
{
measure_iden(); //*p0=="="
if(!isdigit(*p0)&&*p0!='\"'&&*p0!='\'')//注意'和"做字元表示時用\'和\"
system("cls");
printf("\n const data is wrong . exit !");
exit(0);
}
else if(*p0=='\"') /* 處理字元串常量 */
{
p0++;
measure_string();
}
else if(isdigit(*p0)) /* 處理數字 */
measure_digit();
else if(*p0=='\'') //處理字元常量
measure_char();
}
if(*p0!=';')
{
system("cls");
printf("\n this centence is wrong . exit !");
exit(0);
else
printf("int_num=%d; char_num=%d; string_num=%d; float_num=%d.\n",ci,cc,cs,cf);
}
/* 檢查輸入串是否以"'const"開頭 */
void check_const()
while(*p0!=' ')
if(*p0==*t3)
t3++;
printf("this string isn't a const declaration!");
void measure_iden()
if (*p0!='_'&&(!isalpha(*p0)))
printf("\n const name is wrong . exit !");
}
else if (*p0=='_'||isalpha(*p0))
t1=p1;
while(*p0!='=')
*p1=*p0;
p1++;
*p1='\0';
// printf("%s\n",p0);
printf("%s",t1);
void measure_string()
str=p2;
while(*(p0)!='\"')
*p2=*p0;
if(*(p0)==';')//丢了個分号,直接輸出string data is wrong. exit
printf("\n string data is wrong. exit !");
p2++;
*p2='\0';
p0++;
cs++;
printf("(string,\"%s\")\n",str);
void measure_digit()
char *jud;
int mark=0;
jud=p0;
for(;*(jud)!=','&&*(jud)!=';';jud++)
if(*jud=='.')
mark=1;
break;
if(mark==0)
digi=p2;
while(*p0!=','&&*p0!=';')
*p2=*p0;
p2++;
*p2='\0';
ci++;
printf("(integer,%s)\n",digi);
if(mark==1)
flo=p2;
cf++;
printf("(float,%s)\n",flo);
void measure_char()
if(*(jud+1)=='\''&&*(jud)!='\'')
cha=*p0;
p0=p0+2;
cc++;
printf("\n char data is wrong. exit !");
printf("(char,'%c')\n",cha);