900字范文,内容丰富有趣,生活中的好帮手!
900字范文 > 编译原理——Python实现C语言词法分析器

编译原理——Python实现C语言词法分析器

时间:2020-02-11 23:36:03

相关推荐

编译原理——Python实现C语言词法分析器

编译原理——Python实现C语言词法分析器

程序采用pyside2进行交互界面设计,需要下载相应的库

运行效果

代码

from PySide2.QtWidgets import QApplication, QMessageBox, QFileDialogfrom PySide2.QtUiTools import QUiLoaderimport osclass Main:#c语言关键字,运算符,界符key_word=['auto','break','case','char','const','continue','default','do','double','else','enum','extern','float','for','goto','if','int','long','register','return','short','signed','sizeof','static','struct','switch','typedef','union','unsigned','void','volatile','while']delimiters = ['{', '}', '[', ']', '(', ')', '.', ',', ':', ';']operator = ['+', '-', '*', '/',':=', '<', '<>', '<=', '>', '>=', '=', '==','&','++','--']#词法错误计数error_count = 0len_key = len(key_word)len_del = len(delimiters)len_ope = len(operator)#存放分析所有结果all_list = []def __init__(self):# 从文件中加载UI定义# 从 UI 定义中动态 创建一个相应的窗口对象# 注意:里面的控件对象也成为窗口对象的属性了# 比如 self.ui.button , self.ui.textEditself.ui = QUiLoader().load('main.ui')#多行文本框提示内容self.ui.starttxt.setPlaceholderText('请在这里输入代码')# 为菜单创建链接self.ui.open.triggered.connect(self.openFile)self.ui.save.triggered.connect(self.saveFile)self.ui.exit.triggered.connect(self.exitFile)self.ui.allow_ed.triggered.connect(self.allow_ed)self.ui.refuse_ed.triggered.connect(self.refuse_ed)self.ui.words_an.triggered.connect(self.words_an)# self.ui.nfa.triggered.connect(self.NFA)def openFile(self):#打开文件# 选中文件,返回路径filePath = QFileDialog.getOpenFileName(self.ui, "选择文件路径")#若打开文件位置为空,返回if filePath[0]=='':returnelse:f = open(filePath[0], 'r', encoding='utf8')message=f.read()f.close()# 将读取文件内容放入多行文本框self.ui.starttxt.setPlainText(message)def saveFile(self):#保存文件ans1= self.ui.end1.toPlainText()ans2= self.ui.end2.toPlainText()# 返回文件存储路径dirpath = QFileDialog.getSaveFileName(self.ui,'文件存储路径')#若存储文件位置为空if dirpath[0]=="":returnelse:f =open(dirpath[0],'w+',encoding='utf8')f.write(ans1)f.write('\n'+ans2)f.close()def exitFile(self):exit(app.exec_())def allow_ed(self):self.ui.starttxt.setEnabled(True)def refuse_ed(self):self.ui.starttxt.setEnabled(False)# def NFA(self):#os.system("python NFA.py")def words_an(self):#读取内容到texttext = self.ui.starttxt.toPlainText()#在词法分析之前将上次词法分析的内容清空self.all_list.clear()self.ui.end1.clear()self.ui.end2.clear()for line in text.splitlines():word = ''word_line = []i = 0#循环将字符串读入word,遇到界符或者运算符停下开始判断while i < len(line):word += line[i]if line[i] == ' ' or line[i] in self.delimiters or line[i] in self.operator:#当word以英文字母,‘$’,‘_’开头时,判断是关键字还是标识符if word[0].isalpha() or word[0] == '$' or word[0] == '_':word = word[:-1]if word in self.key_word:# 关键字# 将关键字及关键字在关键字列表中的位置以字典形式存放在word_line列表中word_line.append({word: self.key_word.index(word)})else:# 标识符# 标识符位置置零同样以字典形式存放在word_line中word_line.append({word: 0})# 常数elif word[:-1].isdigit():#常数中出现小数点,进行小数的判断sign =0if line[i]=='.':i =i+1word2 =''#从小数点后循环读入,直至遇到空格,运算符或界符停止,小数部分读完while True:word2+=line[i]#当小数点后仍然出现小数点时,此时应该出现错误if line[i]=='.':sign =1i=i+1continueif line[i] == ' ' or line[i] in self.delimiters or line[i] in self.operator:word =word+word2breaki =i+1if sign==0:#将小数以字典形式加入列表word_line.append({word[:-1]: -1})else:word_line.append({word[:-1]: -3})#错误的小数else:word_line.append({word[:-1]: -1})# 不合法标识符elif word[:-1]!='':word_line.append({word[:-1]:-2})self.error_count = self.error_count+1# 字符是界符if line[i] in self.delimiters:word_line.append({line[i]: self.len_key + self.delimiters.index(line[i])})# 字符是运算符elif line[i] in self.operator:s = line[i] + line[i + 1]#两位运算符if s in self.operator:word_line.append({s: self.len_key + self.len_del + self.operator.index(s)})i += 1#单位运算符else:word_line.append({line[i]: self.len_key + self.len_del + self.operator.index(line[i])})#每判断一个单词,word置为空word = ''i += 1self.all_list.append(word_line)#将单词信息存放在word_line列表中#将判断的信息打印在控制台for i in range(len(self.all_list)):print(self.all_list[i])self.show()def circle(self):passdef show(self):self.ui.end1.append('-----------------------------------------------')self.ui.end1.append('行号'+' '+'单词'+' '+'类型'+' '+'是否合法'+' '+'单词码'+' ')self.ui.end1.append('-----------------------------------------------')self.ui.end2.append(str(self.error_count)+' errors')#显示完毕后,错误计数归零self.error_count = 0self.ui.end2.append('-----------------------------------------------')#循环遍历列表,判断每个单词的类型和是否合法for i in range(len(self.all_list)):l = len(self.all_list[i])for j in range(l):leixing = ''hefa = ''#number为存储单词的单词码,words为该单词number =list(self.all_list[i][j].values())[0]words =list(self.all_list[i][j].keys())[0]if 0< number <=self.len_key:leixing = '保留字'hefa ='合法'elif self.len_key< number <=self.len_key+self.len_del:leixing = '界符'hefa = '合法'elif self.len_key+self.len_del< number <=self.len_key+self.len_del+self.len_ope:leixing = '运算符'hefa = '合法'elif number==0:leixing ='标识符'hefa = '合法'elif number==-1:leixing = '常数'hefa = '合法'elif number==-2:leixing ='标识符'hefa ='不合法'elif number==-3:leixing ='常数'hefa ='不合法'if hefa =='合法':self.ui.end1.append("{:<6}{:<6}{:<8}{:<7}{:<5}".format(i+1,words,leixing,hefa,number))else:self.ui.end1.append("{:<6}{:<6}{:<8}{:<7}{:<5}{}".format(i+1, words, leixing, hefa, number,'<-错误行'))if number==-2:self.ui.end2.append("{:<6}{:<6}{:<10}".format(i+1,words,'标识符命名错误'))elif number==-3:self.ui.end2.append("{:<6}{:<6}{:<10}".format(i + 1, words, '常数命名错误'))app = QApplication([])start = Main()start.ui.show()app.exec_()

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。