當前位置:首頁 » 編程語言 » c語言詞法分析程序設計
擴展閱讀
webinf下怎麼引入js 2023-08-31 21:54:13
堡壘機怎麼打開web 2023-08-31 21:54:11

c語言詞法分析程序設計

發布時間: 2022-09-28 08:52:30

c語言的詞法分析器

任務1:識別小型語言所有單詞的詞法分析程序設計
源程序設計語言
G[<程序>]
<程序>→<變數說明><BEGIN>
<語句表>
<END>.
<變數說明>→VAR<變數表>:<類型>;|<空>
<變數表>→<變數表>,<變數>|<變數>
<類型>→INTEGER
<語句表>→<語句>
|
<語句>;<語句表>
<語句>→<賦值語句>|<條件語句>|<WHILE語句>|<復合語句>
<賦值語句>→<變數>:=<算術表達式>
<條件語句>→IF<關系表達式>THEN<語句>ELSE<語句>
<WHILE語句>→WHILE<關系表達式>DO<語句>
<復合語句>→BEGIN<語句表>END
<算術表達式>→<項>|<算術表達式>+<項>|<算術表達式>-<項>
<項>→<因式>|<項>*<因式>|<項>/<因式>
<因式>→<變數>|<整數>|(<算術表達式>)
<關系表達式>→<算術表達式><關系符><算術表達式>
<變數>→<標識符>
<標識符>→<標識符><字母>|<標識符><數字>|<字母>
<整數>→0|<非零數字><泛整數>
<泛整數>→<數字>|<數字><泛整數>|ε
<關系符>→<|<=|==|>|>=|<>
<字母>
→A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
<非零數字>→1|2|3|4|5|6|7|8|9
<數字>→<非零數字>|0
<空>→
要求和提示:
詞法分析階段,可以打開任意位置和名稱的源文件進行詞法分析,可以進行非法字元和數字後邊跟字母的錯誤判斷,如果沒有錯誤則提示「詞法分析正確完成!」,並且可以選擇輸出token.txt(token文件)string.txt(符號表)兩個文件;
1.詞法分析程序的主要任務如下:

組織源程序的輸入,識別出源程序中的各個基本語法單位(也稱為單詞或語法符號),按規則轉換成二元式的形式;

刪除無用的空白字元、回車符、及其它非實質性符號;

刪除註解行;

為後面的語法和語義分析提供二元式鏈表;
單詞
編碼
單詞
編碼
標識符
1
<
15
正整數
2
<=
16
BEGIN
3
>
17
END
4
>=
18
IF
5
<>
19
THEN
6
==
20
ELSE
7

21
WHILE
8

22
DO
9
:=
23
INTEGER
10

24
+
11
(
25
-
12

26
*
13
/
14
1)
對標識符的長度控制在8個字元(包括8個)以內,超過的做截斷處理;
2)
數字不大於65535,否則報錯;
3)
能跳過源程序中的空白格:兩個單詞之間的任何空格,製表符,回車,換行都是白空格,除了用來分隔單詞以外,沒有意義;
4)
能跳過注釋:
a)
接連出現的/*到下一次接連出現的*/之間的任何文字都是注釋(多行);
b)
從某行接連出現的//到該行的結尾的任何文字都是注釋(單行)。
3.怎樣編寫詞法分析程序:
1)
預處理:把源文件一個字元一個字元的讀入詞法分析程序設置的輸入字元結構體數組中(輸入緩沖區),讀入過程要刪除注釋,刪除多餘的白空格;
2)
從源程序字元數組中獲得單詞,
編碼為二元式.:
二元式採用結構體數組存儲,
把單詞類型和詞元記錄下來。
分解單詞的方法:
1)
Case多路轉換語句根據單詞的特點直接編寫;
2)
通過描述單詞的正規文法得到相應的有窮自動機,通過case多路轉換語句完成有窮自動機的處理流程。
3.編寫詞法分析程序要注意的問題:
1)
檢查詞法是否有錯誤
檢查是否有非法字元:如
@,
&,
!
檢查標志符和數字是否滿足限制條件
檢查注釋符號是否配對
2)
符分隔單詞
能夠區分兩個單詞的符號為界符
有些界符不是單詞:如白空格
有些界符僅僅用來分隔:如;
有些界符本身還是源程序不可缺少的單詞,如(,
),
+,
/,
等等
有些界符包含兩個字元:如<>,
>=等等
3)
輸出詞法錯誤
如果有錯誤,需要報告詞法錯誤的原因。並且要能夠越過錯誤,分解下一個單詞,直到源程序結束。
4)
輸出的二元式流保存在二元式結構體數組中。

❷ 求c語言詞法分析程序

以前學c語言的時候寫的,但是沒有經過很好的設計,程序結構比較亂。運行沒有問題。也可以處理包含的頭文件。

/*************************************************
c語言分析程序
*************************************************/
#include"stdio.h"
#include"stdlib.h"
#include"string.h"
char *key[]={"auto","bool","break","case","char","complex","const","continue","default","restrict","do","double","else","enum","extern","float","for","goto","if","imaginary","inline","int","long","register","return","stort","signed","sizeof","static","struct","switch","tyepdef","union","unsigned","void","volatile","while"};
char *limit[]={"#","(",")","[","]","'","\"",";",":","{","}","\\",","};
char *ysf[]={"!","%","^","&","*","-","+","=","~","|",".","<",">","/","?",":","+=","-=","*=","/","%=","<<=",">>=","&=","^=","|=","->","++","--","<<",">>","<=",">=","==","!=","&&","||"};
char b[30];
char fn[20]={'\0'},text1[1000]={'\0'},string[30]={'\0'},text2[1000]={'\0'},kuoru[30];
char hm[10][30],hz[10][30];
char * tempp;
int z=1,y;
int i=0,j=0,k=1,n=1,p=1,q=1,o=1,m=1,x=0,temp,k1=0,k2=0,keyy,key1=0,key2=0,key3=0,key4=0,key5=0,key6=0;
FILE * sfhead;
FILE * ofhead;
FILE * bsfhead;
FILE * zsclbhead;
FILE * fdsclbhead;
FILE * zfclbhead;
FILE * zfcclbhead;
FILE * fgfhead;
FILE * ysfhead;
FILE * blzhead;
FILE * krhead;
bool find1(char * p){
int i=0;
for(i=0;i<36;i++){
if(strcmp(key[i],p)==0)
return true;
}
return false;
} /*判斷提取的字元串是否屬於保留字*/
int bianma1(char * p){
int i=0;
for(i=0;i<36;i++){
if(strcmp(key[i],p)==0)
return i+1;
}
return -1; /*確定保留字的序號*/
}
bool find2(char p){
int i=0;
for(i=0;i<13;i++){
if(*limit[i]==p)
return true;
}
return false;
} /*判斷提取的符號是否為分隔符*/
int bianma2(char p){
int i=0;
for(i=0;i<13;i++){
if(*limit[i]==p)
return i+1;
}
return -1;
} /*確定分割符的序號*/
bool find3(char p){
int i=0;
for(i=0;i<37;i++){
if(*ysf[i]==p)
return true;
}
return false;
} /*判斷提取的符號是否為運算符*/
int bianma3(char * p){
int i=0;
for(i=0;i<37;i++){
if(strcmp(ysf[i],p)==0)
return i+1;
}
return -1;
} /*確定運算符的序號*/
int bianma4(char * p){
int i=0;
for(i=0;i<10;i++){
if(strcmp(hm[i],p)==0)
return i;
}
return -1;
}
bool search(FILE * fp,char * p){
char a[30],c[30];
rewind(fp); /*將fp指向文件頭部*/
while(!feof(fp)){
fscanf(fp,"%s",a);
if(strcmp(a,p)==0){ /*保存編碼*/
fgets(b,30,fp);
return true;
}else
fgets(c,30,fp);
}
return false;
}
void clnmb(char * text){ /*處理以數字開頭的函數*/
bool l=true;
string[j]=text[i];
i++;j++;
while(((text[i]>='0')&&(text[i]<='9'))||text[i]=='.'||text[i]=='e'||text[i]=='E'||text[i]=='-'){
string[j]=text[i];
if(text[i]=='.')
l=false;
i++;j++; /*判斷數字字元串中有無小數點,如果有則證明位浮點數*/
}
if(l){
if(search(zsclbhead,string)){ /*返回原表查詢,防止重復出現*/
fprintf(zsclbhead,"\n\r%s\t",string);
fprintf(zsclbhead,"%s",b);
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}else{
fprintf(zsclbhead,"\n\r%s\t",string);
fprintf(zsclbhead,"4\t");
fprintf(zsclbhead,"0\t");
fprintf(zsclbhead,"%d\t\n\r",m);
fprintf(ofhead,"\n\r%s\t",string);
fprintf(ofhead,"4\t");
fprintf(ofhead,"0\t");
fprintf(ofhead,"%d\t\n\r",m);
m++; /*用m標記出現整數常量的地址*/
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}
}else{
if(search(fdsclbhead,string)){ /*返回原表查詢,防止重復出現*/
fprintf(fdsclbhead,"\n\r%s\t",string);
fprintf(fdsclbhead,"%s",b);
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}else{
fprintf(fdsclbhead,"\n\r%s\t",string);
fprintf(fdsclbhead,"4\t");
fprintf(fdsclbhead,"1\t");
fprintf(fdsclbhead,"%d\t\n\r",o);
fprintf(ofhead,"\n\r%s\t",string);
fprintf(ofhead,"4\t");
fprintf(ofhead,"1\t");
fprintf(ofhead,"%d\t\n\r",o); /*用o標記出現的浮點數常量地址*/
o++;
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}
l=true;
}
}
void dayin(FILE * fp){
int i;
char temp[40];
rewind(fp);
while(!feof(fp)){
fgets(temp,40,fp);
printf("%s",temp);
}
for(i=0;i<40;i++)
temp[i]='\0';
}
/****************************************
掃描分析程序段
*****************************************/
void saomiao(char * text){
i=0;
while(text[i]!='\0'){
if((text[i]>='a'&&text[i]<='z')||(text[i]>='A'&&text[i]<='Z')){ /*分析以字母開頭的情況*/
while((text[i]>='a'&&text[i]<='z')||(text[i]>='A'&&text[i]<='Z')||text[i]=='_'||(text[i]>='0'&&text[i]<='9')){
string[j]=text[i];
i++;j++;
}
if(find1(string)){ /*判斷是否為保留字*/
fprintf(blzhead,"\n\r%s\t",string);
fprintf(blzhead,"0\t");
fprintf(blzhead,"%d\t\n\r",bianma1(string));
fprintf(ofhead,"\n\r%s\t",string);
fprintf(ofhead,"0\t");
fprintf(ofhead,"%d\t\n\r",bianma1(string)); /*將字元串直接寫入相應的文件和輸出文件*/
for(j=0;j<30;j++) /*將string數組清空,防止出現錯誤*/
string[j]='\0';
j=0;
}
else {
if((keyy=bianma4(string))!=-1){
temp=i;
tempp=text;
i=0;
for(j=0;j<30;j++) /*將string數組清空,防止出現錯誤*/
string[j]='\0';
j=0;
clnmb(hz[keyy]);
text=tempp;
i=temp;
}else
if(search(bsfhead,string)){ /*返回原表查詢,防止重復出現*/
fprintf(bsfhead,"\n\r%s\t",string);
fprintf(bsfhead,"%s",b);
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}else{
fprintf(bsfhead,"\n\r%s\t",string);
fprintf(bsfhead,"3\t");
fprintf(bsfhead,"%d\t\n\r",k);
fprintf(ofhead,"\n\r%s\t",string);
fprintf(ofhead,"3\t");
fprintf(ofhead,"%d\t\n\r",k);
k++; /*用k標記出現標識符的地址*/
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}
}
}
else if((text[i]>='0')&&(text[i]<='9')) /*分析以數字開頭的情況*/
clnmb(text);
else if(find2(text[i])){ /*分析以分隔符開頭的情況*/
if(text[i]=='{') key1++;
if(text[i]=='}') key2++;
if(text[i]=='[') key3++;
if(text[i]==']') key4++;
if(text[i]=='(') key5++;
if(text[i]==')') key6++;
string[0]=text[i];
if(text[i]=='\"'){ /*考慮其中可能出現的一"開頭的字元串類型常量*/
do{
string[j]=text[i];
j++;i++;
}while(text[i]!='\"');
string[j]=text[i];
i++;j++;
if(search(zfcclbhead,string)){ /*返回原表查詢,防止重復出現*/
fprintf(zfcclbhead,"\n\r%s\t",string);
fprintf(zfcclbhead,"%s",b);
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}else{
fprintf(zfcclbhead,"\n\r%s\t",string);
fprintf(zfcclbhead,"4\t");
fprintf(zfcclbhead,"3\t");
fprintf(zfcclbhead,"%d\t\n\r",q); /*用q標記出現字元串常量的地址*/
fprintf(ofhead,"\n\r%s\t",string);
fprintf(ofhead,"4\t");
fprintf(ofhead,"3\t");
fprintf(ofhead,"%d\t\n\r",q);
q++;
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}
}
if(text[i]=='\''){ /*考慮可能出現的一'開頭的字元類型常量*/
string[0]=text[i];
while(text[i]!='\''){
string[j]=text[i];
i++;j++;
}
string[j]=text[i];
if(search(zfclbhead,string)){ /*返回原表查詢,防止重復出現*/
fprintf(zfclbhead,"\n\r%c\t",text[i]);
fprintf(zfclbhead,"%s",b);
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}
else{
fprintf(zfclbhead,"\n\r%c\t",text[i]);
fprintf(zfclbhead,"4\t");
fprintf(zfclbhead,"4\t");
fprintf(zfclbhead,"%d\t\n\r",p);
fprintf(ofhead,"\n\r%c\t",text[i]);
fprintf(ofhead,"4\t");
fprintf(ofhead,"4\t");
fprintf(ofhead,"%d\t\n\r",p);
p++;
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}
}
if(text[i]=='#'){
i++;
while((text[i]>='a'&&text[i]<='z')||(text[i]>='A'&&text[i]<='Z')){
string[j]=text[i];
j++;i++;
}
if(strcmp(string,"include")==0){ /*括入文件處理程序段*/
if(text[i]=='\"'||text[i]=='<')i++;
while((text[i]>='a'&&text[i]<='z')||(text[i]>='A'&&text[i]<='Z'||text[i]=='.')){
kuoru[x]=text[i];
i++;x++;
}
if((krhead=fopen(kuoru,"r"))==NULL){
printf("不能建立目標文件!");
exit(0);
}
while(!(feof(krhead)))
text2[y++]=fgetc(krhead);
text2[y]='\0';
y=0;
temp=i;
for(j=0;j<30;j++)
string[j]='\0';
j=0;
saomiao(text2);
i=temp;
for(x=0;x<30;x++)
kuoru[x]='\0';
x=0;
i++;
}
if(strcmp(string,"define")==0){
for(j=0;j<30;j++)
string[j]='\0';
j=0;
while(!(text[i]>='a'&&text[i]<='z')||(text[i]>='A'&&text[i]<='Z'))i++;
while((text[i]>='a'&&text[i]<='z')||(text[i]>='A'&&text[i]<='Z')||text[i]=='_'||(text[i]>='0'&&text[i]<='9')){
hm[k1][k2]=text[i];
i++;k2++;
}
k2=0;
while(!(text[i]>='0')&&(text[i]<='9'))i++;
while((text[i]>='0')&&(text[i]<='9')||text[i]=='.'||text[i]=='e'||text[i]=='E'||text[i]=='-'){
hz[k1][k2]=text[i];
i++;k2++;
}
k1++;
k2=0;
}
}else{
if(search(fgfhead,string));
else{
fprintf(fgfhead,"\n\r%c\t",text[i]);
fprintf(fgfhead,"1\t");
fprintf(fgfhead,"%d\t\n\r",bianma2(text[i]));
}
fprintf(ofhead,"\n\r%c\t",text[i]);
fprintf(ofhead,"1\t");
fprintf(ofhead,"%d\t\n\r",bianma2(text[i]));
i++;
}
}else if(find3(text[i])){ /*分析一運算符開頭的情況*/
while(find3(text[i])){
string[j]=text[i];
i++;j++; /*考慮到有多個字元組成的運算符,運算符的判斷使用字元串*/
}
if(strcmp(string,"/*")==0){
while(!(text[i-1]=='*'&&text[i]=='/'))i++; /*去掉注釋*/
if(text[i]=='/')i++;
}
if(strcmp(string,"//")==0)
while(!(text[i]=='\n'))
i++; /*去掉注釋*/
if((bianma3(string)==-1)&&text[i-1]=='-'){
i=i-1;
for(j=0;j<30;j++)
string[j]='\0';
j=0;
clnmb(text); /*處理負數的情況*/
}
if(search(ysfhead,string));
else{
if(bianma3(string)!=-1){
fprintf(ysfhead,"\n\r%s\t",string);
fprintf(ysfhead,"2\t");
fprintf(ysfhead,"%d\t\n\r",bianma3(string));
}
}
if(bianma3(string)!=-1){
fprintf(ofhead,"\n\r%s\t",string);
fprintf(ofhead,"2\t");
fprintf(ofhead,"%d\t\n\r",bianma3(string));
}
for(j=0;j<30;j++)
string[j]='\0';
j=0;
}else i++;
}
}
int main(){
printf("********************\nc語言分析程序\n********************\n");
printf("\n請輸入文件名:");
scanf("%s",fn);
if((sfhead=fopen(fn,"r"))==NULL){
printf("不能打開源文件!\n");
exit(0);
}
if((ofhead=fopen("分解源文件所得文件.txt","wb+"))==NULL){
printf("不能建立目標文件!");
exit(0);
}
if((bsfhead=fopen("標識符表.txt","wb+"))==NULL){
printf("不能建立目標文件!");
exit(0);
}
if((zsclbhead=fopen("整數常量表.txt","wb+"))==NULL){
printf("不能建立目標文件!");
exit(0);
}
if((fdsclbhead=fopen("浮點數常量表.txt","wb+"))==NULL){
printf("不能建立目標文件!");
exit(0);
}
if((zfclbhead=fopen("字元常量表.txt","wb+"))==NULL){
printf("不能建立目標文件!");
exit(0);
}
if((zfcclbhead=fopen("字元串常量表.txt","wb+"))==NULL){
printf("不能建立目標文件!");
exit(0);
}
if((fgfhead=fopen("分隔符表.txt","wb+"))==NULL){
printf("不能建立目標文件!");
exit(0);
}
if((ysfhead=fopen("運算符表.txt","wb+"))==NULL){
printf("不能建立目標文件!");
exit(0);
}
if((blzhead=fopen("保留字表.txt","wb+"))==NULL){
printf("不能建立目標文件!");
exit(0);
}
fprintf(ofhead,"單詞\t");
fprintf(ofhead,"類\t");
fprintf(ofhead,"編號\t地址\t\n\r");
fprintf(bsfhead,"單詞\t");
fprintf(bsfhead,"類\t");
fprintf(bsfhead,"編號\t地址\t\n\r");
fprintf(zsclbhead,"單詞\t");
fprintf(zsclbhead,"類\t");
fprintf(zsclbhead,"編號\t地址\t\n\r");
fprintf(zfclbhead,"單詞\t");
fprintf(zfclbhead,"類\t");
fprintf(zfclbhead,"編號\t地址\t\n\r");
fprintf(zfcclbhead,"單詞\t");
fprintf(zfcclbhead,"類\t");
fprintf(zfcclbhead,"編號\t地址\t\n\r");
fprintf(fdsclbhead,"單詞\t");
fprintf(fdsclbhead,"類\t");
fprintf(fdsclbhead,"編號\t地址\t\n\r");
fprintf(fgfhead,"單詞\t");
fprintf(fgfhead,"類\t");
fprintf(fgfhead,"編號\t地址\t\n\r");
fprintf(ysfhead,"單詞\t");
fprintf(ysfhead,"類\t");
fprintf(ysfhead,"編號\t地址\t\n\r");
fprintf(blzhead,"單詞\t");
fprintf(blzhead,"類\t");
fprintf(blzhead,"編號\t地址\t\n\r"); /*初始化所需要的文件*/
while(!feof(sfhead)) /*將原程序讀入字元數組便於後面分析*/
text1[i++]=fgetc(sfhead);
text1[i++]='\0';
i=0;
saomiao(text1);
if(key1!=key2)
printf("ERROR:前後大括弧個數不相等。\n");
if(key3!=key4)
printf("ERROR:前後中括弧個數不相等。\n");
if(key5!=key6)
printf("ERROR:前後小括弧個數不相等。\n");
while(z!=0){
printf("列印:\n1分析源文件所得文件\n2保留字表\n3分隔符表\n4運算符表\n5標識符表\n6整數類型常量表\n7浮點數類型常量表\n8字元類型常量表\n9字元串類型常量表\n\n0退出程序");
printf("\n\n請輸入:");
scanf("%d",&z);
switch(z){
case 1 :{printf("**********分析源文件所得文件**********\n");dayin(ofhead);break;}
case 2 :{printf("***************保留字表***************\n");dayin(blzhead);break;}
case 3 :{printf("***************分隔符表***************\n");dayin(fgfhead);break;}
case 4 :{printf("***************運算符表***************\n");dayin(ysfhead);break;}
case 5 :{printf("***************標識符表***************\n");dayin(bsfhead);break;}
case 6 :{printf("************整數類型常量表************\n");dayin(zsclbhead);break;}
case 7 :{printf("***********浮點數類型常量表***********\n");dayin(fdsclbhead);break;}
case 8 :{printf("************字元類型常量表************\n");dayin(zfclbhead);break;}
case 9 :{printf("***********字元串類型常量表***********\n");dayin(zfcclbhead);break;}
case 10 :exit(0);
}
}
fclose(ofhead);
fclose(sfhead);
fclose(bsfhead);
fclose(fgfhead);
fclose(ysfhead);
fclose(blzhead);
fclose(fdsclbhead);
fclose(zfclbhead);
fclose(zfcclbhead);
fclose(zsclbhead);
}

❸ 編譯原理課程設計-詞法分析器設計(C語言)

#include"stdio.h"/*定義I/O庫所用的某些宏和變數*/

#include"string.h"/*定義字元串庫函數*/

#include"conio.h"/*提供有關屏幕窗口操作函數*/

#include"ctype.h"/*分類函數*/

charprog[80]={''},

token[8];/*存放構成單詞符號的字元串*/

charch;

intsyn,/*存放單詞字元的種別碼*/

n,

sum,/*存放整數型單詞*/

m,p;/*p是緩沖區prog的指針,m是token的指針*/

char*rwtab[6]={"begin","if","then","while","do","end"};

voidscaner(){

m=0;

sum=0;

for(n=0;n<8;n++)

token[n]='';

ch=prog[p++];

while(ch=='')

ch=prog[p++];

if(isalpha(ch))/*ch為字母字元*/{

while(isalpha(ch)||isdigit(ch))/*ch為字母字元或者數字字元*/{

token[m++]=ch;

ch=prog[p++];}

token[m++]='';

ch=prog[p--];

syn=10;

for(n=0;n<6;n++)

if(strcmp(token,rwtab[n])==0)/*字元串的比較*/{

syn=n+1;

break;}}

else

if(isdigit(ch))/*ch是數字字元*/{

while(isdigit(ch))/*ch是數字字元*/{

sum=sum*10+ch-'0';

ch=prog[p++];}

ch=prog[p--];

syn=11;}

else

switch(ch){

case'<':m=0;token[m++]=ch;ch=prog[p++];

if(ch=='>'){

syn=21;

token[m++]=ch;}

elseif(ch=='='){

syn=22;

token[m++]=ch;}

else{

syn=20;

ch=prog[p--];}

break;

case'>':m=0;token[m++]=ch;ch=prog[p++];

if(ch=='='){

syn=24;

token[m++]=ch;}

else{

syn=23;

ch=prog[p--];}

break;

case':':m=0;token[m++]=ch;ch=prog[p++];

if(ch=='='){

syn=18;

token[m++]=ch;}

else{

syn=17;

ch=prog[p--];}

break;

case'+':syn=13;token[0]=ch;break;

case'-':syn=14;token[0]=ch;break;

case'*':syn=15;token[0]=ch;break;

case'/':syn=16;token[0]=ch;break;

case'=':syn=25;token[0]=ch;break;

case';':syn=26;token[0]=ch;break;

case'(':syn=27;token[0]=ch;break;

case')':syn=28;token[0]=ch;break;

case'#':syn=0;token[0]=ch;break;

default:syn=-1;}}

main()

{

printf(" Thesignificanceofthefigures: "

"1.figures1to6saidKeyword "

"2. "

"3.figures13to28saidOperators ");

p=0;

printf(" pleaseinputstring: ");

do{

ch=getchar();

prog[p++]=ch;

}while(ch!='#');

p=0;

do{

scaner();

switch(syn){

case11:printf("(%d,%d) ",syn,sum);break;

case-1:printf(" ERROR; ");break;

default:printf("(%d,%s) ",syn,token);

}

}while(syn!=0);

getch();

}

程序測試結果

對源程序beginx:=9:ifx>9thenx:=2*x+1/3;end#的源文件,經過詞法分析後輸出如下圖5-1所示:

具體的你在修改修改吧

❹ c語言詞法分析器

任務1:識別小型語言所有單詞的詞法分析程序設計
源程序設計語言 G[<程序>]
<程序>→<變數說明><BEGIN> <語句表> <END>.
<變數說明>→VAR<變數表>:<類型>;|<空>
<變數表>→<變數表>,<變數>|<變數>
<類型>→INTEGER
<語句表>→<語句> | <語句>;<語句表>
<語句>→<賦值語句>|<條件語句>|<WHILE語句>|<復合語句>
<賦值語句>→<變數>:=<算術表達式>
<條件語句>→IF<關系表達式>THEN<語句>ELSE<語句>
<WHILE語句>→WHILE<關系表達式>DO<語句>
<復合語句>→BEGIN<語句表>END
<算術表達式>→<項>|<算術表達式>+<項>|<算術表達式>-<項>
<項>→<因式>|<項>*<因式>|<項>/<因式>
<因式>→<變數>|<整數>|(<算術表達式>)
<關系表達式>→<算術表達式><關系符><算術表達式>
<變數>→<標識符>
<標識符>→<標識符><字母>|<標識符><數字>|<字母>
<整數>→0|<非零數字><泛整數>
<泛整數>→<數字>|<數字><泛整數>|ε
<關系符>→<|<=|==|>|>=|<>
<字母>
→A|B|C|D|E|F|G|H|I|J|K|L|M|N|O|P|Q|R|S|T|U|V|W|X|Y|Z
<非零數字>→1|2|3|4|5|6|7|8|9
<數字>→<非零數字>|0
<空>→
要求和提示:
詞法分析階段,可以打開任意位置和名稱的源文件進行詞法分析,可以進行非法字元和數字後邊跟字母的錯誤判斷,如果沒有錯誤則提示「詞法分析正確完成!」,並且可以選擇輸出token.txt(token文件)string.txt(符號表)兩個文件;
1.詞法分析程序的主要任務如下:
① 組織源程序的輸入,識別出源程序中的各個基本語法單位(也稱為單詞或語法符號),按規則轉換成二元式的形式;
② 刪除無用的空白字元、回車符、及其它非實質性符號;
③ 刪除註解行;
④ 為後面的語法和語義分析提供二元式鏈表;
單詞 編碼 單詞 編碼
標識符 1 < 15
正整數 2 <= 16
BEGIN 3 > 17
END 4 >= 18
IF 5 <> 19
THEN 6 == 20
ELSE 7 ; 21
WHILE 8 . 22
DO 9 := 23
INTEGER 10 , 24
+ 11 ( 25
- 12 ) 26
* 13
/ 14
1) 對標識符的長度控制在8個字元(包括8個)以內,超過的做截斷處理;
2) 數字不大於65535,否則報錯;
3) 能跳過源程序中的空白格:兩個單詞之間的任何空格,製表符,回車,換行都是白空格,除了用來分隔單詞以外,沒有意義;
4) 能跳過注釋:
a) 接連出現的/*到下一次接連出現的*/之間的任何文字都是注釋(多行);
b) 從某行接連出現的//到該行的結尾的任何文字都是注釋(單行)。
3.怎樣編寫詞法分析程序:
1) 預處理:把源文件一個字元一個字元的讀入詞法分析程序設置的輸入字元結構體數組中(輸入緩沖區),讀入過程要刪除注釋,刪除多餘的白空格;
2) 從源程序字元數組中獲得單詞, 編碼為二元式.:
二元式採用結構體數組存儲, 把單詞類型和詞元記錄下來。
分解單詞的方法:
1) Case多路轉換語句根據單詞的特點直接編寫;
2) 通過描述單詞的正規文法得到相應的有窮自動機,通過case多路轉換語句完成有窮自動機的處理流程。
3.編寫詞法分析程序要注意的問題:
1) 檢查詞法是否有錯誤
檢查是否有非法字元:如 @, &, !
檢查標志符和數字是否滿足限制條件
檢查注釋符號是否配對
2) 符分隔單詞
能夠區分兩個單詞的符號為界符
有些界符不是單詞:如白空格
有些界符僅僅用來分隔:如;
有些界符本身還是源程序不可缺少的單詞,如(, ), +, /, 等等
有些界符包含兩個字元:如<>, >=等等
3) 輸出詞法錯誤
如果有錯誤,需要報告詞法錯誤的原因。並且要能夠越過錯誤,分解下一個單詞,直到源程序結束。
4) 輸出的二元式流保存在二元式結構體數組中。

❺ 編制C語言子集的詞法分析程序

#include <iostream>

#include <string>

using namespace std;

string key[6] = {"begin", "if", "then", "while", "do", "end"};

//關鍵字

bool isKey( string str, int &syn) //判斷是否為關鍵字,若是傳回相

應關鍵碼的種別名

{

int i;

for(i=0; i<6; i++)

{

if(str == key[i])

{

syn = i + 1;

return true;

}

}

return false;

}

bool isLetter(char c) //是否為字母

{

if((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))

return true;

else

return false;

}

bool isDigit(char c) //是否為數字

{

if(c >= '0' && c <= '9')

return true;

else

return false;

}

void analyse(FILE *fileP)

{

int n;

char c;

string str = "";

while((c = fgetc(fileP)) != EOF)

{

if(c == ' ' || c == '\n' || c == '\t')

continue;

else if(isDigit(c)) //數字

{

while(isDigit(c))

{

str += c;

c = fgetc(fileP);

}

fseek(fileP, -1, SEEK_CUR);

cout << "(11, " << str << ")" << endl;

str = "";

}

else if(isLetter(c)) //字母開頭的

{

while(isDigit(c) || isLetter(c))

{

str += c;

c = fgetc(fileP);

}

fseek(fileP, -1, SEEK_CUR);

if(isKey(str, n))

cout << "(" << n << ", " << str << ")" << endl; //關鍵碼

else

cout << "(10, " << "\'"<< str << "\'" << ")" << endl; //標志符

str = "";

}

else //操作符等

{

switch(c)

{

case '+':

cout << "(13, +)" << endl;

break;

case '-':

cout << "(14, -)" << endl;

break;

case '*':

cout << "(15, *)" << endl;

break;

case '/':

cout << "(16, /)" << endl;

break;

case ':':

{

if(c=fgetc(fileP) == '=')

cout << "(18, :=)" << endl;

else

{

cout << "(17, :)" << endl;

fseek(fileP, -1, SEEK_CUR);

}

break;

}

case '<':

{

c=fgetc(fileP);

if(c == '=')

cout << "(22, <=)" << endl;

else if(c == '>')

cout << "(21, <>)" << endl;

else

{

cout << "(20, <)" << endl;

fseek(fileP, -1, SEEK_CUR);

}

break;

}

case '>':

{

c=fgetc(fileP);

if(c == '=')

cout << "(24, >=)" << endl;

else

{

cout << "(23, >)" << endl;

fseek(fileP, -1, SEEK_CUR);

}

break;

}

case '=':

cout << "(25, =)" << endl;

break;

case ';':

cout << "(26, ;)" << endl;

break;

case '(':

cout << "(27, ()" << endl;

break;

case ')':

cout << "(28, ))" << endl;

break;

case '#':

cout << "(0, #)" << endl;

break;

}

}

}

}

int main()

{

FILE *fileP;

fileP = fopen("test.txt", "r");

cout << "------詞法分析如下------" << endl;

analyse(fileP);

return 0;

}

❻ c語言詞法分析實驗

你劃亮火柴,它的火焰讓你眼花繚亂
句子可能會走投無路,
請翻它背上的皮囊
幾乎遮沒花園里的小徑。
陌生人,我喜歡你
才是他們該是的胸懷哈哈

❼ 怎麼用c語言編一個詞法分析器

簡而言之就是先畫一個狀態圖,然後根據圖來編碼就行
一個簡單的xml的詞法分析器供參考
#include
<stdio.h>
#include
<stdlib.h>
#include
<string.h>
typedef
struct
{
char
*p;
int
len;
}
xml_Text;
typedef
enum
{
xml_tt_U,
/*
Unknow
*/
xml_tt_H,
/*
Head
<?xxx?>*/
xml_tt_E,
/*
End
</xxx>
*/
xml_tt_B,
/*
Begin
<xxx>
*/
xml_tt_BE,
/*
Begin
End
<xxx/>
*/
xml_tt_T
/*
Text
xxx
*/
}
xml_TokenType;
typedef
struct
{
xml_Text
text;
xml_TokenType
type;
}
xml_Token;
int
xml_initText(xml_Text
*pText,
char
*s)
{
pText->p
=
s;
pText->len
=
strlen(s);
return
0;
}
int
xml_initToken(xml_Token
*pToken,
xml_Text
*pText)
{
pToken->text.p
=
pText->p;
pToken->text.len
=
0;
pToken->type
=
xml_tt_U;
return
0;
}
int
xml_print(xml_Text
*pText)
{
int
i;
for
(i
=
0;
i
<
pText->len;
i++)
{
putchar(pText->p[i]);
}
return
0;
}
int
xml_println(xml_Text
*pText)
{
xml_print(pText);
putchar('\n');
return
0;
}
int
xml_getToken(xml_Text
*pText,
xml_Token
*pToken)
{
char
*start
=
pToken->text.p
+
pToken->text.len;
char
*p
=
start;
char
*end
=
pText->p
+
pText->len;
int
state
=
0;
pToken->text.p
=
p;
pToken->type
=
xml_tt_U;
for
(;
p
<
end;
p++)
{
switch(state)
{
case
0:
switch(*p)
{
case
'<':
state
=
1;
break;
default:
state
=
7;
break;
}
break;
case
1:
switch(*p)
{
case
'?':
state
=
2;
break;
case
'/':
state
=
4;
break;
default:
state
=
5;
break;
}
break;
case
2:
switch(*p)
{
case
'?':
state
=
3;
break;
default:
state
=
2;
break;
}
break;
case
3:
switch(*p)
{
case
'>':
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_H;
return
1;
default:
state
=
-1;
break;
}
break;
case
4:
switch(*p)
{
case
'>':
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_E;
return
1;
default:
state
=
4;
break;
}
break;
case
5:
switch(*p)
{
case
'>':
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_B;
return
1;
case
'/':
state
=
6;
break;
default:
state
=
5;
break;
}
break;
case
6:
switch(*p)
{
case
'>':
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_BE;
return
1;
default:
state
=
-1;
break;
}
break;
case
7:
switch(*p)
{
case
'<':
p--;
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_T;
return
1;
default:
state
=
7;
break;
}
break;
default:
pToken->text.len
=
p
-
start
+
1;
pToken->type
=
xml_tt_T;
return
1;
}
}
return
0;
}
int
main()
{
int
ret
=
0;
xml_Text
xml;
xml_initText(&xml,
"<?xml?><root>
ss
<haha>hoho</haha></root>");
xml_Token
token;
xml_initToken(&token,
&xml);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
ret
=
xml_getToken(&xml,
&token);
printf("ret=%d;text=",ret);
xml_print(&token.text);
printf(";type=%d;\n\n",
token.type);
return
0;
}

❽ c語言寫的一個詞法分析程序,識別標識符的,但是好像邏輯有問題,自己不知道怎麼改,求大神指點

#include<stdio.h>
#include<ctype.h>
#include<string.h>
#include<stdbool.h>//C99支持bool類型
intmain(void)
{
charstr[]="wordptr_239";
intt;
inti;
t=strlen(str);
boolok=true;//添加標識符,默認合法
for(i=0;i<t;i++)
{
if(!isdigit(str[0]))
{
if(str[i]>='a'&&str[i]<='z'||str[i]>='A'&&str[i]<='Z'||str[i]>='0'&&str[i]<='9'||str[i]=='_')
{
printf("%c",str[i]);
while(str[i]=='#')
{
break;
}
}
else
{
printf("非法");
ok=false;
}
}
else
{
printf("非法");
ok=false;
}
}
if(ok)printf("正確");
return0;
}

給你優化了以下,

錯誤原因如下:

printf("%c",str[i]);//字元列印用%c不是%s