前言
okey,到这里的话,就要到尾声了。当然这里要说明的是,这个项目也是基于这个项目 进行的二次开发,然后我按照自己的理解进行说明改动。当然项目本身比较简单,所以只花了差不多三天的时间搞懂了。那么到后期有时间的话,我会给它引入对象类型,更高级的内置函数。这一点主要是因为实现起来确实更复杂,有更多的语法规则和细节要处理。不过对于这一部分功能我并不着急,后期慢慢实现就可以,作为毕设的话,这个也只是第一部分,还有后面的部分。没办法还有一个身份,Java全干工程师。
中英文双语法
okey,那么废话不多说,我们直接开始吧,这个的话,昨天想了一坤时,觉得,既然是中文编程,但是这个中文有时候太别扭了,所以直接那是支持中英文吧。
所以在这里的话,对关键字做了处理:
首先是定义这个新的的关键字
在这里的的话,定义了新的这个关键字,和标点符号。然后重新里面比较和contains方法。
class KeyWord:
def __init__(self,ek,ck):
self.ex = ek
self.ck = ck
def __contains__(self, value):
# 如果value等于ex或ck中的任意一个,返回True;否则返回False
return value == self.ex or value == self.ck
def __eq__(self, other):
# 如果ex或ck有一个相等,则两个对象相等
return self.ex == other.ex or self.ck == other.ck
def __ne__(self, other):
# 如果ex和ck都不相等,则两个对象不相等
return not (self.ex == other.ex or self.ck == other.ck)
class Punctuation:
def __init__(self,ep,cp):
self.ep = ep
self.cp = cp
def __contains__(self, value):
return value == self.ep or value == self.cp
def __eq__(self, other):
return self.ep == other.ep or self.cp == other.cp
def __ne__(self, other):
return not (self.ep == other.ep or self.cp == other.cp)
这样一来的话,对于这个符号,和关键字就可以做到很好地比对了,实现效果的话,就是可以这样编程:
然后的话,是定义这个:
PUNCTUATIONS = {
',':Punctuation(',',','),
'(':Punctuation('(','('),
')':Punctuation(')',')'),
'[':Punctuation('[','【'),
']':Punctuation(']','】'),
';':Punctuation(';',';'),
}
KEYWORDSEC = {
'var':KeyWord('var','设'),
'设':KeyWord('var','设'),
'and':KeyWord('and','且'),
'且':KeyWord('and','且'),
'or':KeyWord('or','或'),
'或':KeyWord('or','或'),
'not':KeyWord('not','否'),
'否':KeyWord('not','否'),
'if':KeyWord('if','如果'),
'如果':KeyWord('if','如果'),
'elif':KeyWord('elif','再者'),
'再者':KeyWord('elif','再者'),
'else':KeyWord('else','不然'),
'不然':KeyWord('else','不然'),
'for':KeyWord('for','遍历'),
'遍历':KeyWord('for','遍历'),
'to':KeyWord('to','到'),
'到':KeyWord('to','到'),
'step':KeyWord('step','步长'),
'步长':KeyWord('step','步长'),
'while':KeyWord('while','循环'),
'循环':KeyWord('while','循环'),
'fun':KeyWord('fun','函数'),
'函数':KeyWord('fun','函数'),
'then':KeyWord('then','就'),
'就':KeyWord('then','就'),
'end':KeyWord('end','结束'),
'结束':KeyWord('end','结束'),
'return':KeyWord('return','返回'),
'返回':KeyWord('return','返回'),
'continue':KeyWord('continue','继续'),
'继续':KeyWord('continue','继续'),
'break':KeyWord('break','终止'),
'终止':KeyWord('break','终止'),
}
KEYWORDS = [
'var',
'设',
'and',
'且',
'or',
'或',
'not',
'否',
'if',
'如果',
'elif',
'再者',
'else',
'不然',
'for',
'遍历',
'to',
'到',
'step',
'步长',
'while',
'循环',
'fun',
'函数',
'then',
'就',
'end',
'结束',
'return',
'返回',
'continue',
'继续',
'break',
'终止'
]
这里需要把前面的关键字都这样改过来。
不过这里注意的是,我们的这些内置函数的话,还是英文的,主要是如果也要改成中文的话,这个python代码里面写就是这样:
我看着都难受。所以砍了,砍了。
okey,那么这个最后的改动就是这个。
项目结构
那么之后的话,来看到我们的这个项目结构
这个项目结构的的话,一目了然,其实很简单。就这几个部分,
comm
这个部分是定义我们的一些常量,还有这个工具类。
errors
之后是异常的包,这个包里面全是我们定义的异常。然后这些异常的话,都是继承到这个类:
from comm.strings import string_with_arrows
class HlangError:
def __init__(self, pos_start, pos_end, error_name, details):
self.pos_start = pos_start
self.pos_end = pos_end
self.error_name = error_name
self.details = details
def as_string(self):
red_code = " 33[91m"
reset_code = " 33[0m"
result = f'{self.error_name}: {self.details}n'
result += f'File {self.pos_start.fn}, line {self.pos_start.ln + 1}'
result += 'nn' + string_with_arrows(self.pos_start.ftxt, self.pos_start, self.pos_end)
return red_code + result + reset_code
core
最后就是我们的核心包,这里面就是我们的词法解析器,语法解析器,解释器的实现了。
然后看的话从对应的抽象类(基类)里面看:
然后的话,在这个文件里面:
是我们的这个解释器的具体实现部分,还有常量等等的定义部分,后面的这个shell文件直接调用这个。
项目打包
那么这里的话,我们的项目地址是:gitee.com/Huterox/hla…
然后项目的话当然已经打包好了,在这里就可以下载:
Pyinstaller
那么这里的话,也是使用到Pyinstaller进行打包。所以的话,需要下载
pip install pyinstaller
即可完成下载。
编写Spec文件
由于这个包含的模块比较多,所以的话,我们需要这个编写这个文件。
这里的话我直接贴出来代码:
# -*- mode: python ; coding: utf-8 -*-
block_cipher = None
a = Analysis(['hlang_shell.py'],
pathex=['C:/Users/31395/Desktop/Hlang'],
binaries=[],
datas=[
('C:/Users/31395/Desktop/Hlang/comm/*', 'comm'),
('C:/Users/31395/Desktop/Hlang/errors/*', 'errors'),
('C:/Users/31395/Desktop/Hlang/core/*', 'core')
],
hiddenimports=[],
hookspath=[],
runtime_hooks=[],
excludes=[],
win_no_prefer_redirects=False,
win_private_assemblies=False,
cipher=block_cipher,
noarchive=False)
pyz = PYZ(a.pure, a.zipped_data,
cipher=block_cipher)
exe = EXE(pyz,
a.scripts,
[],
exclude_binaries=True,
name='Hlang',
debug=False,
bootloader_ignore_signals=False,
strip=False,
upx=True,
console=True , icon='favicon.ico')
coll = COLLECT(exe,
a.binaries,
a.zipfiles,
a.datas,
strip=False,
upx=True,
upx_exclude=[],
name='Hlang')
pathex
: 设置脚本所在的路径,可以是单个路径或者路径列表。datas
: 指定需要打包到可执行文件中的其他非 Python 文件,可以是单个文件或者文件夹,并指定在可执行文件内的相对路径。hiddenimports
: 设置需要隐式导入的模块,即无法通过静态分析检测到的依赖模块。cipher
: 设置加密算法,目前该参数为None
,表示不进行加密。exclude_binaries
: 设置是否排除二进制文件。name
: 指定生成的可执行文件的名称。debug
: 设置是否开启调试模式。bootloader_ignore_signals
: 设置引导加载程序是否忽略信号。strip
: 设置是否删除调试符号。upx
: 设置是否使用 UPX 压缩可执行文件。console
: 设置是否为控制台应用程序,如果为False
,则为窗口应用程序。icon
: 指定可执行文件的图标文件。
之后执行
pyinstaller hlang.spec
这里的话,注意创建好虚拟环境,这样的话,打包的程序更干净,体积更小。 我这里是直接使用pycharm 创建了。当然你也可以使用conda或者virtual。
总结
那么到这里的话,这个家伙就算搞完了。接下来继续数学强化,还差几个小结。然后的话,就轻松一点了,这个时候就只需要巩固,刷真题即可。