蚃专业课程设计II
膂题 目:
芆专 | 业 |
肇学生姓名 |
罿指导教师
薈指导单位
蒆日 | 期 |
|
|
1
膄词法分析程序的构造
一、
二、羀课题内容和要求
蚇基本功能:通过状态转换图构造C或者PASCAL 语言子集的词法分析程序。例如选取了C语言,选取其中一个子集,例如包含了部分关键字main、float、if、for等等,特殊符号(、<、=、+等等,特殊定义的标识符变量以及部分常量等,采用《编译原理》词法分析中有穷自动机的思想构建出该语言子集的状态转换图,并编码实现。要求将选取的语言子集编写一个简单程序,放在一个文本文件中;要将一个个单词区分清楚并归类(例如for属于关键字),词法分析程序作一遍扫描,采用双缓冲区结构。并且如vc将关键字着色以加以识别。
袅二、概要设计 (1)
(2) 袄状态装换图
(3)
(4) 肂功能模块
聿核心代码:
芅1)、数据类型定义:
2
薅extern struct table
衿{
膇 int id;
螄 char code[10];
肁};
//保留字(关键字)和各自的编码
羀struct table key[100] = {{100,"main"},{101,"int"},{102,"char"},{103,"if"},
膄int a=200; //自定义变量编码
袂int b=300; //数字编码
羂int d=400; //运算符编码
蚈int e=500; //分隔符编码
袇int f=600; //关系运算符编码
3
薂2)、函数调用
蝿void scanner(FILE *fp)
螇int reserve(char* p)
//读取文件内容,并加以识别判断
//识别判断是否为关键字函数
芆void output(int t,char *s) //输出函数
莂3)、状态判断
袁void scanner(FILE *fp)
蚆 if(isalpha(ch)) //如果是字母
肃 {
袂 token[0]=ch;
芇 i=1;
膅 ch=fgetc(fp);
4
螃 while(isalpha(ch)||isalnum(ch)) //循环接受字母
虿 {
蚀 token[i]=ch; //放入数组中
薄 i++;
薃 ch=fgetc(fp);
螁 }
羄 token[i]='\0';
芄 c=reserve(token); //判断是否为关键字
螂 if(c!=-1){
袆 output(c,token);
蚇 }
5
肄 else
蕿 output(a++,token);
艿 }
肇 else
螅 if(isdigit(ch)) //如果是数字
蚁 {
薆 ch=fgetc(fp);
芁 i=1;
螂 while(isdigit(ch))//循环接受
螀 {
羅 token[i]=ch;
6
羁 i++;
葿 ch=fgetc(fp);
袈 }
莅 token[i]='\0';
螂 fseek(fp,-1,1);
薁 output(b++,token);
螄 else
蒂 switch(ch) //判断是否为符号
蚂 {
荿 case'(':output(e++,"(");break; //是否为(,是则输出
芃 case')':output(e++,")");break; //是否为),是则输出
7
节 case'[':output(e++,"[");break; //是否为[,是则输出
蒀 case']':output(e++,"]");break; //是否为],是则输出
蒇 case'{':output(e++,"{");break; //是否为{,是则输出
羇 case'}':output(e++,"}");break; //是否为},是则输出
羃 case',':output(e++,",");break; //是否为,,是则输出
蒁 case':':output(e++,":");break; //是否为:,是则输出
莆 case'"':output(e++,"\"");break; //是否为\,是则输出
螃 case'+':ch=fgetc(fp);//是否为+,是则往前搜索一个字符
芈 if(!feof(fp)) //判断是否到文件末尾
羈 {
螆 if(ch=='+') //如果下一个字符是+,则输出++
8
蒄 output(f++,"++");
莀 else //不是则文件指针回退一个,输出+
肆 {
芅 fseek(fp,0,1);
膄 output(f++,"+");
莁 }
蚄 else output(f++,"+");
羄 break;
膈 case'-':ch=fgetc(fp); //是否为-,是则往前搜索一个字符
薇 if(!feof(fp))
肄 {
9
蚅 if(ch=='-')
芀 output(f++,"--");
衿 else
螇 {
膁 fseek(fp,0,1);
莁 output(f++,"-");
膆 }
羁 else output(f++,"-");
聿 break;
膆 case'*':output(d++,"*");break;
蚆 case'/':output(d++,"/");break;
10
蚂 case'>':ch=fgetc(fp);//是否为>,是则往前搜索一个字符
膀 if(!feof(fp))
蒈 {
肅 if(ch=='=')
莂 output(f++,">=");
芁 else
蒅 fseek(fp,0,1);
膃 output(f++,">");
聿 }
罿 }
袄 else output(f++,">");
11
袃 break;
肀 case'<': ch=fgetc(fp); //是否为<,是则往前搜索一个字符
肈 if(!feof(fp))
薇 {
蚃 if(ch=='=')
膂 output(f++,"<=");
肇 {
莄 fseek(fp,-1,1);
罿 output(f++,"<");
薈 }
蒆 }
12
膄 else{
羀 fseek(fp,0,1);
蚇 output(f++,"<");}
袅 break;
袄 case'=':ch=fgetc(fp);//是否为=,是则往前搜索一个字符
肂 if(feof(fp)){
芅 output(f++,"=");}
薅 else
衿 {
膇 if(ch=='=')
螄 output(f++,"==");
13
肁 else
羀 {
芆 fseek(fp,-1,1);
膄 output(f++,"=");
袂 }
羂 }
袇 case'!':ch=fgetc(fp); //是否为!,是则往前搜索一个字
符
薂 if(!feof(fp))
蝿 {
螇 if(ch=='=')
芆 | output(f++,"!="); |
|
14
莂 else
袁 {
腿 fseek(fp,0,1);
蚆 output(f++,"!");
肃 }
袂 }
膅 break;
螃 }
虿 }
蚀三、详细设计(格式:宋体,4号,加粗,两端对齐)
15
薄 源代码:
薃 ********************************extre.h*********************************
螁externstruct table
螈{
羄 intid;
芄 charcode[10];
螂}; | |
蚇{104,"else"},{105,"for"},{106,"while"},{107,"ERROR"}};
肄intreserve(char* p)
蕿{
艿 inti=0;
肇 for(i=0;i<8;i++)
16
螅 {
蚁 if(strcmp(p,key[i].code)==0)
莇 return(key[i].id);
薆 }
芁 return(-1);
螂}
螀void output(int t,char *s)
羅{
羁 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
葿 if(100<=t&&t<=107){
袈 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),FOREGROUND_GREEN);
莅 printf("%-2d %-6s",t,s);
17
螂 printf(" 关键字\n");
薁 SetConsoleTextAttribute(GetStdHandle(STD_OUTPUT_HANDLE),15);
羆 }
螄 else printf("%-2d %-6s ",t,s);
蒂 switch(t/100){
蚂 荿 芃 节 蒀 | case 2:printf(" | 变量 \n");break; |
case 3:printf(" | 数字 \n");break; | |
| ||
case 5:printf(" | 分隔符 \n");break; | |
case 6:printf(" | 关系运算符 \n");break; | |
蒇 }
羇}
羃*****************************************guwen.cpp***********************************
18
蒁#include<stdio.h>
衿#include<string.h>
莆#include<windows.h>
螃#include<ctype.h>
芈#include"extre.h"
羈extern int reserve(char*);
螆extern void output(int,char*);
蒄chartoken[20];
莀charch;
肆inti,c;
芅int a=200; | //变量 |
|
膄int b=300; | //数字 |
19
莁intd=400; //运算符
葿inte=500; //分隔符
蚄intf=600; //关系运算符
羄voidscanner(FILE *fp)
膈{
薇 肄 蚅 芀 衿 螇 膁 | if(isalpha(ch)) | //如果是字母 |
{ |
| |
i=1; | ||
莁 | token[i]=ch; | //放入数组中 |
|
20
肈 | } | i++; | |
膆 | ch=fgetc(fp); | ||
羁 | } | ||
聿 | |||
fseek(fp,-1,1); | |||
膆 | |||
token[i]='\0'; | |||
蚆 | |||
c=reserve(token); |
| ||
蚂 | |||
| |||
膀 | output(c,token); | ||
蒈 | } | ||
肅 | else | ||
莂 | output(a++,token); | ||
芁 | |||
| |||
21
蚇 蒅 膃 聿 罿 袄 袃 肀 肈 薇 蚃 膂 | else | |
if(isdigit(ch)) | //如果是数字 | |
{ token[0]=ch; ch=fgetc(fp); i=1; | ||
while(isdigit(ch)) |
| |
token[i]=ch; | ||
芆 | token[i]='\0'; |
|
22
肇 fseek(fp,-1,1);
莄 output(b++,token);
罿 }
薈 else
蒆 switch(ch)//判断是否为符号
膄 {
羀
蚇 case')':output(e++,")");break; //是否为),是则输出
袅 case'[':output(e++,"[");break; //是否为[,是则输出
袄 case']':output(e++,"]");break; //是否为],是则输出
肂 case'{':output(e++,"{");break; //是否为{,是则输出
聿case'}':output(e++,"}");break; //是否为},是则输出
23
芅 | case',':output(e++,",");break; | //是否为,,是则输出 |
薅 | //是否为:,是则输出 | |
case':':output(e++,":");break; | ||
衿 | //是否为;,是则输出 | |
case';':output(e++,";");break; | ||
膇 | //是否为\,是则输出 | |
case'"':output(e++,"\"");break; |
螄 case'+':ch=fgetc(fp); //是否为+,是则往前搜索一个字
符
肁 羀 芆 膄 袂 羂 蚈 | | |
else | //不是则文件指针回退一个,输出+ | |
{ | ||
fseek(fp,0,1); |
| |
24
袇output(f++,"+");
薂}
蝿 }
螇 else output(f++,"+");
芆break;
莂 case'-':ch=fgetc(fp); //是否为-,是则往前搜索一个字
符 袁 腿 蚆 肃 袂 芇 | | |
{ |
| |
25
芈 羆 螂 螂 蚇 蚆 袃 袁 | fseek(fp,0,1); |
肆 case'>':ch=fgetc(fp); //是否为>,是则往前搜索一个字
符
蒆 | if(!feof(fp)) |
|
羅 | { | |
罿 | ||
if(ch=='=') |
26
螀 膇 螂 莁 艿 袇 螃 蒀 蚈 莃 袅 袂 | output(f++,">="); else { fseek(fp,0,1); output(f++,">"); } | |
} |
| |
break; | ||
case'<': ch=fgetc(fp); | //是否为<,是则往前搜索一个字符 | |
if(!feof(fp)) { | ||
肈 | if(ch=='=') |
|
27
膄output(f++,"<=");
蚂else
羀{
蒇fseek(fp,-1,1);
袄output(f++,"<");
蚃 }
聿
羇 else{
蚅 fseek(fp,0,1);
螅 output(f++,"<");}
蒁break;
莆 case'=':ch=fgetc(fp); //是否为=,是则往前搜索一个字
符
28
莅 薂 薀 聿 肅 薄 羂 葿 袆 莁 肀 袈 | if(feof(fp)){ fseek(fp,0,1); output(f++,"=");} else { | |
if(ch=='=') |
| |
else | ||
} |
| |
29
薆 蒂 腿 莇 莆 薄 薁 螇 肇 莁 虿 膆 | } break; | |
case'!': ch=fgetc(fp); | //是否为!,是则往前搜索一个字符 | |
if(!feof(fp)) { if(ch=='=') | ||
output(f++,"!="); |
| |
{ | ||
袇 | } |
|
30
莂 else output(f++,"!");
肂break;
袀 }
芄 }
蒄voidmain()
膀{ 艿 肄 芁 艿 螈 螄 | | |
{ ch=fgetc(fp); |
| |
31
芃 scanner(fp);
蚁 }
膈 fclose(fp);
薅}
莄四、测试数据及其结果分析
蝿测试用例(1):
芅测试用例(2):
膁测试结果:
膂五、课程设计总结
肆(1)课程设计过程中的问题
肅问题:在超前搜索时候,当达到文件最后一个字符时候,仍然会超前搜索,搜索
32
eof,从而程序陷入无限循环。原来部分代码为:
膃case'<': ch=fgetc(fp);
芀if(ch=='=')
output(f++,"<=");
螀else{
fseek(fp,-1,1);
output(f++,"<");
螆}
芄 break;莈解决方案
号,是则输出当前符号,否则继续判断是否为双目符号。修正后:
腿case'<': ch=fgetc(fp);
蒆 if(!feof(fp))
肁{
螁if(ch=='=')
output(f++,"<=");
33
蕿else
芇{
fseek(fp,-1,1);
output(f++,"<");
膃}
衿}
羈else{
羇fseek(fp,0,1);
膄output(f++,"<");}膂 break;
蒇(2)课程设计的总结
螇词法分析程序的编写,是我对c语言编程的认识又多了一些新的认识。让我把这段时间
荒废的c语言中的一些知识点重新巩固了。了解了一些计算机编程的艺术。同样也发现了
自己的不足,对于界面设计的缺乏。
羁从这个设计中我更加理解了《编译原理》中关于词法分析这块的知识,对于这本书的
理解加深了一层,“书读百遍,其义自现”最为贴切。也从vc++这个程序运行环境发现了
自己对于词法分析器考虑的不足之处,对于以后自身的发展有着重要的意义。
34
莀 教 师 评 语 蒈 成 绩 评 定 |
| ||||||||||||||||||
35
Forpersonal use only in study and research; not for commercial use
36