一、实验目的
了解词法分析程序的基本构造原理,掌握词法分析程序的手工构造方法。
二、实验内容
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、根据常量说明串置于高级语言源程序中时可能出现的错误情况,模仿高级语言编译器对不同错误情况做出相应处理;
import sys
import re
keywords = ['const']
def to_split(str):
str = str.strip()
f = 0
while True:
if str[-1] == ';':
str = str[:-1]
f = 1
else:
if f == 1:
break
else:
print("末尾缺少;\n")
sys.exit()
# str_list = str.split(',')
all = re.finditer(',[^\"\'=]{1,100}=', str)
list_dou = []
for i in all:
list_dou.append(i.span()[0])
str2 = list(str)
a = ""
for i in range(len(str)):
if i in list_dou:
a = a + '!@#123$%^&*'
else:
a = a + str[i]
str = a.split('!@#123$%^&*')
return str
def get_type(str):
str = str.strip()
global int_num
global char_num
global string_num
global float_num
name_word = ""
type_word = ""
value_word = ""
# p判断是否有 = 号,如果有的话输出下标
index_dengyu = str.find("=")
if index_dengyu == -1:
print("缺少 = \n")
sys.exit()
# = 号左右分割
str_left = str[:index_dengyu].strip()
str_right = str[index_dengyu + 1:].strip()
# = 号左分割成单词
# =左边按空格分隔,去掉列表里面的'',然后判断
str_left_list = str_left.split(' ')
temp = []
for i in str_left_list:
if i != '':
temp.append(i)
str_left_list = temp
if len(str_left_list) == 1:
name_word = str_left_list[0]
# 判断第一个是否为字母
if name_word[0].isalpha() is False:
print("%s(错误!变量名首字母不为字母!)\n" % str_left_list[0])
return 0
elif len(str_left_list) == 2:
if str_left_list[0] in keywords:
name_word = str_left_list[1]
if name_word[0].isalpha() is False:
print("%s(错误!变量名首字母不为字母!)\n" % str_left_list[1])
return 0
else:
print("%s 不是关键字!\n" % str_left_list[0])
sys.exit();
# 格式
if str_right[0] == '.':
type_word = "float"
float_num = float_num + 1
value_word = str_right
elif str_right[0] == '\'' and str_right[-1] == '\'':
if len(str_right) != 3:
print("%s(错误!字符串格式错误!)\n" % name_word)
return 0
type_word = "char"
char_num = char_num + 1
value_word = str_right
else:
try:
try:
type_word = "integer"
value_word = int(str_right)
int_num = int_num + 1
except:
type_word = "float"
value_word = float(str_right)
float_num = float_num + 1
except:
if str_right[0] != '\"' and str_right[-1] != '\"':
print("%s(错误!字符串格式错误!)\n" % name_word)
return 0
type_word = "string"
string_num = string_num + 1
value_word = str_right
print("%s(%s,%s)\n" % (name_word, type_word, value_word))
str = """
const count1 = 2180,sum1 = 6881.655,char1='f',
count2=65,max1=169,char2='@',sum2=.0815,str1="\"cds f 89h\"",
max2=1.6229,str2="good jbhn";
"""
str_list = to_split(str)
int_num = 0
char_num = 0
string_num = 0
float_num = 0
# str_list = ["const count1 = 2180"]
for i in str_list:
get_type(i)
print(("int_num = %s,char_num = %s,string_num = %s,float_num = %s\n" \
% (int_num, char_num, string_num, float_num)))