编译原理实验一

一、 实验目的
通过设计编制调试一个具体的词法分析程序,加深对词法分析原理的理解。并掌握在对程序设计语言源程序进行扫描过程中将其分解为各类单词的词法分析方法。
这里以开始定义的c语言子集的源程序作为词法分析程序的输入数据。在词法分析中,自文件头开始扫描源程序字符,一旦发现符合“单词”定义的源程序字符串时,将它翻译成固定长度的单词内部表示,并查填适当的信息表。经过词法分析后,源程序字符串(源程序的外部表示)被翻译成具有等长信息的单词串(源程序的内部表示),并产生两个表格:常数表和标识符表,它们分别包含了源程序中的所有常数和所有标识符。
二、 实验要求
程序能够从左到右一个字符一个字符地读入源程序,并对构成的源程序的字符流进行扫描和分解,从而识别出一个个单词(也称单词符号或符号)。并给出单词的值和属性。
三、 实验步骤
(一)提示词法分析程序的运行流程
1、主函数main():
2、打开要分析的C源程序,若不能正确打开,则报错。
3、 先从源程序中读入一个字符ch,然后进行如下处理:
1)ch是字符:转入关键字和标识符处理子函数;
2)ch是数字:转入数字处理函数;
3)ch是其他字符:转入其他字符处理子函数;
4)结束。
(二)相关规定
1、假设其中关键字包括:“if”,“else”,“for”,“while”,“do”,“return”,“break”,“continue”
2、界符包括:",", “;”, “{”, “}”, “(”, “)”
3、算术运算包括:"+","-","*","/"
4、关系运算法包括"<","<=","=",">",">=","<>"
5、常量和标识符的数位最大为20;
(三)提示
关键字和标识符处理过程用函数来实现,假设为alphaprocess(char buffer)
1、将buffer送入临时数组中(设为alphatp),再读入一个字符至buffer;
2、判断buffer是否为字符或数字,若是,则alphatp[1]=buffer;
3、重复1,2,直到2判断为假;在alphatp末尾添加’\0’;
4、调用search()子函数,在关键字表中匹配alphatp,若匹配成功,则返回序号;
5、调用search,在标识符表中匹配alphatp,若匹配成功,则返回序号;
6、在标识符表中添加alphatp,并返回序号;
(四)提示
数字和字符的判断利用库函数提供的isalpha()和(isdigit()

实验中用到的测试的 example.c的文件内容
///
#include <stdio.h>
void mian(){
    int a=10,b=5;
if(a<b){
	printf("a is smaller than b");}
else if(a>b){
		printf("a is bigger than b");}
else{
do{
	a=b+a;
             b=a*b;	
             break;
		}while(a==b)
		}
		return 0;
}/

代码

#include   <iostream>
#include <string>
using   namespace  std;
#define  MAX 22 
char  ch = ' ' ;
string key[15]={ "begin" , "end" , "if" , "then" , "else" , "while" , "write" , "read" ,
"do" ,  "call" , "const" , "char" , "until" , "procedure" , "repeat" };
int  Iskey(string c){  // 关键字判断
  int  i;
  for (i=0;i<MAX;i++) {
  if (key[i].compare(c)==0)  return  1;
 } 
  return  0;
}
int  IsLetter( char  c) {  // 判断是否为字母
  if (((c<= 'z' )&&(c>= 'a' ))||((c<= 'Z' )&&(c>= 'A' )))  return  1;
  else   return  0;
}
int  IsDigit( char  c){  // 判断是否为数字
  if (c>= '0' &&c<= '9' )  return  1;
  else   return  0;
}
void  analyse(FILE *fpin){
 string arr= "" ; 
  while ((ch=fgetc(fpin))!=EOF) {
 arr= "" ; 
  if (ch== ' ' ||ch== '\t' ||ch== '\n' ){} 
 
  else   if (IsLetter(ch)){
  while (IsLetter(ch)||IsDigit(ch)) {
  if ((ch<= 'Z' )&&(ch>= 'A' )) ch=ch+32; 
 arr=arr+ch;
 ch=fgetc(fpin);
 }
 fseek(fpin,-1L,SEEK_CUR); 
  if  (Iskey(arr)){cout<<arr<< "\t$ 关键字 " <<endl;} 
  else  cout<<arr<< "\t$ 普通标识符 " <<endl; 
 }
 
  else   if (IsDigit(ch)){
  while (IsDigit(ch)||ch== '.' &&IsDigit(fgetc(fpin))){
 arr=arr+ch;
 ch=fgetc(fpin);
 }
 fseek(fpin,-1L,SEEK_CUR);
 cout<<arr<< "\t$ 无符号实数 " <<endl; 
 }
  else   switch (ch){ 
  case '+' :
  case '-'  :
  case '*'  :
  case '='  :
  case '/'  :cout<<ch<< "\t$ 运算符 " <<endl; break ;
  case '('  :
  case ')'  :
  case '['  :
  case ']'  : 
  case ';'  :
  case '.'  :
  case ','  :
  case '{'  :
  case '}'  :cout<<ch<< "\t$ 界符 " <<endl; break ;
  case ':'  :{ch=fgetc(fpin);
  if (ch== '=' ) cout<< ":=" << "\t$ 运算符 " <<endl;
  else  {cout<< "=" << "\t$ 运算符 " <<endl;;
 fseek(fpin,-1L,SEEK_CUR);}
 } break ;
case '>'  :{ch=fgetc(fpin);
  if (ch== '=' ) cout<< ">=" << "\t$ 运算符 " <<endl;
  if (ch== '>' )cout<< ">>" << "\t$ 输入控制符 " <<endl;
  else  {cout<< ">" << "\t$ 运算符 " <<endl;
 fseek(fpin,-1L,SEEK_CUR);}
 } break ;
  case '<'  :{ch=fgetc(fpin);
  if (ch== '=' )cout<< "<=" << "\t$ 运算符 " <<endl;
  else   if (ch== '<' )cout<< "<<" << "\t$ 输出控制符 " <<endl;
  else   if (ch== '>' ) cout<< "<>" << "\t$ 运算符 " <<endl;
  else {cout<< "<" << "\t$ 运算符 " <<endl;
 fseek(fpin,-1L,SEEK_CUR);}
 } break ;
  default  : cout<<ch<< "\t$ 无法识别字符 " <<endl;
 }
 }
}
void  main(){
  char  in_fn[30];
 FILE * fpin;
 cout<< " 请输入源文件名(包括路径和后缀名) :" ;
  for (;;){
 cin>>in_fn;
  if ((fpin=fopen(in_fn, "r" ))!=NULL)  break ;
  else  cout<< " 文件路径错误!请输入源文件名(包括路径和后缀名) :" ;
 }
 cout<< "\n******************** 分析如下 *********************" <<endl;
 analyse(fpin);
 fclose(fpin);
 cout<<endl;
 cout<< " 按任意键结束 " <<endl;
  int  a;
 cin>>a;
}

实验结果

  • 3
    点赞
  • 47
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值