用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())

你可能感兴趣的:(学习记录,python)