设计与实现一个简单词法分析。具体内容是产生一个二元式文本文件,扩展名为dyd,可将Java或C程序(测试程序)分解成为一个一个的单词及类型。
(选做:并查“单词符号与种别对照表”得出其种别,用一数字表示。)
词法编译器基本功能包括:
(1) 输入源程序:输入C/java源程序;
(2) 输出单词,输出形式为:(序号,类型,单词);
(3) 输出出错信息,输出形式为:(出错行号,出错列号,出错信息);
为了运行代码并进行实验,需要满足以下条件:
1.Python环境:确保计算机上安装了Python,并且可以在命令行中运行python命令。
2.输入源程序文件:创建一个名为input.java或input.c的文件,其中包含想要进行词法分析的Java/C源程序。确保源程序的语法是正确的,否则可能会导致词法分析错误。
3.下载依赖:下载需要的依赖库。
4.查看输出文件:运行成功后,将生成一个名为output.dyd的文件,其中包含了词法分析的结果,包括单词及其类型的二元式信息。
词法分析器源程序文件:(lexer.py)
import re
import tkinter as tk
from tkinter import filedialog# 定义单词种别码
KEYWORD = 1
IDENTIFIER = 10
CONSTANT = 11
OPERATOR = 4
DELIMITER = 5# 定义关键字列表
keywords = ["if", "int", "for", "while", "do", "return", "break", "continue"]class LexicalAnalyzer:def __init__(self, window):# 窗口设置self.window = windowself.window.title("词法分析器")self.window.geometry("500x500")# 顶部文件选择与运行控制区域self.top_frame = tk.Frame(self.window)self.top_frame.pack(side=tk.TOP, pady=10, padx=10)# 文件选择按钮self.select_file_button = tk.Button(self.top_frame, text="选择文件", command=self.select_file)self.select_file_button.pack(side=tk.LEFT)# 运行按钮self.run_button = tk.Button(self.top_frame, text="运行", state=tk.DISABLED, command=self.run_analysis)self.run_button.pack(side=tk.RIGHT)# 中间的文本显示框self.text_frame = tk.Frame(self.window)self.text_frame.pack(pady=10)self.scrollbar = tk.Scrollbar(self.text_frame)self.scrollbar.pack(side=tk.RIGHT, fill=tk.Y)self.display_area = tk.Text(self.text_frame, wrap=tk.WORD, yscrollcommand=self.scrollbar.set)self.display_area.pack(side=tk.LEFT, fill=tk.BOTH)self.scrollbar.config(command=self.display_area.yview)# 底部状态栏区域self.status_bar = tk.Frame(self.window)self.status_bar.pack(side=tk.BOTTOM, pady=10)self.status_label = tk.Label(self.status_bar, text="请选择一个文件")self.status_label.pack()# 初始化属性self.input_file = Noneself.tokens = []def select_file(self):self.input_file = filedialog.askopenfilename(filetypes=[("C源程序", "*.c"), ("文本", "*.txt"), ("所有文件", "*.*")])if self.input_file:self.status_label.config(text=f"已选择文件:{self.input_file}")self.run_button.config(state=tk.NORMAL)def run_analysis(self):if not self.input_file:returnself.status_label.config(text="运行中,请稍候...")self.window.update()with open(self.input_file, 'r', encoding='utf-8') as file:lines = file.readlines()token_count = 0error_count = 0self.tokens.clear()for line_number, line in enumerate(lines, start=1):words = re.findall(r'[a-zA-Z_][a-zA-Z0-9_]*|\d+|&&|\|\||==|>=|<=|!=|[+\-*/=><,;(){}]', line)column_number = 1for word in words:category = classify_token(word)if category != -1:self.tokens.append((line_number, column_number, category, word))token_count += 1else:self.display_area.insert(tk.END, f'Invalid token: {word} at Line {line_number}, Column {column_number}\n')error_count += 1column_number += len(word) + 1if error_count == 0:self.status_label.config(text=f"词法分析完成,共生成 {token_count} 个二元式。")self.display_tokens()self.save_results() # 保存结果到文件中else:self.status_label.config(text=f"词法分析失败,请查看输出窗口。")def display_tokens(self):self.display_area.delete('1.0', tk.END)for token in self.tokens:line_number, column_number, category, word = tokenself.display_area.insert(tk.END, f'({line_number},{column_number})\t{category}\t{word}\n')def save_results(self):output_file = filedialog.asksaveasfilename(defaultextension=".dyd", filetypes=[("二元式文件", "*.dyd")])if output_file:with open(output_file, 'w', encoding='utf-8') as file:for token in self.tokens:line_number, column_number, category, word = tokenfile.write(f"{line_number}\t{column_number}\t{category}\t{word}\n")self.status_label.config(text=f"结果已保存至文件:{output_file}")def show(self):self.window.mainloop()# 判断单词种别函数
def classify_token(word):if word in keywords:return KEYWORDelif re.match(r'^[a-zA-Z_][a-zA-Z0-9_]*$', word):return IDENTIFIERelif re.match(r'^\d+$', word):return CONSTANTelif word in ['+', '-', '*', '/', '=', '>', '<', '==', '>=', '<=', '!=', '&&', '||']:return OPERATORelif word in [',', ';', '(', ')', '{', '}']:return DELIMITERelse:return -1 # 无法分类的单词种别码if __name__ == '__main__':window = tk.Tk()analyzer = LexicalAnalyzer(window)analyzer.show()
运行结果: