引言
光說不練,假把式。
此小節來做一個實驗,用c語言自己實現一個簡單的詞法分析器,來加深對詞法分析的理解。感興趣的就自己分析一下源碼吧,挺簡單的,就沒畫流程圖,請見諒。閒言少敘,我們開始吧。
4.1實驗描述
例如:對源程序:
begin x:=9: if x>9 then x:=2*x+1/3; end #
的源文件,經過詞法分析後輸出如下序列:
<1,begin><10,x><18,:=><11,9><26,;><2,if>……
4.1.1待分析的簡單的詞法
(1)關鍵字:
begin if then while do end
所有的關鍵字都是小寫。
(2)運算符和界符
: = + - * / < <= <> > >= = ; ( ) #
(3)其他單詞是標識符(ID)和整型常數(SUM),通過以下正規式定義:
ID = letter (letter | digit)*
NUM = digit digit*
(4)空格有空白、制表符和換行符組成。空格一般用來分隔ID、SUM、運算符、界符和關鍵字,詞法分析階段通常被忽略。
4.1.2 各種單詞符號對應的種別碼:
表4.2.1 各種單詞符號對應的種別碼
單詞符號
種別碼
單詞符號
種別碼
bgin
1
:
17
If
2
:=
18
Then
3
<
20
wile
4
<>
21
do
5
<=
22
end
6
>
23
lettet(letter|digit)*
10
>=
24
dight dight*
11
=
25
+
13
;
26
—
14
(
27
*
15
)
28
/
16
#
0
4.2實現源碼參考
[html]
#include <stdio.h>
#include <string.h>
char prog[80],token[8],ch;
int syn,p,m,n,sum;
char *rwtab[6]={"begin","if","then","while","do","end"};
void scaner(void);
main()
{
p=0;
printf("\n please input a string(end with '#'):\n");
do{
scanf("%c",&ch);
prog[p++]=ch;
}while(ch!='#');
p=0;
do{
scaner();
switch(syn)
{
case 11:
printf("( %-10d%5d )\n",sum,syn);
break;
case -1:
printf("you have input a wrong string\n");
//getch();
return 0;
break;
default:
printf("( %-10s%5d )\n",token,syn);
break;
}
}while(syn!=0);
//getch();
}
void scaner(void)
{
sum=0;
for(m=0;m<8;m++)
token[m++]= NULL;
ch=prog[p++];
m=0;
while((ch==' ')||(ch=='\n'))
ch=prog[p++];
if(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A')))
{
while(((ch<='z')&&(ch>='a'))||((ch<='Z')&&(ch>='A'))||((ch>='0')&&(ch<='9')))
{
token[m++]=ch;
ch=prog[p++];
}
p--;
syn=10;
for(n=0;n<6;n++)
if(strcmp(token,rwtab[n])==0)
{
syn=n+1;
break;
}
}
else if((ch>='0')&&(ch<='9'))
{
while((ch>='0')&&(ch<='9'))
{
sum=sum*10+ch-'0';
ch=prog[p++];
}
p--;
syn=11;
}
else
{
switch(ch)
{
case '<':
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=22;
token[m++]=ch;
}
else
{
syn=20;
p--;
}
break;
case '>':
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=24;
token[m++]=ch;
}
else
{
syn=23;
p--;
}
break;
case '+':
token[m++]=ch;
ch=prog[p++];
if(ch=='+')
{
syn=17;
token[m++]=ch;
}
else
{
syn=13;
p--;
}
break;
case '-':
token[m++]=ch;
ch=prog[p++];
if(ch=='-')
{
syn=29;
token[m++]=ch;
}
else
{
syn=14;
p--;
}
break;
case '!':
ch=prog[p++];
if(ch=='=')
{
syn=21;
token[m++]=ch;
}
else
{
syn=31;
p--;
}
break;
case '=':
token[m++]=ch;
ch=prog[p++];
if(ch=='=')
{
syn=25;
token[m++]=ch;
}
else
{
syn=18;
p--;
}
break;
case '*':
syn=15;
token[m++]=ch;
break;
case '/':
syn=16;
token[m++]=ch;
break;
case '(':
syn=27;
token[m++]=ch;
break;
case ')':
syn=28;
token[m++]=ch;
break;
case '{':
syn=5;
token[m++]=ch;
break;
case '}':
syn=6;
token[m++]=ch;
break;
case ';':
syn=26;
token[m++]=ch;
break;
case '\"':
syn=30;
token[m++]=ch;
break;
case '#':
syn=0;
token[m++]=ch;
break;
case ':':
syn=17;
token[m++]=ch;
break;
default:
syn=-1;
break;
}
}
token[m++]='\0';
}
4.3小結:
詞法分析,就是將程序源代碼序列,循環讀取一個字串,然後根據詞法要求,確定其屬性,然後組成詞法單元。對於現實中的編程語言,其詞法比較復雜,一般用正則表達式表示。