实验项目:词法分析程序实验
实验的目的与任务
编译方法是计算机类专业特别是计算机软件专业的一门重要专业课。设置该课程的目的在于系统地向学生讲述编译系统的结构、工作流程及编译程序各组成部分的设计原理和实现方法,使学生通过学习既掌握编译理论和方法方面的基本知识,也具有设计、实现、分析和维护编译程序等方面的初步能力。编译原理是一门理论性和实践性都比较强的课程。进行上机实验的目的是使学生通过完成上机实验题目加深对课堂教学内容的理解。同时培养学生实际动手能力。
编译实验由三个既是独立又能最终组成一个系统的实验组成,按照由浅入深进行排列,希望通过本实验使学生更深学习并理解编译的主要过程和相关方法。
词法分析的目的是将输入的源程序进行划分,给出基本符号(token)的序列,并掠过注解和空格等分隔符号。基本符号是与输入的语言定义的词法所规定的终结符。
本实验要求学生编制一个读单词过程,从输入的源程序中,识别出各个具有独立意义的单词,即基本保留字、标识符、常数、运算符、分隔符五大类。并依次输出各个单词的内部编码及单词符号自身值。(遇到错误时可显示“Error”,然后跳过错误部分继续进行)
估计实验时间 8学时
1.课余准备;2.上机一次到二次,第一次编好程序,第二次修改完善,并尽量扩充程序的功能;3.完成实验报告2小时。
实验过程和指导
准备
确定并熟悉开发工具,如JAVA 、C、C++等;充分了解被处理的语言的语法特点(语言定义见下面)。写好实验报告,编好程序并测试。
上机
准备:确定并熟悉开发工具,如JAVA 、C、C++等;充分了解被处理的语言的语法特点(语言定义见下面)。写好实验报告,编好程序并测试。
源代码
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <malloc.h>
#include <conio.h>
FILE *fp;
char ch;
char *keyword[34]={"auto","break","case","char","const","continue","default","do","double",
"else","enum","extern","float","for","goto","if","int","long","register",
"return","short","signed","sizeof","static","struct","switch","typedef", "printf",
"union","unsigned","void","volatile","while","main"};
char *operatornum[6]={"+","-","*","/","++","--"};
char *comparison[7]={"<","<=",">",">=","<>","==","!="};
char *fuzhi = "=";
char *interpunction[8]={",",";",":=",".","(",")","{","}"};
char *biaoshifu[5]={"%","$","^","&","#"};//特殊标识符
char *zhushifu[3]={"//","/*","*/"};//注释符
char *luoji[3]={"&&","||","!"};//逻辑运算符
bool search(char searchstr[],int wordtype)//符号匹配
{
int i;
switch (wordtype)
{
case 1:
for(i=0;i<=33;i++)
{
if(strcmp(keyword[i],searchstr)==0)
return(true);
}
break;
case 2:
for(i=0;i<=5;i++)
{
if(strcmp(operatornum[i],searchstr)==0)
return(true);
}
break;
case 3:
for(i=0;i<=6;i++)
{
if(strcmp(comparison[i],searchstr)==0)
return(true);
}
break;
case 4:
for(i=0;i<=7;i++)
{
if(strcmp(interpunction[i],searchstr)==0)
return(true);
}
break;
case 5:
for(i=0;i<=4;i++)
{
if(strcmp(biaoshifu[i],searchstr)==0)
return(true);
}
break;
case 6:
for(i=0;i<=2;i++)
{
if(strcmp(zhushifu[i],searchstr)==0)
return(true);
}
break;
case 7:
for(i=0;i<=2;i++)
{
if(strcmp(luoji[i],searchstr)==0)
return(true);
}
break;
}
return false;
}
char letterprocess (char ch)//字母处理函数
{
int i=-1;
char letter[20];
while (isalnum(ch)!=0 || ch=='_' || ch=='[' || ch==']')
{
letter[++i]=ch;
ch=fgetc(fp);
}
letter[i+1]='\0';
if (search(letter,1))
printf("<%s,key>\n",letter);
else
printf("<%s,id>\n",letter);
return(ch);
}
char numberprocess(char ch)//数字处理程序
{
int i=-1;
char num[20];
int point = 0;
while (isdigit(ch)!=0 || ch=='.')
{
if(ch=='.')
point++;
num[++i]=ch;
ch=fgetc(fp);
}
if(isalpha(ch)!=0 || point>=2)//数字后面是字符或小数点
{
while(isdigit(ch)!=0 || isalnum(ch)!=0 || ch=='_' || ch=='.')
{
num[++i]=ch;
ch=fgetc(fp);
}
num[i+1]='\0';
if(point>=2)
printf("错误!非法num:%s\n",num);
else
printf("错误!非法id:%s\n",num);
goto u;
}
num[i+1]='\0';
printf("<%s,num>\n",num);
u: return(ch);
}
char otherprocess(char ch)//其他处理程序
{
int i=-1;
char other[20];
if (isspace(ch)!=0)
{
ch=fgetc(fp);
goto u;
}
while ((isspace(ch)==0)&&(isalnum(ch)==0))
{
other[++i]=ch;
ch=fgetc(fp);
}
other[i+1]='\0';
if (search(other,2))
printf("<%s,op>\n",other);
else if (search(other,3))
printf("<%s,relop>\n",other);
else if (search(other,4))
printf("<%s,界符>\n",other);
else if (search(other,5))
printf("<%s,special char>\n",other);
else if (search(other,6))
printf("<%s,note>\n",other);
else if (search(other,7))
printf("<%s,logop>\n",other);
else if (strcmp(other,fuzhi)==0)
printf("<%s,赋值>\n",other);
else
printf("错误!非法字符:%s\n",other);
u: return (ch);
}
int main ()
{
char str;
if ((fp=fopen("lexicalinput.txt","r"))==NULL)
printf("源程序无法打开!\n");
else
{
str = fgetc(fp);//从流中读取字符
int i = 0;
while (str!=EOF)
{
if (isalpha(str)!=0)//如果是字符 isalpha包含在#include <cctype>
{
str=letterprocess(str);
}
else
{
if (isdigit(str)!=0)
{
str=numberprocess(str);
}
else
{
str=otherprocess(str);
}
}
}
printf("词法分析结束,谢谢使用。");
}
fclose(fp);
return 0;
}