编译原理实验:实验一 简单词法分析程序设计(必修)(Python实现)
一、实验目的
了解词法分析程序的基本构造原理,掌握词法分析程序的手工构造方法。
二、实验内容
1、了解编译程序的词法分析过程。
2、根据PASCAL语言的说明语句形式,用手工方法构造一个对说明语句进行词法分析的程序。该程序能对从键盘输入或从文件读入形如:
“const count=10,sum=81.5, char1=’f’, string1=”hj”,max=169;”
的常量说明串进行处理,分析常量说明串中各常量名、常量类型及常量值,并统计各种类型常量个数。
三、实验要求
1、输入的常量说明串,要求最后以分号作结束标志;
2、根据输入串或读入的文本文件中第一个单词是否为“const”判断输入串或文本文件是否为常量说明内容;
3、识别输入串或打开的文本文件中的常量名。常量名必须是标识符,定义为字母开头,后跟若干个字母,数字或下划线;
4、根据各常量名紧跟等号“=”后面的内容判断常量的类型。其中:字符型常量定义为放在单引号内的一个字符;字符串常量定义为放在双引号内所有内容;整型常量定义为带或不带+、- 号,不以0开头的若干数字的组合;实型常量定义为带或不带+、- 号,不以0开头的若干数字加上小数点再后跟若干数字的组合;
5、统计并输出串或文件中包含的各种类型的常量个数;
6、以二元组(类型,值)的形式输出各常量的类型和值;
7、根据常量说明串置于高级语言源程序中时可能出现的错误情况,模仿高级语言编译器对不同错误情况做出相应处理;
代码实现:考虑到Python的正则表达式的强大,我就用了Python来实现,也正好练练自己的Python代码能力,学习Python这么久了,自己还没用Python正式写过项目,实在不敢说自己学过Python。
考虑到实验内容,我分别用了几个函数来提取const关键字,提取每一个常量定义的句子,和提取变量标识符,和判断变脸的类型。
代码如下:
1 import re 2 """5个做统计的全局变量""" 3 int_num = 0 4 char_num = 0 5 string_num = 0 6 float_num = 0 7 bool_num = 0 8 """用来去掉正则时产生的 中括号 以及 分号 ' """ 9 def myReplace(s): 10 s = s.replace('[\'','') 11 s = s.replace('\']','') 12 s = s.replace('[','') 13 s = s.replace(']','') 14 return s 15 """判断是否是bool型常量""" 16 def IsBool(s,currn): 17 s = s + ' ' 18 global bool_num 19 bool_error = re.findall(r'= *([a-z]+ +[^ ]+) ',s,0)#优先匹配错误情况,比如 x = true hdfkjg(中间空格分开的字符) 20 if(bool_error): 21 return False 22 bool_T = re.findall(r'= *(true) ',s,0)#匹配true情况 23 if(bool_T): 24 print(currn+'(bool,'+bool_T[0]+')') 25 bool_num = bool_num + 1 26 return True 27 bool_F = re.findall(r'= *(false) ',s,0)#匹配false情况 28 if(bool_F): 29 print(currn + '(bool,' + bool_F[0] + ')') 30 bool_num = bool_num + 1 31 return True 32 33 """判断是否是字符串常量""" 34 def IsStrings(s,currn): 35 global string_num 36 String = (re.findall('=[\ ]*([\“|\"][^\“\"]*[\”|\"])[\ |,|;]*',s,0)) 37 for strings in String: 38 strings = str(strings) 39 if(strings): 40 print(currn+'(string,'+strings+')') 41 string_num = string_num + 1 42 return True 43 else: 44 return False 45 """判断是否是字符常量""" 46 def IsChar(s,currn): 47 Char = re.findall('=\ *([\‘|\'][^\'\‘\’]+[\’|\'])',s,0) 48 global char_num 49 for C in Char: 50 C = str(C) 51 if(C): 52 if(len(C)==3): 53 print(currn+'(char, '+C+')') 54 char_num = char_num + 1 55 else: 56 print(currn+'(Wrong! There are more than one char in ‘’.)') 57 return True 58 else: 59 return False 60 61 """判断是否是浮点数常量""" 62 def IsFloat(s,currn): 63 s = s + ' ' 64 global float_num 65 Float_first = re.findall(r'= *([+|-]?0?.[0-9]+) ',s,0)#匹配整数部分为0或者没有的情况的情况 66 if(Float_first): 67 print(currn+'(float,'+Float_first[0]+')') 68 float_num = float_num + 1 69 return True 70 Float_0 = re.findall(r'= *([+|-]?0[0-9]+.[0-9]+) ',s,0)#匹配整数部分以0开始的错误情况 71 if(Float_0): 72 print(currn + '(Wrong! The float can’t be started with ‘0’.)') 73 return False 74 Float_E = re.findall(r'= *([+|-]?[1-9].[0-9]+[E|e]-[1-9][0-9]*) ',s,0)#匹配正确的实型科学计数法,未考虑错误情况 75 if(Float_E): 76 print(currn + '(float,' + Float_E[0]+ ')') 77 float_num = float_num + 1 78 return True 79 Float = str(re.findall(r'\=[\ ]*([+|-]?[0-9]*\.[0-9]+) ',s,0)) 80 Float = myReplace(Float) 81 if(Float): 82 print(currn+'(float,'+Float+')') 83 float_num = float_num + 1 84 return True 85 else: 86 return False 87 88 """判断是否是整形常量""" 89 def IsInt(s,currn): 90 s = s + ' ' 91 global int_num 92 Int_E = re.findall(r'= *([+|-]?[1-9].[0-9]+[E|e][+][1-9][0-9]*) ',s,0)#匹配整型为科学计数法的情况,未考虑错误情况 93 if(Int_E): 94 print(currn + '(integer,' + Int_E[0] + ')') 95 int_num = int_num + 1 96 return True 97 Int_first = re.findall(r'= *([0]) ',s,0)#匹配数值为0的情况 98 if(Int_first): 99 int_num = int_num + 1 100 print(currn + '(integer,' + '0' + ')') 101 return True 102 Int_0 = re.findall(r'= *([+|-]?0[0-9]*) ',s,0)#匹配数值以0开头的情况(已去掉单个0情况) 103 if(Int_0): 104 print(currn + '(Wrong! The integer can’t be started with ‘0’.)') 105 return False 106 Int = (str)(re.findall(r'= *([+|-]?[1-9][0-9]*) ',s,0)) 107 Int = myReplace(Int) 108 if(Int): 109 print(currn+'(integer,'+Int+')') 110 int_num = int_num + 1 111 return True 112 else: 113 return False 114 """判断变量名是否合法""" 115 def pd(s): 116 bian = str(re.findall(r' *([A-Za-z0-9_]*) *=',s,0)) 117 bian = myReplace(bian) 118 if(bian and (not(bian[0]>='0'and bian[0]<='9'))): 119 return bian 120 else: 121 print(bian+'(Wrong! It is not aidentifier!)') 122 return '0error' 123 """获得const关键字""" 124 def getcon(s): 125 fir = re.findall('[\ ]*(const)\ ', s, 0) 126 if(len(fir) == 1): 127 return fir 128 else: 129 return 'None' 130 """获得变量的类型""" 131 def getType(s): 132 fir = (re.findall(r'[ |,|,|]+?(.*?[^,;]+)[,|;]*?',s,0))#将输入正确的串按照 ,(逗号) 或者 ;(分号)分开,/ 133 #操作后的fir就是一个个变量定义的集合 例如 [x = 1, y=2.2] 134 for men in fir: 135 currn = pd(str(men))#判断变量名是否合法,并取出合法的变量名,如果变量名不合法,currn='0error' 136 if(currn=='0error'): 137 continue 138 else: 139 if(IsBool(men,currn)): 140 continue 141 if(IsStrings(men,currn)): 142 continue 143 if(IsChar(men,currn)): 144 continue 145 if(IsFloat(men,currn)): 146 continue 147 if(IsInt(men,currn)): 148 continue 149 150 """Main 函数入口""" 151 if __name__ == '__main__': 152 while(True): 153 bool_num = int_num = float_num = char_num = string_num = 0 154 st = input() 155 fir = getcon(st)#获得const标识符 156 if(fir!='None'): 157 getType(st) 158 print("int_num=%d; char_num=%d; string_num=%d; float_num=%d; bool_num=%d."%(int_num,char_num,string_num,float_num,bool_num)) 159 else: 160 print('It is not a constant declaration statement!') 161 print('Please input a string again!') 162 163 164 """ const count=10,sum=81.5,char1=‘f’,max=169,str1=“h*54 2..4S!AAsj”, char2=‘@’,str2=“aa!+h”;
count(float,10)
sum(float,81.5)
char1(char, ‘f’)
max(float,169)
str1(string,“h*54 2..4S!AAsj”)
char2(char, ‘@’)
str2(string,“aa!+h”)
int_num=0; char_num=2; string_num=2; float_num=3; bool_num=0.
Aconstt count=10,sum=81.5,char1=‘f’;
It is not a constant declaration statement!
Please input a string again!
const count=10,12sum=81.5,char1=‘ff’,max=0016;
count(float,10)
12sum(Wrong! It is not aidentifier!)
char1(Wrong! There are more than one char in ‘’.)
max(float,0016)
int_num=0; char_num=0; string_num=0; float_num=2; bool_num=0.
const dx = 1.27e+7,de = 1.27e-21,dd=89.7,fdg=678.6.7.6,4554, rtrtryt=.9898,gfgffggf=8.45,rt = +11.23,rr = -0.01,ry=-00.11;
dx(integer,1.27e+7)
de(float,1.27e-21)
dd(float,89.7)
(Wrong! It is not aidentifier!)
rtrtryt(float,.9898)
gfgffggf(float,8.45)
rt(float,+11.23)
rr(float,-0.01)
ry(Wrong! The float can’t be started with ‘0’.)
int_num=1; char_num=0; string_num=0; float_num=6; bool_num=0.
const x = 1,y=2.2,z='u',u="hdfjksah",dd=true,dt=false,ry=true ,ri= false , zx = true ui,mr = false dslk;
x(float, 1)
y(float,2.2)
z(char, 'u')
u(string,"hdfjksah")
dd(bool,true)
dt(bool,false)
ry(bool,true)
ri(bool,false)
int_num=0; char_num=1; string_num=1; float_num=2; bool_num=4.
const x = 1,y=2.2,z=‘u’,u="hdfjksah";
It is not a constant declaration statement!
Please input a string again!
x(float, 1)
y(float,2.2)
z(char, ‘u’)
u(string,"hdfjksah")
int_num=0; char_num=1; string_num=1; float_num=2; bool_num=0.
"""
六、分析与讨论
1、若考虑用E或e的科学计数法来表示整数和实数,应该如何实现?
2、若考虑布尔型常量,且规定其值只能为true或false,应该如何实现?
3、如何对手工构造的词法分析程序做进一步的优化,以提高代码质量和运行效率?
优化咋办还没有考虑,希望大神帮忙指点。