编译原理实验实战 | |
作者: falcon 发表日期: 2006-04-07 17:47 | |
编译原理课程设计实现 一,概述 1、词法分析 2、语法分析 3、语义分析 相关资料: 1)实验教材信息学院ftp>incoming>教师专用>编译原理>编译原理实验题目 2)其他资料 《程序实现C语言词法分析器的设计》:http://pro.jxyd.net/A921/zhuye/analy1.cpp 3)Lex$yacc使用 http://li2.itpub.net/post/72/64211 二,正文 1,词法分析器 4月21日,花了几个小时的时间,把以前有过一定准备的词法分析器基本完成。 首先介绍词法分析器的流程(由于我太懒,没有重新划,直接copy自老师的课件): [注:我还不知道这个blog怎么把图片弄上来哦,真是郁闷] 下面简单介绍一下设计过程算拉: 由于编译原理课程中对词法分析的基本原理讲得非常清楚(当然,还是有好多值得思考和探讨的地方哦),甚至都给出了基本的算法,所以我们要做的只是用某一个语言把它实现拉。 我的做法是: 1)理清词法分析的功能 词法分析器又称扫描器,输入源程序,进行词法分析,输出单词符号。 这样我们就弄清楚了词法分析器的基本功能,该过程的输入与输出,接着就是要“如何实现词法分析”,从相应的输入获得相应的输出。 2)词法分析器的设计 这个过程基本上是进一步弄清词法分析器的工作过程,从输入(预处理)——>单词符号的识别(超前搜索)——>画出状态转化图(实现过程流程化)——>实现状态转换图(算法实现,子过程划分等) 3)用某一门具体语言编写代码,算法程序化 我用的是c语言哦,实现的时候还是蛮方便的。不过由于有好长一段时间没有用c,好多语法都有些陌生拉。 总结: 通过词法分析器的设计,发现了自己好多问题,比如由于好长时间没有用c语言进行编程,所以导致无法积累这方面的编程经验。另外,由于该实验两个礼拜以前就已经布置,但我到现在才麻烦完成,说明我对时间的把握还是比较欠缺的。 |
/*
============前言==========================
SUBJEST:Pascal语言子集词法分析器
Author:falcon
announce:版权所有,请尊重知识产权
=========Pascal语言子集要求===============
关键字 begin do else end if then var while
-----------------------------------------
分界符 , ; . := ( )
-----------------------------------------
算术运算符
(code,运算符)
10H +
11H -
20H *
21H /
------------------------------------------
关系运算符
(code,运算符)
00H <
01H <=
02H =
03H >
04H >=
05H <>
------------------------------------------
字符种类 code type
关键字 指针,0
分界符 指针,1
算术运算符 code,2
关系运算符 code,3
标识符 指针,4
常数表 指针,5
===========================================
*/
/*代码正文*/
#include <stdio.h>
#include <string.h>
#include<process.h> // exit 包含的头文件
/*涉及到的字符集*/
char* key[6]={"begin","if","then","while","do","end"};
/*定义关键字*/
char* par[6]={",",";",".",":=","(",")"}; /*定义分界符*/
typedef struct /*定义运算符结构体*/
{
int ISN; /*内部编码*/
char *Oper; /*值*/
}Ope;
Ope
AriOpe[4]={{10,"+"},{11,"-"},{20,"*"},{21,"/"}},RelOpe[6]={{0,"<"},{1,"="},{2,">"},{3,"<="},{4,">="},{5,"<>"}};
char mask[200][8],cons[200][8];
/*标识符和常数数组,最好是弄成动态分配*/
int maski=-1,consi=-1; /*上述数组对应的指针*/
/*词法分析用到的一些变量*/
char strToken[8],ch,instring[500]; /*字符串、字符、文件缓冲变量*/
int si=0,searchi=0; /*对应的指针*/
int tempi; /*循环过程中用到指针*/
/*返回结果形式的结构体*/
typedef struct
{
int CODE;
int TYPE;
}RetCT;
/*各个子过程*/
void GetChar() /*取得一个字符*/
{
ch=instring[searchi];
searchi=searchi+1;
}
void GetBC()
/*取得一个字符并且为非空*/
{
while(ch==' ') GetChar();
}
void Concat()
/*把最近取得的字符(ch)连接到字符串(strToken)*/
{
strToken[si]=ch;
si=si+1;
}
int IsLetter() /*判断某个字符是否为字母*/
{
if((ch<='Z'&& ch>='A')||(ch<='z'&&ch>='a'))
return 1;
else return 0;
}
int IsDigit() /*判断某个字符是否为数字*/
{
if(ch<='9'&&ch>='0') return 1;
else return 0;
}
int Reserve() /*查找保留字表,返回它的编码*/
{
for(tempi=0;tempi<6;tempi++)
if (strcmp(strToken,key[tempi])==0) {return tempi;}
return 0;
}
void Retract()
/*回退一个字符,并且置ch为空*/
{
searchi=searchi-1;
ch=' ';
}
int InsertId()
/*把strToken插入标识符表,返回标识表指针*/
{
for(tempi=0;tempi<maski;tempi++)
if(strcmp(strToken,mask[tempi])==0){return tempi;}
maski++;
strcpy(mask[maski],strToken);
return maski;
}
int InsertConst()
/*将strTken中的常数常数插入常数表,返回常数表指针*/
{
for(tempi=0;tempi<consi;tempi++)
if(strcmp(strToken,cons[tempi])==0){return tempi;}
consi++;
strcpy(cons[consi],strToken);
return consi;
}
int GetCode(int type)
/*取得分界符表、算术运算和逻辑运算符表的内部编码或指针*/
{
if(type==1)
{
for(tempi=0;tempi<6;tempi++)
if(strcmp(strToken,par[tempi])==0){return tempi;}
return -1;
}
else if(type==2)
{
for(tempi=0;tempi<4;tempi++)
if(ch==AriOpe[tempi].Oper[0]){return AriOpe[tempi].ISN;}
return -1;
}
else if(type==3)
{
for(tempi=0;tempi<6;tempi++)
if(strcmp(strToken,RelOpe[tempi].Oper)==0){return RelOpe[tempi].ISN;}
return -1;
}
}
/*一次词法分析过程*/
RetCT CFFX()
{
int code,type;
RetCT Ret;
si=0; /*每次词法分析之前进行初始化*/
for(tempi=0;tempi<8;tempi++)
{
strToken[tempi]=' ';
}
GetChar();
GetBC();
if(IsLetter())
{
while(IsLetter()||IsDigit())
{
Concat();GetChar();
}
Retract();
code=Reserve();
if(code==0)
{
code=InsertId(strToken);
type=4;
}
else type=0;
}
else if(IsDigit())
{
while(IsDigit())
{
Concat();GetChar();
}
Retract();
code=InsertConst(strToken);
type=5;
}
else if(ch==','||ch==';'||ch=='.'||ch=='('||ch==')'||ch==':')
{
type=1;
Concat();
GetChar();
if(ch!='=') Retract();
else Concat();
code=GetCode(type);
}
else if(ch=='+'||ch=='-'||ch=='*'||ch=='/')
{
type=2;
code=GetCode(type);
}
else if(ch=='='||ch=='>'||ch=='<')
{
type=3;
Concat();
GetChar();
if(ch!='='&&ch!='>') Retract();
else Concat();
code=GetCode(type);
}
else code=-1;
Ret.CODE=code;
Ret.TYPE=type;
return Ret;
}
/*打开文件读取源代码*/
void ReadSource()
{
FILE *fp;
char cha;
if((fp=fopen("F://compiler//program//Pascal.txt","r"))==NULL)
/*打开文件,文件名最好是可以输入*/
{
printf("cannot open file/n");
exit(0) ;
}
cha=fgetc(fp);
while(cha!=EOF)
{
if(cha!='/n')
{
instring[searchi]=cha;
searchi=searchi+1;
}
cha=fgetc(fp);
}
fclose(fp);
instring[searchi]='#';
/*在源代码缓冲区的最后插入一个标记作为结束标志*/
searchi=0;
}
/*主函数过程*/
int main()
{
RetCT RetTmp;
ReadSource(); /*调用ReadSource()过程获得源代码*/
/*显示出来*/
printf("/nThe Source is :/n/n%s/n/nAfter analysing the accidence,The Result is:/n/n",instring);
/*调用一次词法分析过程进行词法分析*/
do
{
RetTmp=CFFX();
if(RetTmp.CODE==-1)
{
printf("ERROR!/n");
break;
}
else
printf("%d,%d/n",RetTmp.CODE,RetTmp.TYPE);
}while(instring[searchi]!='#');
return 1;
}
///
txt 文件内容:
var a:=0;
do
a:=a+1;
while(a<=5);