词法分析
要求:
编制一个读单词过程,源程序为一个文件,读取该文件,识别出各个具有独立意义的单词,并依次输出各个单词的内部编码及单词符号自身值。
单词的内部编码如下:
1、保留字:main、if、int、for、while、do、return、break、continue,单词种别码分别为1~9,输出的二元组形式为(单词种别码,0)
2、标识符:除保留字外的以字母开头,后跟字母、数字的字符序列,单词种别码为20,输出的二元组形式为(单词种别码,标识符的名字);
3、常数为无符号整型数;单词种别码为30,输出的二元组形式为(单词种别码,常数值);
4、运算符包括:+、-、*、/、=、>、<、>=、<=、==、!=;单词种别码为41~51,输出的二元组形式为(单词种别码,0);
5、分隔符包括:,、;、{、}、(、); 单词种别码为61~66,输出的二元组形式为(单词种别码,0)。
单词符号 | 种别码 | 单词符号 | 种别码 |
main | 1 | / | 44 |
int | 2 | = | 45 |
if | 3 | > | 46 |
for | 4 | < | 47 |
while | 5 | >= | 48 |
do | 6 | <= | 49 |
return | 7 | == | 50 |
break | 8 | != | 51 |
continue | 9 | , | 61 |
ID | 20 | ; | 62 |
NUM | 30 | { | 63 |
+ | 41 | } | 64 |
- | 42 | ( | 65 |
* | 43 | ) | 66 |
举例
源程序文件内容如下:
main()
{
int a, b;
a = 10;
b = a + 20;
}
要求输出如下:
(1,0)
(65,0)
(66,0)
(63,0)
(2,0)
source code:
#include <stdio.h>
#include<stdlib.h>
#include <ctype.h>
char a[10];//用于存储待识别的标识符或关键字
char *p=a;
void token_scan();
int qiseq(char *p,char *q);
typedef struct token
{
char *kind;
int value;
char *word;
}TOKEN;
TOKEN token[28]=
{
{"1",0,"main"},// main
{"2",0,"int"},// int
{"3",0,"if"},// if
{"4",0,"for"},// for
{"5",0,"while"},// while
{"6",0,"do"},// do
{"7",0,"return"},// return
{"8",0,"break"},// break
{"9",0,"continue"},// continue
{"20",0},//10 ID
{"30",0},//11 NUM
{"41",0,},//12 +
{"42",0,},//13 -
{"43",0,},//14 *
{"44",0,},//15 /
{"45",0,},//16 =
{"46",0,},//17 >
{"47",0,},//18 <
{"48",0,},//19 >=
{"49",0,},//20 <=
{"50",0,},//21 ==
{"51",0,},//22 !=
{"61",0,},//23 ,
{"62",0,},//24 ;
{"63",0,},//25 {
{"64",0,},//26 }
{"65",0,},//27 (
{"66",0,},//28 )
};
void main()
{
token_scan();
getchar();
}
int qiseq(char *p,char *q)
{
//u判断两字符串的内容是否相等,若相等返回1,不等返回0
while(*(p++)!='/0'&&*(q++)!='/0')
{
if(*p==*q) continue;
else
return 0;
}
if(*p!='/0'||*q!='/0')
return 0;
else
return 1;
}
void token_scan()
{
//模拟词法分析程序,每次读入一个单词,返回(单词种别,属性值)
FILE *fp;
char ch;
int i=0;
int j=0;
fp=fopen("file.txt","r");
if (fp==NULL)
{ printf("cannot open file/n");exit(0);}
ch=fgetc(fp);
while(ch!=EOF)
{
if(isalpha(ch))
{ i=0;
a[i++]=ch;
ch=fgetc(fp);
while(isalnum(ch)||isalpha(ch))
{ a[i++]=ch;ch=fgetc(fp);}
p=a;
for(i=0;i<8;i++)
{
if(qiseq(p,token[i].word))
{
printf("(%s,0)/n",token[i].kind);
goto loop;
}
}
printf("(20,/"%s/")/n",a);
loop:
j=0;
while(a[j]!='/0')
a[j++]='/0';
}
else if(isdigit(ch))
{ i=0;
while(isdigit(ch))
{
if(isdigit(ch))
{
a[i++]=ch;ch=fgetc(fp);}
else break;
}
printf("(30,%s)/n",a);
j=0;
while(a[j]!='/0')
a[j++]='/0';
}
else
switch(ch)
{
case '=':
ch=fgetc(fp);
if(ch=='=')
{
printf("(%s,%d)/n",token[20].kind,token[20].value);
ch=fgetc(fp);
}
else
printf("(%s,%d)/n",token[15].kind,token[15].value);
//ch=fgetc(fp);
break;
case '+':
ch=fgetc(fp);
printf("(%s,%d)/n",token[11].kind,token[11].value);
//ch=fgetc(fp);
break;
case '-':
ch=fgetc(fp);
printf("(%s,%d)/n",token[12].kind,token[12].value);
//ch=fgetc(fp);
break;
case '(':
ch=fgetc(fp);
printf("(%s,%d)/n",token[26].kind,token[26].value);
//ch=fgetc(fp);
break;
case ')':
ch=fgetc(fp);
printf("(%s,%d)/n",token[27].kind,token[27].value);
//ch=fgetc(fp);
break;
case ',':
ch=fgetc(fp);
printf("(%s,%d)/n",token[22].kind,token[22].value);
//ch=fgetc(fp);
break;
case ';':
ch=fgetc(fp);
printf("(%s,%d)/n",token[23].kind,token[23].value);
//ch=fgetc(fp);
break;
case '{':
ch=fgetc(fp);
printf("(%s,%d)/n",token[24].kind,token[24].value);
//ch=fgetc(fp);
break;
case '}':
ch=fgetc(fp);
printf("(%s,%d)/n",token[25].kind,token[25].value);
//ch=fgetc(fp);
break;
default:
ch=fgetc(fp);
}
}
}