用python+pyqt5手工编写一个含交互界面的简易的词法分析器

python+pyqt5手工编写一个含交互界面的简易词法分析器

@author:x1nge.

  • 编译原理基础实验

基础

在之前的一篇博文中我记录了一个不含交互界面的简易词法分析器程序编写内容 点击此处查看
在本文我将用pyqt5写一个简单的交互界面,也修改了部分代码使得程序更加完整。

具体实验分析

本文全部源码见本文末尾,上次编写的不含交互界面的源码也可点此处下载

  1. 交互界面可以用QtDesigner快速编写,或者自己写,我采用的是用可视化界面创建了一个大致的框架,然后再手动添加其他需要的控件,或者微调一些属性。
    我简单设计的交互界面如图所示:
    p1

有话说: 这边以C和C++为输入语言,其他语言有一些差别,可以自行修改代码。

  1. UI设计部分,主体代码由pyuic转换后自动获得,分析一下代码,会发现其实很简单,也便于我们之后修改代码或属性。
class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(694, 470)
        MainWindow.setFixedSize(694,470)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.text_input = QtWidgets.QTextEdit(self.centralwidget)
        self.text_input.setGeometry(QtCore.QRect(20, 40, 241, 351))
        self.text_input.setObjectName("text_input")
        self.btn_local = QtWidgets.QPushButton(self.centralwidget)
        self.btn_local.setGeometry(QtCore.QRect(20, 400, 101, 30))
        self.btn_local.setObjectName("btn_local")
        self.text_address = QtWidgets.QTextEdit(self.centralwidget)
        self.text_address.setGeometry(QtCore.QRect(136, 400, 396, 30))
        self.text_address.setObjectName("text_address")
        self.btn_get = QtWidgets.QPushButton(self.centralwidget)
        self.btn_get.setGeometry(QtCore.QRect(556, 400, 126, 30))
        self.btn_get.setObjectName("btn_get")
        self.btn_clear_address = QtWidgets.QPushButton(self.centralwidget)
        self.btn_clear_address.setGeometry(QtCore.QRect(570, 360, 101, 26))
        self.btn_clear_address.setObjectName("btn_clear_address")
        self.lb_text = QtWidgets.QLabel(self.centralwidget)
        self.lb_text.setGeometry(QtCore.QRect(20, 20, 91, 16))
        self.lb_text.setObjectName("lb_text")
        self.rbtn_java = QtWidgets.QRadioButton(self.centralwidget)
        self.rbtn_java.setGeometry(QtCore.QRect(570, 90, 115, 19))
        self.rbtn_java.setObjectName("rbtn_java")
        self.rbtn_java.setEnabled(False)
        self.buttonGroup = QtWidgets.QButtonGroup(MainWindow)
        self.buttonGroup.setObjectName("buttonGroup")
        self.buttonGroup.addButton(self.rbtn_java)
        self.rbtn_python = QtWidgets.QRadioButton(self.centralwidget)
        self.rbtn_python.setEnabled(False)
        self.rbtn_python.setGeometry(QtCore.QRect(570, 121, 115, 19))
        self.rbtn_python.setObjectName("rbtn_python")
        self.buttonGroup.addButton(self.rbtn_python)
        self.rbtn_c = QtWidgets.QRadioButton(self.centralwidget)
        self.rbtn_c.setEnabled(True)
        self.rbtn_c.setGeometry(QtCore.QRect(570, 150, 115, 19))
        self.rbtn_c.setObjectName("rbtn_c")
        self.rbtn_c.setChecked(True)
        self.buttonGroup.addButton(self.rbtn_c)
        self.rbtn_cpp = QtWidgets.QRadioButton(self.centralwidget)
        self.rbtn_cpp.setGeometry(QtCore.QRect(570, 179, 115, 19))
        self.rbtn_cpp.setObjectName("rbtn_cpp")
        self.buttonGroup.addButton(self.rbtn_cpp)
        self.rbtn_html = QtWidgets.QRadioButton(self.centralwidget)
        self.rbtn_html.setEnabled(False)
        self.rbtn_html.setGeometry(QtCore.QRect(570, 211, 115, 19))
        self.rbtn_html.setObjectName("rbtn_html")
        self.buttonGroup.addButton(self.rbtn_html)
        self.lb_choice = QtWidgets.QLabel(self.centralwidget)
        self.lb_choice.setGeometry(QtCore.QRect(570, 60, 72, 15))
        self.lb_choice.setObjectName("lb_choice")
        self.text_output = QtWidgets.QTextEdit(self.centralwidget)
        self.text_output.setGeometry(QtCore.QRect(280, 40, 251, 351))
        self.text_output.setObjectName("text_output")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(280, 20, 72, 15))
        self.label.setObjectName("label")
        self.btn_run = QtWidgets.QPushButton(self.centralwidget)
        self.btn_run.setGeometry(QtCore.QRect(570, 240, 101, 26))
        self.btn_run.setObjectName("btn_run")
        self.lb_name = QtWidgets.QLabel(self.centralwidget)
        self.lb_name.setEnabled(True)
        self.lb_name.setGeometry(QtCore.QRect(650, 446, 51, 20))
        self.lb_name.setObjectName("lb_name")
        self.btn_clear_input = QtWidgets.QPushButton(self.centralwidget)
        self.btn_clear_input.setGeometry(QtCore.QRect(570, 279, 101, 26))
        self.btn_clear_input.setObjectName("btn_clear_input")
        self.btn_clear_output = QtWidgets.QPushButton(self.centralwidget)
        self.btn_clear_output.setGeometry(QtCore.QRect(570, 320, 101, 26))
        self.btn_clear_output.setObjectName("btn_clear_output")
        # MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        # MainWindow.setStatusBar(self.statusbar)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "LexicalAnalyzer"))
        self.lb_text.setText(_translate("MainWindow", "待分析代码:"))
        self.rbtn_java.setText(_translate("MainWindow", "JAVA"))
        self.rbtn_python.setText(_translate("MainWindow", "PYTHON"))
        self.rbtn_c.setText(_translate("MainWindow", "C"))
        self.rbtn_cpp.setText(_translate("MainWindow", "C++"))
        self.rbtn_html.setText(_translate("MainWindow", "HTML"))
        self.lb_choice.setText(_translate("MainWindow", "语言:"))
        self.label.setText(_translate("MainWindow", "输出:"))
        self.btn_run.setText(_translate("MainWindow", "分析"))
        self.lb_name.setText(_translate("MainWindow", "x1nge."))
        self.btn_clear_input.setText(_translate("MainWindow", "清空待分析"))
        self.btn_local.setText(_translate("MainWindow", "浏览"))
        self.text_address.setText(_translate("MainWindow", "可在此手动输入路径(目前支持txt文件)"))
        self.btn_clear_output.setText(_translate("MainWindow", "清空输出"))
        self.btn_clear_address.setText(_translate("MainWindow", "清空路径"))
        self.btn_get.setText(_translate("MainWindow", "手动获取路径文本"))
  1. 设计主体代码:

有话说: 接下来的部分涉及到一些监听事件以及旧代码的修改,同一个类的代码可能拆开分析,全部源码见下文

初始化:

class main_window(QtWidgets.QWidget,Ui_MainWindow):
    def __init__(self):
        super(main_window,self).__init__()
        self.setupUi(self)

        self.text_output.clear()

测试是否能够正常连接至数据库:

	try:
		check_client = pymongo.MongoClient("mongodb://localhost:27017/")
		check_db = check_client["PrincipleOfCompiler"]
		check_col = check_db["ReservedWord"]
	except:
		self.text_output.append("info:当前未连接至预设的mongodb保留字库,保留字将被识别为可以合法		定义的标识符或"
		                         "整常数\n--------------------------")

有话所: 这里用的是mongodb,做这个测试是为了告知用户如果未连接到保留字数据库的操作,因为在分析过程中查询出错会导致程序退出,所以设置了如果无法连接则默认为未查询到保留字。

设置监听:

 # 设置监听器
        self.btn_clear_input.clicked.connect(self.btn_clear_input_click)
        self.btn_clear_output.clicked.connect(self.btn_clear_output_click)
        self.btn_run.clicked.connect(self.btn_run_click)
        self.btn_local.clicked.connect(self.btn_openfile_click)
        self.btn_get.clicked.connect(self.btn_load_address_click)
        self.btn_clear_address.clicked.connect(self.btn_clear_address_click)

功能、监听函数编写:

    # 功能函数编写
    def btn_clear_input_click(self):
         self.text_input.clear()

    def btn_clear_output_click(self):
        self.text_output.clear()

	# 调用python函数浏览本地文件,读出txt文件内容并显示路径
    def btn_openfile_click(self):
        filename,_ = QFileDialog.getOpenFileName()
        self.text_address.setText(filename)
        text = open(filename,'r').read()
        self.text_input.setText(text)

	# 读取路径所指定的txt文件内容并显示到文本框内
    def btn_load_address_click(self):
        f = open(self.text_address.toPlainText(),'r')
        res = f.read()
        self.text_input.setText(res)
        f.close()

    def btn_clear_address_click(self):
        self.text_address.clear()

	# 分析按钮主体代码,这里添加了一个结束符防止越界产生的程序退出,分析结果将追加到输出框中
    def btn_run_click(self):
        res = self.text_input.toPlainText().replace('\n','').replace('\t','').replace('  ',' ')
        res_lst1 = list(res)
        res_lst1.append("\0")
        print(res)
        print(res_lst1)
        global p
        p = 0
        while p in range(len(res_lst1)):
            if res_lst1[p] == "\0":
                break
            temp_output = ','.join(check_code(res_lst1))
            self.text_output.append(temp_output)

主要分析功能函数编写:
该部分详细分析见上次发布的博文,文章开头也有提到。

p = 0 # 初始化
def check_code(res_lst):
    # 初始化
    result = []
    str_get = []
    ch = get_char(res_lst)
    new_ch = get_blank_ch(ch,res_lst)
    # 识别标识符
    if  new_ch.isalpha() or new_ch == '_' or new_ch == '$':
        str_get.append(new_ch)
        new_ch = get_char(res_lst)
        while new_ch.isalpha() or new_ch.isdigit() or new_ch == '_' or new_ch == '$':
            str_get.append(new_ch)
            new_ch = get_char(res_lst)
        retract_pointer()
        str_result = ''.join(str_get)
        code = is_reserved_word(str_result)
        if code == 0 :
            value = insert_identifier(str_result)
            result.append('2') # 这里使用2作为非保留字的标识符的种别编码
            result.append(value)
            return result
        else:
            result.append('1') # 这里使用1作为保留字的种别编码
            result.append(str_result) # 实验例子中value值为保留字本身
            """
            result.append('-') # 保留字无自身值
            """
            return result
    # 识别整常数
    elif new_ch.isdigit():
        str_get.append(new_ch)
        new_ch = get_char(res_lst)
        while new_ch.isdigit():
            str_get.append(new_ch)
            new_ch = get_char(res_lst)
        retract_pointer()
        str_result = ''.join(str_get)
        value = insert_constant(str_result)
        result.append('3') # 这里使用3作为整常数的种别编码
        result.append(value)
        return result
    #识别运算符
    elif new_ch == '=' or new_ch == '+' or new_ch == '-' or new_ch == '*' or new_ch == '/' or new_ch == '>'\
        or new_ch == '<' or new_ch == '!' or new_ch == '%':
        if new_ch == '>' or new_ch == '<' or new_ch == '!':
            str_get.append(new_ch)
            value = ''.join(new_ch)
            new_ch = get_char(res_lst)
            if new_ch == '=':
                str_get.append(new_ch)
                str_result = ''.join(str_get)
                result.append('4') # 这里使用4作为运算符的种别编码
                result.append(str_result)
                return result
            else:
                retract_pointer()
                result.append('4')
                result.append(value)
                return result
        elif new_ch == '*':
            str_get.append(new_ch)
            value = ''.join(new_ch)
            new_ch = get_char(res_lst)
            if new_ch == '*':
                str_get.append(new_ch)
                str_result = ''.join(str_get)
                result.append('4')
                result.append(str_result)
                return result
            else:
                retract_pointer()
                result.append('4')
                result.append(value)
                return result
        else:
            value = ''.join(new_ch)
            result.append('4')
            result.append(value)
            return  result
    # 识别分隔符
    elif new_ch == ',' or new_ch == ';' or new_ch == '{' or new_ch == '}' or new_ch == '(' or new_ch == ')':
        value = ''.join(new_ch)
        result.append('5') # 这里使用5作为分隔符的种别编码
        result.append(value)
        return result
    else:
        result.append("Error.")
        return result

# 把下一个字符读入到new_ch中
def get_char(res_lst):
    global p
    temp_ch = res_lst[p]
    p += 1
    return temp_ch

# 跳过空白符直至ch读入一个非空白符
def get_blank_ch(temp_ch_1,res_lst):
    if temp_ch_1 == ' ':
        temp_ch_2 = get_char(res_lst)
        return temp_ch_2
    return temp_ch_1

# 把ch中的字符连接到str_get之后
def ch_append():
    #直接调用python函数
    return

# 查找保留字表中是否有str_get,若存在则返回1,否则返回0
def is_reserved_word( str_result ):
    try:
        check_client = pymongo.MongoClient("mongodb://localhost:27017/")
        check_db = check_client["PrincipleOfCompiler"]
        check_col = check_db["ReservedWord"]
        check_query = {"content" : str_result}
        for get_text in check_col.find(check_query):
            # 判断匹配到的get_text是否为空,若不为空则要匹配的字符串在保留字表中找到
            if any(get_text):
                check_client.close()
                return 1
        """
        check_doc = check_col.find(check_query)
        print(check_doc)
        for res in check_doc:
            print(res)
        """
        check_client.close()
    except:
        return 0
    return 0

# 将搜索指针回调一个字符位置
def retract_pointer():
    global p
    p -= 1
    return

# 若识别为标识符,将str_result中的标识符插入符号表并返回符号表指针
def insert_identifier( str_result ):
    return str_result

# 若识别为常数,将str_result中的常数插入常数表并返回参数表指针
def insert_constant( str_result ):
    return str(bin(int(str_result)))

其他:

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    main_show = main_window()
    main_show.show()
    sys.exit(app.exec())

运行截图

p2
p3
p4

总结

  • 同步更新至CSDN,仅作实验记录之用。
  • 顺带小小一提,python生成可执行的exe文件:

安装pyinstaller

pip3 install pyinstaller

这里的-F是指打包生成一个文件,-w是不显示控制台,适合有GUI界面,控制台日志输出又不是很重要的程序。执行完成后,可以在输出信息中找到文件的输出位置。

pyinstaller -F -w demo_lexical_analyzer.py

源码

# -*- coding: utf-8 -*-

# Form implementation generated from reading ui file 'demo_lexical_analyzer.ui'
#
# Created by: PyQt5 UI code generator 5.13.2
#
# WARNING! All changes made in this file will be lost!
from tkinter import messagebox

from PyQt5 import QtCore, QtGui, QtWidgets
import sys,pymongo

from PyQt5.QtWidgets import QFileDialog

class Ui_MainWindow(object):
    def setupUi(self, MainWindow):
        MainWindow.setObjectName("MainWindow")
        MainWindow.resize(694, 470)
        MainWindow.setFixedSize(694,470)
        self.centralwidget = QtWidgets.QWidget(MainWindow)
        self.centralwidget.setObjectName("centralwidget")
        self.text_input = QtWidgets.QTextEdit(self.centralwidget)
        self.text_input.setGeometry(QtCore.QRect(20, 40, 241, 351))
        self.text_input.setObjectName("text_input")
        self.btn_local = QtWidgets.QPushButton(self.centralwidget)
        self.btn_local.setGeometry(QtCore.QRect(20, 400, 101, 30))
        self.btn_local.setObjectName("btn_local")
        self.text_address = QtWidgets.QTextEdit(self.centralwidget)
        self.text_address.setGeometry(QtCore.QRect(136, 400, 396, 30))
        self.text_address.setObjectName("text_address")
        self.btn_get = QtWidgets.QPushButton(self.centralwidget)
        self.btn_get.setGeometry(QtCore.QRect(556, 400, 126, 30))
        self.btn_get.setObjectName("btn_get")
        self.btn_clear_address = QtWidgets.QPushButton(self.centralwidget)
        self.btn_clear_address.setGeometry(QtCore.QRect(570, 360, 101, 26))
        self.btn_clear_address.setObjectName("btn_clear_address")
        self.lb_text = QtWidgets.QLabel(self.centralwidget)
        self.lb_text.setGeometry(QtCore.QRect(20, 20, 91, 16))
        self.lb_text.setObjectName("lb_text")
        self.rbtn_java = QtWidgets.QRadioButton(self.centralwidget)
        self.rbtn_java.setGeometry(QtCore.QRect(570, 90, 115, 19))
        self.rbtn_java.setObjectName("rbtn_java")
        self.rbtn_java.setEnabled(False)
        self.buttonGroup = QtWidgets.QButtonGroup(MainWindow)
        self.buttonGroup.setObjectName("buttonGroup")
        self.buttonGroup.addButton(self.rbtn_java)
        self.rbtn_python = QtWidgets.QRadioButton(self.centralwidget)
        self.rbtn_python.setEnabled(False)
        self.rbtn_python.setGeometry(QtCore.QRect(570, 121, 115, 19))
        self.rbtn_python.setObjectName("rbtn_python")
        self.buttonGroup.addButton(self.rbtn_python)
        self.rbtn_c = QtWidgets.QRadioButton(self.centralwidget)
        self.rbtn_c.setEnabled(True)
        self.rbtn_c.setGeometry(QtCore.QRect(570, 150, 115, 19))
        self.rbtn_c.setObjectName("rbtn_c")
        self.rbtn_c.setChecked(True)
        self.buttonGroup.addButton(self.rbtn_c)
        self.rbtn_cpp = QtWidgets.QRadioButton(self.centralwidget)
        self.rbtn_cpp.setGeometry(QtCore.QRect(570, 179, 115, 19))
        self.rbtn_cpp.setObjectName("rbtn_cpp")
        self.buttonGroup.addButton(self.rbtn_cpp)
        self.rbtn_html = QtWidgets.QRadioButton(self.centralwidget)
        self.rbtn_html.setEnabled(False)
        self.rbtn_html.setGeometry(QtCore.QRect(570, 211, 115, 19))
        self.rbtn_html.setObjectName("rbtn_html")
        self.buttonGroup.addButton(self.rbtn_html)
        self.lb_choice = QtWidgets.QLabel(self.centralwidget)
        self.lb_choice.setGeometry(QtCore.QRect(570, 60, 72, 15))
        self.lb_choice.setObjectName("lb_choice")
        self.text_output = QtWidgets.QTextEdit(self.centralwidget)
        self.text_output.setGeometry(QtCore.QRect(279, 40, 251, 351))
        self.text_output.setObjectName("text_output")
        self.label = QtWidgets.QLabel(self.centralwidget)
        self.label.setGeometry(QtCore.QRect(279, 20, 72, 15))
        self.label.setObjectName("label")
        self.btn_run = QtWidgets.QPushButton(self.centralwidget)
        self.btn_run.setGeometry(QtCore.QRect(570, 240, 101, 26))
        self.btn_run.setObjectName("btn_run")
        self.lb_name = QtWidgets.QLabel(self.centralwidget)
        self.lb_name.setEnabled(True)
        self.lb_name.setGeometry(QtCore.QRect(650, 446, 51, 20))
        self.lb_name.setObjectName("lb_name")
        self.btn_clear_input = QtWidgets.QPushButton(self.centralwidget)
        self.btn_clear_input.setGeometry(QtCore.QRect(570, 279, 101, 26))
        self.btn_clear_input.setObjectName("btn_clear_input")
        self.btn_clear_output = QtWidgets.QPushButton(self.centralwidget)
        self.btn_clear_output.setGeometry(QtCore.QRect(570, 321, 101, 26))
        self.btn_clear_output.setObjectName("btn_clear_output")
        # MainWindow.setCentralWidget(self.centralwidget)
        self.statusbar = QtWidgets.QStatusBar(MainWindow)
        self.statusbar.setObjectName("statusbar")
        # MainWindow.setStatusBar(self.statusbar)
        self.retranslateUi(MainWindow)
        QtCore.QMetaObject.connectSlotsByName(MainWindow)

    def retranslateUi(self, MainWindow):
        _translate = QtCore.QCoreApplication.translate
        MainWindow.setWindowTitle(_translate("MainWindow", "LexicalAnalyzer"))
        self.lb_text.setText(_translate("MainWindow", "待分析代码:"))
        self.rbtn_java.setText(_translate("MainWindow", "JAVA"))
        self.rbtn_python.setText(_translate("MainWindow", "PYTHON"))
        self.rbtn_c.setText(_translate("MainWindow", "C"))
        self.rbtn_cpp.setText(_translate("MainWindow", "C++"))
        self.rbtn_html.setText(_translate("MainWindow", "HTML"))
        self.lb_choice.setText(_translate("MainWindow", "语言:"))
        self.label.setText(_translate("MainWindow", "输出:"))
        self.btn_run.setText(_translate("MainWindow", "分析"))
        self.lb_name.setText(_translate("MainWindow", "x1nge."))
        self.btn_clear_input.setText(_translate("MainWindow", "清空待分析"))
        self.btn_local.setText(_translate("MainWindow", "浏览"))
        self.text_address.setText(_translate("MainWindow", "可在此手动输入路径(目前支持txt文件)"))
        self.btn_clear_output.setText(_translate("MainWindow", "清空输出"))
        self.btn_clear_address.setText(_translate("MainWindow", "清空路径"))
        self.btn_get.setText(_translate("MainWindow", "手动获取路径文本"))

class main_window(QtWidgets.QWidget,Ui_MainWindow):
    def __init__(self):
        super(main_window,self).__init__()
        self.setupUi(self)

        self.text_output.clear()

        try:
            check_client = pymongo.MongoClient("mongodb://localhost:27017/")
            check_db = check_client["PrincipleOfCompiler"]
            check_col = check_db["ReservedWord"]
        except:
            self.text_output.append("info:当前未连接至预设的mongodb保留字库,保留字将被识别为可以合法定义的标识符或"
                                    "整常数\n--------------------------")

        # 设置监听器
        self.btn_clear_input.clicked.connect(self.btn_clear_input_click)
        self.btn_clear_output.clicked.connect(self.btn_clear_output_click)
        self.btn_run.clicked.connect(self.btn_run_click)
        self.btn_local.clicked.connect(self.btn_openfile_click)
        self.btn_get.clicked.connect(self.btn_load_address_click)
        self.btn_clear_address.clicked.connect(self.btn_clear_address_click)

    # 功能函数编写
    def btn_clear_input_click(self):
         self.text_input.clear()

    def btn_clear_output_click(self):
        self.text_output.clear()

    def btn_openfile_click(self):
        filename,_ = QFileDialog.getOpenFileName()
        self.text_address.setText(filename)
        text = open(filename,'r').read()
        self.text_input.setText(text)

    def btn_load_address_click(self):
        f = open(self.text_address.toPlainText(),'r')
        res = f.read()
        self.text_input.setText(res)
        f.close()

    def btn_clear_address_click(self):
        self.text_address.clear()

    def btn_run_click(self):
        res = self.text_input.toPlainText().replace('\n','').replace('\t','').replace('  ',' ')
        res_lst1 = list(res)
        res_lst1.append("\0")
        print(res)
        print(res_lst1)
        global p
        p = 0
        while p in range(len(res_lst1)):
            if res_lst1[p] == "\0":
                break
            temp_output = ','.join(check_code(res_lst1))
            self.text_output.append(temp_output)

p = 0 # 初始化
def check_code(res_lst):
    # 初始化
    result = []
    str_get = []
    ch = get_char(res_lst)
    new_ch = get_blank_ch(ch,res_lst)
    # 识别标识符
    if  new_ch.isalpha() or new_ch == '_' or new_ch == '$':
        str_get.append(new_ch)
        new_ch = get_char(res_lst)
        while new_ch.isalpha() or new_ch.isdigit() or new_ch == '_' or new_ch == '$':
            str_get.append(new_ch)
            new_ch = get_char(res_lst)
        retract_pointer()
        str_result = ''.join(str_get)
        code = is_reserved_word(str_result)
        if code == 0 :
            value = insert_identifier(str_result)
            result.append('2') # 这里使用2作为非保留字的标识符的种别编码
            result.append(value)
            return result
        else:
            result.append('1') # 这里使用1作为保留字的种别编码
            result.append(str_result) # 实验例子中value值为保留字本身
            """
            result.append('-') # 保留字无自身值
            """
            return result
    # 识别整常数
    elif new_ch.isdigit():
        str_get.append(new_ch)
        new_ch = get_char(res_lst)
        while new_ch.isdigit():
            str_get.append(new_ch)
            new_ch = get_char(res_lst)
        retract_pointer()
        str_result = ''.join(str_get)
        value = insert_constant(str_result)
        result.append('3') # 这里使用3作为整常数的种别编码
        result.append(value)
        return result
    #识别运算符
    elif new_ch == '=' or new_ch == '+' or new_ch == '-' or new_ch == '*' or new_ch == '/' or new_ch == '>'\
        or new_ch == '<' or new_ch == '!' or new_ch == '%':
        if new_ch == '>' or new_ch == '<' or new_ch == '!':
            str_get.append(new_ch)
            value = ''.join(new_ch)
            new_ch = get_char(res_lst)
            if new_ch == '=':
                str_get.append(new_ch)
                str_result = ''.join(str_get)
                result.append('4') # 这里使用4作为运算符的种别编码
                result.append(str_result)
                return result
            else:
                retract_pointer()
                result.append('4')
                result.append(value)
                return result
        elif new_ch == '*':
            str_get.append(new_ch)
            value = ''.join(new_ch)
            new_ch = get_char(res_lst)
            if new_ch == '*':
                str_get.append(new_ch)
                str_result = ''.join(str_get)
                result.append('4')
                result.append(str_result)
                return result
            else:
                retract_pointer()
                result.append('4')
                result.append(value)
                return result
        else:
            value = ''.join(new_ch)
            result.append('4')
            result.append(value)
            return  result
    # 识别分隔符
    elif new_ch == ',' or new_ch == ';' or new_ch == '{' or new_ch == '}' or new_ch == '(' or new_ch == ')':
        value = ''.join(new_ch)
        result.append('5') # 这里使用5作为分隔符的种别编码
        result.append(value)
        return result
    else:
        result.append("Error.")
        return result

# 把下一个字符读入到new_ch中
def get_char(res_lst):
    global p
    temp_ch = res_lst[p]
    p += 1
    return temp_ch

# 跳过空白符直至ch读入一个非空白符
def get_blank_ch(temp_ch_1,res_lst):
    if temp_ch_1 == ' ':
        temp_ch_2 = get_char(res_lst)
        return temp_ch_2
    return temp_ch_1

# 把ch中的字符连接到str_get之后
def ch_append():
    #直接调用python函数
    return

# 查找保留字表中是否有str_get,若存在则返回1,否则返回0
def is_reserved_word( str_result ):
    try:
        check_client = pymongo.MongoClient("mongodb://localhost:27017/")
        check_db = check_client["PrincipleOfCompiler"]
        check_col = check_db["ReservedWord"]
        check_query = {"content" : str_result}
        for get_text in check_col.find(check_query):
            # 判断匹配到的get_text是否为空,若不为空则要匹配的字符串在保留字表中找到
            if any(get_text):
                check_client.close()
                return 1
        """
        check_doc = check_col.find(check_query)
        print(check_doc)
        for res in check_doc:
            print(res)
        """
        check_client.close()
    except:
        return 0
    return 0

# 将搜索指针回调一个字符位置
def retract_pointer():
    global p
    p -= 1
    return

# 若识别为标识符,将str_result中的标识符插入符号表并返回符号表指针
def insert_identifier( str_result ):
    return str_result

# 若识别为常数,将str_result中的常数插入常数表并返回参数表指针
def insert_constant( str_result ):
    return str(bin(int(str_result)))

if __name__ == '__main__':
    app = QtWidgets.QApplication(sys.argv)
    main_show = main_window()
    main_show.show()
    sys.exit(app.exec())
  • 2
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: 基于PythonPyQt5和MySQL的GUI学生管理系统项目是一个帮助学校、教师和学生进行学生信息管理和查询的应用程序。 该系统具有以下功能: 1. 学生信息管理:可以添加、编辑和删除学生的基本信息,如姓名、性别、年龄、班级等。 2. 成绩管理:可以记录和统计学生的课程成绩,包括考试成绩、作业成绩等,并可以按照学期和科目进行查询和统计。 3. 学生出勤管理:可以记录学生的出勤情况,包括请假、缺勤等,并可以查看学生的出勤统计信息。 4. 班级管理:可以添加、编辑和删除班级的信息,并可以将学生分配到不同的班级中。 5. 查询功能:可以根据学号、姓名、班级等条件进行学生信息和成绩的查询,并可以进行排序和筛选。 6. 用户权限管理:可以设置不同用户的权限,如管理员、教师、学生等,不同用户有不同的操作权限。 该系统使用Python作为开发语言,PyQt5作为图形用户界面库进行界面设计和开发,MySQL作为数据库存储学生信息和成绩。通过连接MySQL数据库,实现数据的存储和查询功能,通过PyQt5提供的界面组件,实现用户交互界面显示。 这个项目的开发过程中,需要使用PyQt5提供的各种界面组件进行界面的设计和布局,使用MySQL连接器库实现与MySQL数据库的连接和数据操作,同时还需要使用Python的面向对象编程思想设计和实现各种功能模块。 通过该学生管理系统,学校和教师可以方便地管理和查询学生信息和成绩,提高工作效率和减少人力成本。同时,学生也可以通过系统查询自己的信息和成绩,帮助他们更好地了解自己的学习情况。 ### 回答2: 基于PythonPyQt5的MySQL GUI学生管理系统项目主要包括以下功能和模块: 1. 用户登录和权限控制:系统需要提供用户登录功能,根据用户的角色进行权限控制,例如管理员和普通用户。 2. 学生信息管理:包括学生的个人基本信息管理,例如学生姓名、性别、年龄、学号等。可以进行增加、删除、修改和查询等操作。 3. 课程管理:包括课程的添加、删除、修改和查询等操作。可以将课程分配给学生,记录学生的选课情况。 4. 成绩管理:可以录入学生的成绩,并可进行查询和统计。可以按照课程和学生进行成绩的录入和查询。 5. 教师管理:包括教师的基本信息管理,例如教师姓名、性别、工号等。可以进行增加、删除、修改和查询操作。 6. 班级管理:可以创建和管理班级的信息,例如班级号、班级人数等。可以对班级进行增加、删除、修改和查询操作。 7. 数据库连接与操作:通过PyQt5连接MySQL数据库,并实现数据库表的创建和数据的存储和读取。 8. 用户界面设计:使用PyQt5的图形界面库进行用户界面的设计,包括各项功能的菜单栏、工具栏和表格等展示。 9. 数据统计和报表输出:可以对学生的成绩进行统计和分析,并支持将统计结果导出为报表文件或打印出来。 通过以上功能和模块的实现,基于PythonPyQt5的MySQL GUI学生管理系统项目可以实现学生信息、课程、成绩、教师和班级等信息的管理,方便学校或教育机构进行学生管理工作的自动化处理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

x1Nge.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值