一. 实验一:词法分析设计
二.实验目的及要求
实现目的:
通过本实验的编程实践,使学生了解词法分析的任务,掌握词法分析程序设
计的原理和构造方法,使学生对编译的基本概念、原理和方法有完整的和清楚的
理解,并能正确地、熟练地运用。
实验要求:
1、编程时注意编程风格:空行的使用、注释的使用、缩进的使用等。
2、将标识符填写的相应符号表须提供给编译程序的以后各阶段使用。
3、根据测试数据进行测试。测试实例应包括以下三个部分:
全部合法的输入。
各种组合的非法输入。
由记号组成的句子
三. 实验内容
用 VC++/VB/JAVA 语言实现对 C 语言子集的源程序进行词法分析。通过输
入源程序从左到右对字符串进行扫描和分解,依次输出各个单词的内部编码及单
词符号自身值;若遇到错误则显示“Error”,然后跳过错误部分继续显示 ;同时
进行标识符登记符号表的管理。
以下是实现词法分析设计的主要工作:
(1)从源程序文件中读入字符。
(2)统计行数和列数用于错误单词的定位。
(3)删除空格类字符,包括回车、制表符空格。
(4)按拼写单词,并用(内码,属性)二元式表示。(属性值——token 的机内
表示)
(5)如果发现错误则报告出错
- 根据需要是否填写标识符表供以后各阶段使用。
(8)识别注释
(9)判别浮点数和整数
四. 核心算法流程
五.核心代码
for line in open("test.txt", 'r', encoding="UTF-8"):
str = line #每次读一行内容
i = 0
while i < len(str): #遍历当前行
if jud1 != 1: #如果不是注释
if str[i].isdigit(): # 字符为数字
jud = 1 # 用于判断该单词是不是纯数字
str1 = '' # 用于暂时存储单词
while i < len(str):
if str[i].isdigit() or str[i] == '.':
str1 += str[i]
i += 1
elif str[i].isalpha():
str1 += str[i]
i += 1
jud = 0
else: break #非字母或者数字(空格或者换行)就退出当前循环
if jud == 1: # 全为数字,构建输出
if str1 not in u: u.append(str1) #为常数表添加新的元素
mes = [str1, f'(1,{str1})', '常数', f'({hang},{lie})']
else: # 夹杂有字母(错误情况,不满足标识符的要求)
mes = [str1, 'Error', 'Error', f'({hang},{lie})']
lie += 1
message = tep.join(mes) #以tep为分隔符创建一个字符串
output.append(message)
elif str[i].isalpha(): # 字符为字母
str1 = ""
while i < len(str):
if str[i].isdigit() or str[i].isalpha() or str[i] == '_':
str1 += str[i]
i += 1
else:
break #不满足标识符要求
if str1 in k: #如果在关键字表中
mes = [str1, f'(1,{k.index(str1)})', '关键字', f'({hang},{lie})']
elif str1 not in v: # 标识符
v.append(str1)
mes = [str1, f'(6,{str1})', '标识符', f'({hang},{lie})']
else:
mes = [str1, f'(6,{str1})', '标识符', f'({hang},{lie})']
lie += 1
message = tep.join(mes)
output.append(message)
elif (str[i] in s): # 字符为算术运算符
str1 = ""
# 判断当前是否是注释
if str[i] == '/' and i != len(str)-1 and str[i+1] == '/':
i = len(str)
elif str[i] == '/' and i != len(str)-1 and str[i+1] == '*':
jud1 = 1
else:
while i < len(str):
if str[i] in s:
str1 += str[i]
i += 1
else: break
if str1 in s: # 字符为算数运算符
mes = [str1, f'(3,{s.index(str1)})', '算术运算符', f'({hang},{lie})']
else:
mes = [str1, 'Error', 'Error', f'({hang},{lie})']
lie += 1
message = tep.join(mes)
output.append(message)
elif (str[i] in t): # 字符为关系运算符
str1 = ""
while i < len(str):
if str[i] in t:
str1 += str[i]
i += 1
else: break
if str1 in t: mes = [str1, f'(4,{t.index(str1)})', '关系运算符', f'({hang},{lie})']
else: mes = [str1, 'Error', 'Error', f'({hang},{lie})']
lie += 1
message = tep.join(mes)
output.append(message)
elif (str[i] in r): # 字符为分界符
str1 = str[i]
i += 1
mes = [str1, f'(2,{r.index(str1)})', '分界符', f'({hang},{lie})']
lie += 1
message = tep.join(mes)
output.append(message)
elif (str[i] == ' '): i += 1 #字符为空格
elif (str[i] == '\n'): #字符为换行
hang += 1
i += 1
continue
else: # 收尾工作(以奇怪字符开头)
str1 = str[i]
i += 1
mes = [str1, 'Error', 'Error', f'({hang},{lie})']
lie += 1
message = tep.join(mes)
output.append(message)
else: #如果当前是注释
while str[i] != '*' or str[i+1] != '/':
if (i < len(str)-2):
i += 1
else: break
if str[i] == '*' and i != len(str)-1 and str[i+1] == '/': #注释的结尾
jud1 = 0
hang -= 1
i += 2
else: break
for datas in output:
data_list = datas.split(' ')
print(f"{data_list[0]:<15}{data_list[1]:<15}{data_list[3]:<15}{data_list[2]:<15}")
六. 具体代码
github仓库链接:https://github.com/1StephenCurry1/Compiler-Design.git