题目描述:
输入:所给文法的源程序字符串
输出:二元组(syn,token或sum)构成的序列。
syn为单词种别码;
token为存放的单词自身字符串;
sum为整形常数。
例如:对源程序begin x:=9;if x>0 then x:=2*x+1/3;end# 经词法分析后输出如下序列:(1,begin)(10,’x’) (18,:=) (11,9) (26,😉 (2,if)……
设计步骤:
1.建立数据库存储保留字表
保留字的数量较多,若采用列表或字典存储保留字,需编写对列表或字典的查询函数,每次运行都需要对保留字列表进行初始化赋值,因此采取数据库存储方便查询、更新、修改等操作,符合程序设计理念,同时还可以对数据库相关知识进行实践与复习。
1. # 连接
2. db = pymysql.connect("localhost", "root", "数据库密码", "lexical")
3. # 使用 cursor() 方法创建一个游标对象 cursor
4. cursor = db.cursor()
5. sql = """create table lexical_cpp(
6. name varchar(100),
7. id int);"""
8. cursor.execute(sql)
9. 1. # 插入保留字
2. f = open('reservedWord.txt', 'r')
3. temp = 1
4. for i in f:
5. i = i.strip('\n')
6. sql = "INSERT INTO lexical_cpp(name, id) VALUES ('" + str(i) + "'," + str(temp) + ")"
7. try:
8. cursor.execute(sql)
9. db.commit()
10. except:
11. # 发生错误时回滚
12. db.rollback()
13. temp += 1
14.
15. # 关闭数据库连接
16. db.close()
2.词法分析过程
首先初始化词法分析所需的几个列表和位置指针,读入写有测试代码的txt文件,去除文件中的换行符、制表符、多余的空格等符号;逐个字符读入分析,依次按照标识符和变量名、常数、运算符、分隔符的顺序分析。
(1) 判断保留字或变量名:
第一个字符如果为字母、_或
,
则
有
可
能
为
保
留
字
或
者
变
量
,
(
是
否
是
字
母
通
过
s
t
r
.
i
s
a
l
p
h
a
(
)
函
数
判
断
)
接
着
向
下
判
断
,
若
接
下
来
的
字
符
是
字
母
、
数
字
、
或
,则有可能为保留字或者变量,(是否是字母通过str.isalpha()函数判断)接着向下判断,若接下来的字符是字母、数字、_或
,则有可能为保留字或者变量,(是否是字母通过str.isalpha()函数判断)接着向下判断,若接下来的字符是字母、数字、或,则加入分析列表res_lst,直到最新字符不是上述字符类型为止;使用join()函数合并res_lst列表中字符,得到一个字符串,SQL语句查询数据库中的保留字表,若存在该字符串,则返回保留字和保留字对应的种别码,若不存在,说明该字符串为变量名,返回该字符串和种别码0。
(2) 判断常数:
通过str.isdigit()函数判断第一个字符,如果是数字,则接着判断下一字符,直到数字结束为止,回退指针;使用join()函数合并列表,用33作为种别码返回。
(3) 判断运算符:
判断字符是否是=,+,-,,/,>,<,!,%中的某一个,若是,接着判断后续字符(判断“特殊”运算符>=,<=,!=,**,=,+=,-=);使用join()合并,用34作为种别码返回。
(4) 判断分隔符:
判断字符是否是{,},;,(,)中某一个,若是,则返回种别码35。
1)识别过程:
对标识符、常数、运算符和分隔符的分析过程类似,以分析标识符为例:
1.# 第一个字符规则
2. if new_ch.isalpha() or new_ch == '_' or new_ch == '$':
3. str_get.append(new_ch)
4. new_ch = get_char(res_lst)
5. # 第二个字符规则
6. while new_ch.isalpha() or new_ch.isdigit() or new_ch == '_' or new_ch == '$':
7. str_get.append(new_ch)
8. new_ch = get_char(res_lst)
9. retract_pointer()
10. str_result = ''.join(str_get)
11. code, id = is_reserved_word(str_result)
12. if code == 0:
13. value = insert_identifier(str_result)
14. result.append('0') # 这里使用0作为非保留字的标识符的种别编码
15. result.append(value)
16. # print(result)
17. return result
18. else:
19. result.append(str(id)) # 对应的保留字编码
20. result.append(str_result)
21. # print(result)
22. return result
(2)判断是否在保留字表中:
在判断标识符时,需要通过SQL语句查询数据库判断是否为保留字,主要代码如下:
1. def is_reserved_word(str_result):
2. db = pymysql.connect("localhost", "root", "123456", "lexical")
3. # 使用 cursor() 方法创建一个游标对象 cursor
4. cursor = db.cursor()
5. sql = "select * from lexical_cpp;"
6. try:
7. # 执行SQL语句
8. cursor.execute(sql)
9. # 获取所有记录列表
10. results = cursor.fetchall()
11. reserved_words = []
12. for row in results:
13. index = {}
14. name = row[0]
15. id = row[1]
16. index['name'] = name
17. index['id'] = id
18. reserved_words.append(index)
19. # print(reserved_words)
20. for temp in reserved_words:
21. if temp['name'] == str_result:
22. db.close()
23. return 1, temp['id']
24. else:
25. continue
26. db.close()
27. return 0, 0
28. except:
29. # 发生错误时回滚
30. db.rollback()