词法分析程序
1.词法分析程序的功能:
词法分析程序的主要功能是从字符流的程序中识别单词,他主要从左至右逐个字符地扫描源程序,因此他还可以完成其他任务。比如,滤掉源程序中的注释和空白(由空格/控制符或回车换行字符引起的空白);又如,为了使编译程序能将发现的错误信息与源程序的出错位置联系起来,词法分析程序负责记录新读入的字符行的行号,以便行号与出错信息相关联;再如,在支持宏处理功能的源程序中,可以由词法分析程序完成其预处理等。
2.符号与种别码对照表:
单词符号 |
种别码 |
单词符号 |
种别码 |
单词符号 |
种别码 |
auto |
1 |
short |
21 |
<= |
41 |
break |
2 |
signed |
22 |
>= |
42 |
case |
3 |
sizeof |
23 |
== |
43 |
char |
4 |
static |
24 |
:= |
44 |
const |
5 |
struct |
25 |
<> |
45 |
continue |
6 |
switch |
26 |
< |
46 |
default |
7 |
typedef |
27 |
=> |
47 |
do |
8 |
union |
28 |
= |
48 |
double |
9 |
unsigned |
29 |
: |
49 |
else |
10 |
void |
33 |
+ |
50 |
enum |
11 |
include |
34 |
- |
51 |
extern |
12 |
stdio |
35 |
* |
52 |
float |
13 |
string |
36 |
/ |
53 |
for |
14 |
main |
37 |
( |
54 |
goto |
15 |
stdlib |
38 |
) |
55 |
if |
16 |
d(number) |
40 |
{ |
56 |
int 17 |
17 |
l(qita) |
100 |
} |
57 |
long |
18 |
|
|
; |
58 |
register |
19 |
|
|
. |
59 |
return |
20 |
|
|
|
|
3.用文法描述词法规则:
- <字母> →l
- <数字> →d
- <整数常数> →d|d<整数常数>
- <标识符> →l|l〈字母数字〉
- <关键字>→l|l〈字母数字〉
- <运算符> →+|-|*|/|=|〈〈等号〉|〉〈等号〉……
- <界符> →,|;|(|)|……
其中l表示a~z中的任一英文字母,d表示0~9中的任一数字。
4.已完成的代码:
#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 A[10000];//输入的所有值
int syn,row;
int n,m,p,sum,j;
static int i = 0;
void scaner();
int main()
{
row = 0 ;
p = 0 ;
printf("符号与种别码对照表如下:\n");
printf(" 单词符号 种别码 单词符号 种别码\n");
printf(" auto 1 return 20\n");
printf(" break 2 short 21\n");
printf(" case 3 signed 22\n");
printf(" char 4 sizeof 23\n");
printf(" const 5 static 24\n");
printf(" continue 6 struct 25\n");
printf(" default 7 switch 26\n");
printf(" do 8 typedef 27\n");
printf(" double 9 union 28\n");
printf(" else 10 unsigned 29\n");
printf(" enum 11 void 30\n");
printf(" extern 12 volatile 31\n");
printf(" float 13 while 32\n");
printf(" for 14 end 33\n");
printf(" goto 15 include 34\n");
printf(" if 16 stdio 35\n");
printf(" int 17 string 36\n");
printf(" long 18 main 37\n");
printf(" register 19 @ 0\n\n");
printf("\n 其他均为100。\n\n");
printf(" 请输入您想转换的语句:(输入@结束)\n");
do{
scanf("%c",&ch);
A[p]=ch;
p++;
}while(ch!='@');/*将输入的语句分别存入数组A[]中,@出现时结束语句*/
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()/*分别对标示符、数字、符号进行分析*/
{
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';/*将识别出来的字符和已定义的标示符作比较,输出其种别码*/
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(TOken,r8)==0){syn=8;}
else if(strcmp(TOken,r9)==0){syn=9;}
else if(strcmp(TOken,r10)==0){syn=10;}
else if(strcmp(TOken,r11)==0){syn=11;}
else if(strcmp(TOken,r12)==0){syn=12;}
else if(strcmp(TOken,r13)==0){syn=13;}
else if(strcmp(TOken,r14)==0){syn=14;}
else if(strcmp(TOken,r15)==0){syn=15;}
else if(strcmp(TOken,r16)==0){syn=16;}
else if(strcmp(TOken,r17)==0){syn=17;}
else if(strcmp(TOken,r18)==0){syn=18;}
else if(strcmp(TOken,r19)==0){syn=19;}
else if(strcmp(TOken,r20)==0){syn=20;}
else if(strcmp(TOken,r21)==0){syn=21;}
else if(strcmp(TOken,r22)==0){syn=22;}
else if(strcmp(TOken,r23)==0){syn=23;}
else if(strcmp(TOken,r24)==0){syn=24;}
else if(strcmp(TOken,r25)==0){syn=25;}
else if(strcmp(TOken,r26)==0){syn=26;}
else if(strcmp(TOken,r27)==0){syn=27;}
else if(strcmp(TOken,r28)==0){syn=28;}
else if(strcmp(TOken,r29)==0){syn=29;}
else if(strcmp(TOken,r30)==0){syn=30;}
else if(strcmp(TOken,r31)==0){syn=31;}
else if(strcmp(TOken,r32)==0){syn=32;}
else if(strcmp(TOken,r33)==0){syn=33;}
else if(strcmp(TOken,r34)==0){syn=34;}
else if(strcmp(TOken,r35)==0){syn=35;}
else if(strcmp(TOken,r36)==0){syn=36;}
else if(strcmp(TOken,r37)==0){syn=37;}
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=59;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;
default: syn=-1;break;
}
}