詞法分析以及文法描述詞法規則的己見


一.詞法分析程序的功能。

    詞法分析程序完成的事編譯第一階段的工作。詞法分析工作可以使獨立的一遍,把字符流的源程序變成單詞序列,輸出到一個中間文件,這個文件作為語法分析程序的惡輸入而繼續的編譯過程。對字符串表示的源程序從左到右進行掃描和分解根據詞法規則,識別出一個一個具有獨立意義的單詞符號以供語法分析之用。發現詞法錯誤則返回出錯信息。

 

二。符號與種別碼的對照表以及源程序。

      我所做的詞法分析程序和大多數程序差不多,也有着很多的不足,我將需要進行翻譯的各種單詞符號的對應的種別碼分成了若干個數組,並且在后期的修改中將老師的種別表進行了擴充,具體的功能是:輸入需要翻譯的東西作為字符串存儲在A[][]的數組中,用字符ch來存儲一個個的字符,在一次的循環中翻譯出一個個種別類並將其用(,)來顯示出來,一次循環,用數組TOKEN[]存儲,進行下一次循環的同時清除里面的數據,方便進行下一次的翻譯與存儲。大致是如此。

     源代碼如下:

  

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
char TOken[10];//分開進行比較
char ch;
/*char rwtab[6]={"begin","if","then","while","do","end"};*/
char r1[]={"auto"};
char r2[]={"break"};
char r3[]={"case"};
char r4[]={"char"};
char r5[]={"const"};
char r6[]={"continue"};
char r7[]={"default"};
char r8[]={"do"};
char r9[]={"double"};
char r10[]={"else"};
char r11[]={"enum"};
char r12[]={"extern"};
char r13[]={"float"};
char r14[]={"for"};
char r15[]={"goto"};
char r16[]={"if"};
char r17[]={"int"};
char r18[]={"long"};
char r19[]={"register"};
char r20[]={"return"};
char r21[]={"short"};
char r22[]={"signed"};
char r23[]={"sizeof"};
char r24[]={"static"};
char r25[]={"struct"};
char r26[]={"switch"};
char r27[]={"typedef"};
char r28[]={"union"};
char r29[]={"unsigned"};
char r30[]={"void"};
char r31[]={"volatile"};
char r32[]={"while"};
char r33[]={"end"};
char r34[]={"include"};
char r35[]={"stdio"};
char r36[]={"string"};
char r37[]={"main"};
char r38[]={"stdlib"};//這是我定義的
char A[10000];//輸入的所有值
int syn,row;
int n,m,p,sum,j;
static int i = 0;
void scaner();
int main()
{
row = 0 ;
p = 0 ;
printf("Please input string:(end of '@')\n");
do
{
scanf("%c",&ch);
A[p]=ch;
p++;
}//輸入值到數組A【】中,以@結束
while(ch!='@');
do
{
scaner();//進入函數進行判定
switch(syn)
{
case 40: printf("(%d,%d)\n",syn,sum); break;//如果是40,那么就是數字
case 0: printf("(%d,%c)\n",syn,TOken[0]);break;//如果是0,那么是@ 結束
case -2: row=row++;break;
default: printf("(%d,%s)\n",syn,TOken);break;//否則,就是變量名、關鍵詞
}
}
while (syn!=0);
}
void scaner()
{
/*
共分為三大塊,分別是標示符、數字、符號,對應下面的 if else if 和 else


*/
for(n=0;n<7;n++)
TOken[n]=0;//每次循環完就清零
ch=A[i];
while(ch==' '||ch=='\n')//如果字符是空格或者回車,跳過
{
i++;
ch=A[i];
}
if((ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z')) //可能是標示符或者變量名
{
m=0;
while((ch>='0'&&ch<='9')||(ch>='a'&&ch<='z')||(ch>='A'&&ch<='Z'))//找到一個變量名或者關鍵字,直到遇到空格為止
{
TOken[m]=ch;m++;
i++;ch=A[i];
}
TOken[m]='\0';
//將識別出來的字符和已定義的標示符作比較, //因為定義的begin為1,if為2......
if(strcmp(TOken,r1)==0){syn=1;}
else if(strcmp(TOken,r2)==0){syn=2; }
else if(strcmp(TOken,r3)==0){syn=3;}
else if(strcmp(TOken,r4)==0){syn=4;}
else if(strcmp(TOken,r5)==0){syn=5;}
else if(strcmp(TOken,r6)==0){syn=6;}
else if(strcmp(TOken,r7)==0){syn=7;}
else if(strcmp(r8,TOken)==0){syn=8;}
else if(strcmp(r9,TOken)==0){syn=9;}
else if(strcmp(r10,TOken)==0){syn=10;}
else if(strcmp(r11,TOken)==0){syn=11;}
else if(strcmp(r12,TOken)==0){syn=12;}
else if(strcmp(r13,TOken)==0){syn=13;}
else if(strcmp(r14,TOken)==0){syn=14;}
else if(strcmp(r15,TOken)==0){syn=15;}
else if(strcmp(r16,TOken)==0){syn=16;}
else if(strcmp(r17,TOken)==0){syn=17;}
else if(strcmp(r18,TOken)==0){syn=18;}
else if(strcmp(r19,TOken)==0){syn=19;}
else if(strcmp(r20,TOken)==0){syn=20;}
else if(strcmp(r21,TOken)==0){syn=21;}
else if(strcmp(r22,TOken)==0){syn=22;}
else if(strcmp(r23,TOken)==0){syn=23;}
else if(strcmp(r24,TOken)==0){syn=24;}
else if(strcmp(r25,TOken)==0){syn=25;}
else if(strcmp(r26,TOken)==0){syn=26;}
else if(strcmp(r27,TOken)==0){syn=27;}
else if(strcmp(r28,TOken)==0){syn=28;}
else if(strcmp(r29,TOken)==0){syn=29;}
else if(strcmp(r30,TOken)==0){syn=30;}
else if(strcmp(r31,TOken)==0){syn=31;}
else if(strcmp(r32,TOken)==0){syn=32;}
else if(strcmp(r33,TOken)==0){syn=33;}
else if(strcmp(r34,TOken)==0){syn=34;}
else if(strcmp(r35,TOken)==0){syn=35;}
else if(strcmp(r36,TOken)==0){syn=36;}
else if(strcmp(r37,TOken)==0){syn=37;}
else if(strcmp(r38,TOken)==0){syn=38;}
else{syn=100;} //變量名
}
else if((ch>='0'&&ch<='9')) //數字
{
sum=0;
while((ch>='0'&&ch<='9'))
{
sum=sum*10+ch-'0';//顯示其數字sum
i++;
ch=A[i];
}
syn=40;
}
else switch(ch) //其他字符
{
case'<':m=0;TOken[m]=ch;m++;
i++;ch=A[i];
if(ch=='=')//<>為22
{
syn=41;
TOken[m]=ch;m++;i++;
}
else
{
syn=46;
}
break;
case'>':m=0;TOken[m]=ch;m++;
i++;ch=A[i];
if(ch=='=')
{
syn=42;
TOken[m]=ch;m++;i++;
}
else
{
syn=47;
}
break;
case':':m=0;TOken[m]=ch;m++;
i++;ch=A[i];
if(ch=='=')
{
syn=44;
TOken[m]=ch;m++;i++;
}
else
{
syn=49;
}
break;
case'@':syn=0;TOken[0]=ch;i++;break;
case'=':syn=48;TOken[0]=ch;i++;break;
case'#':syn=50;TOken[0]=ch;i++;break;
case'+':syn=50;TOken[0]=ch;i++;break;
case'-':syn=51;TOken[0]=ch;i++;break;
case'*':syn=52;TOken[0]=ch;i++;break;
case'/':syn=53;TOken[0]=ch;i++;break;
case'(':syn=54;TOken[0]=ch;i++;break;
case')':syn=55;TOken[0]=ch;i++;break;
case'{':syn=56;TOken[0]=ch;i++;break;
case'}':syn=57;TOken[0]=ch;i++;break;
case';':syn=58;TOken[0]=ch;i++;break;
case'.':syn=59;TOken[0]=ch;i++;break;
case'\'':syn=60;TOken[0]=ch;i++;break;
case'\n':syn=-2;break;
default: syn=-1;break;
}
}

/*這是我定義的種別類 符號:

@ 0 # 33
auto 1 
break 2 
case 3 
char 4 
const 5 
continue 6 
default 7 
do 8 
double 9 
else 10 
enum 11 
extern 12
float 13 
for 14 
goto 15 
if 16 
int 17 
long 18
register 19 
return 20
short 21
signed 22
sizeof 23
static 24
struct 25
switch 26
typedef 27
union 28
unsigned 29
void 30
volatile 31
while 32
end 33
include 34
stdio 35
string 36
main 37
stdlib 38
qita 100
number 40

#      33

<=     41

>=     42

==     43

:=     44

<>     45

<      46

>      47

 =      48

:      49

+  50

-  51

*  52 

/  53

(  54

)  55

{  56

}  57

;  58

.  59

*/

程序運行如下:

 

三 .用文法描述詞法規則。

    這個概念我不是太懂,但是也說說自己的理解和想法。

     首先是文法形式的定義:A-〉B ,A代表的是左部符號,‘-〉’意思是為生成,而B代表的是右部的符號串。

     有着終結符號:如0,1:1.組成語言的終止符。2.基本有小寫字母組成。

     文法(Vn,Vt,P,S)

   就比如說:A->a|b|e|Aa|Ae|Ao|A

                Vn = {A},

                 Vt ={a,b,c,d,e,0,1}

                P={A->a|b|e|Aa|Ae|Ao|A}

               S = A .

      其實A-〉Aa 就代表着循環的意思,每進行一次,就會增加一個a,假如A-〉Aaa,意思就是每循環一次,就增加aa,所以暫時也就是理解到了這個意思,然后通過幾道題來強化自己的理解。

      就好比Q={a,b},L={a^2n ,b^2n|n>=1}

     首先是看好n的取值范圍,然后看n具體指了多少個,那么就比如一起來進行循環,這個題a,b都有n,但是是分開的,所以不用一起進行。

     解題思路如下:

     1.增長的趨勢:a^2n,aa aaaa aaaaaa........

                        b^2n,bb bbbb bbbbbb.......

    2.循環規律:A->aa  A->Aaa

                     B->bb B->Bbb

    3.S->A|B

     A->aa|Aaa // 意思是aa為開頭,循環不斷增加aa

     B->bb|Bbb // 意思是bb為開頭,循環不斷增加bb

     大概就這樣。嗯

     可以做幾道典型題型來試一試。{ab^n a|n>=0} {a^m b^m|n>=1 m>=1}等等

 201506110166 黃仲浩


免責聲明!

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



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