基于Python編寫個語法解析器
前言
目的純粹,基于Python做一個簡單的新的簡單的編程語言。一方面是開拓視野,另一方面是作為畢設(shè)的臨時過渡方案(沒錯,先前提到的算法平臺,沒有把握快速開發(fā)完畢,即便我使用大量的腳手架完成開發(fā),但是算法容器,rpc算法調(diào)度中間件都需要自己造輪子,難度較大,此外還有用戶部分的UI設(shè)計等等,最重要的是,那幫老師根本無法理解這種項目。沒有必要搞太“花里胡哨”但是盡管如此,這個項目我后期還是要開發(fā)的,主要原因在于算法容器和rpc算法調(diào)度中間件,這個對我來說是非常值得去做的。里面涉及到的思想是非常受用的。雖然我現(xiàn)在在腦子里面構(gòu)思好了,要怎么做,但是這個編碼量實在太大。并且目標(biāo)院校改考11408,現(xiàn)在導(dǎo)致我很被動,因此,我決定寫一個sample computer language。同時為了加快開發(fā)進(jìn)度,直接使用Python進(jìn)行編寫,后期轉(zhuǎn)到Pypy,然后編譯出這個語言的編譯器。
那么目標(biāo)的話,就是做到簡單,直接做中文的,給小孩子鍛煉思維的。當(dāng)然,這也是為了方便給我講故事。能在那幫尸位素餐的老師面前多說點他們能夠理解的東西。沒辦法一個普通院校,很多老師水平也就那樣,很無奈,但是沒有辦法改變。
選型
針對人群
有樣沒樣,樣子要像,那么這個編程語言的主要目的話,就是易學(xué)易用。推出中文編程,兼容Python,方便培養(yǎng)小學(xué)生鍛煉編程思維,適合一到兩年級的小學(xué)生進(jìn)行學(xué)習(xí)。不同于圖形化編程,Hlang可以體驗到更加真實的編程環(huán)境,并且不會增加難度。既可以培養(yǎng)孩子的邏輯思維,同時還可以。。。 算了,編不下去了,就是個dome,同時用來應(yīng)付應(yīng)付畢設(shè)。
目標(biāo)
沒有目標(biāo),就是混~~ 本文目標(biāo),實現(xiàn)一個簡單的語法解析器。反正隨便寫個幾千行代碼就能交個差,一幫混子!
技術(shù)實現(xiàn)
基于Python,體現(xiàn)體現(xiàn)思想,不追求運(yùn)行效率,重在好學(xué),給小孩子玩玩兒。不是總有某些家長說啥,英語難計算機(jī)簡單的嘛?來,那就用用這個~~
本文目標(biāo)
寫一個簡單的語法解析器,然后下班~ 高數(shù)玩膩了,就玩這個,這個玩膩了就學(xué)英語。
效果
ok,我們先來看到我們的實現(xiàn)效果:

這個就是一個簡易的語法解析器。
實現(xiàn)
扯遠(yuǎn)了,我們來看看是如何進(jìn)行實現(xiàn)的。
首先是定義好我們的標(biāo)準(zhǔn)合法字符:
TT_INT = "整數(shù)" TT_FLOAT = "浮點數(shù)" TT_PLUS = "加號" TT_DIV = "除號" TT_MINUS = "減號" TT_LPAREN = "左括號" TT_RPAREN = "右括號" TT_MUL = "乘" TT_POWER = "次冪" DIGITS = "123456789"
然后我們定義一個Token把這些對象封裝起來
class Token:
def __init__(self,is_type,is_value=None):
self.is_type = is_type
self.is_value = is_value
def __repr__(self):
if self.is_value:
return "|類型:{},值:{}|".format(self.is_type,self.is_value)
return "|類型:{}|".format(self.is_type)
def __str__(self):
if(self.is_value):
return "|{}|".format(self.is_value)
return "|這個對象沒有值,類型為:{}|".format(self.is_type)在這里我們要做的目的很簡單,那就是,把接下來輸入的內(nèi)容,或者文本內(nèi)容,進(jìn)行讀取,然后解析出東西,把合法的字符收集起來。注意,我們這里還沒有什么變量的概念,在這里只是負(fù)責(zé)解析好基本的合法字符。至于變量的引入要到后面,因為這個時候要設(shè)計清楚基本的語法規(guī)范,然后就是照著一頓借鑒就完了。
字符指針
之后的話,我們定義好了Token,那么就要去讀取解析文本,這個沒有辦法,我們只能一個字符一個字符進(jìn)行掃描。為了方便,因此,這里對字符指針進(jìn)行一個簡單封裝。
class Position:
def __init__(self, idx, ln, col):
self.idx = idx
self.ln = ln
self.col = col
def advance(self, cur_char):
self.idx += 1
self.col += 1
if cur_char == '\n':
self.ln += 1
self.col = 0
return self錯誤類型
之后的話,我們還要去定義錯誤。比如,當(dāng)我輸入一個非法字符之后要報個錯,就像Python一樣:

所以我們也要來個這個東西:

"""
頂級錯誤(老大)
"""
class HlangError:
def __init__(self, pos_ln,in_fn,error_name, details):
"""
:param pos_ln: 錯誤行
:param in_fn: 輸入文件
:param error_name: 錯誤名稱
:param details: 錯誤細(xì)節(jié),說明
"""
self.pos_ln = pos_ln
self.in_fn = in_fn
self.error_name = error_name
self.details = details
def as_string(self):
red_code = "\033[91m"
reset_code = "\033[0m"
result = f'{self.error_name}: {self.details}\n'
result += f'來自 {self.in_fn}, line {self.pos_ln + 1}'
return red_code+result+reset_code
class IllegalCharError(HlangError):
"""
非法字符錯誤
"""
def __init__(self, pos_ln,in_fn, details):
super().__init__(pos_ln, in_fn, '非法字符', details)語法解析
那么之后的話,就可以開始我們的語法解析了
這個代碼的話,很簡單,就是往死里加入就好了
"""
語法解析器
"""
class Lexer:
def __init__(self, in_fn, text):
"""
:param in_fn: 從哪里輸入的文本(文本所在文件,標(biāo)準(zhǔn)輸入,輸出也是一個文件)
其實就是文件名~~~
:param text: 待解析文本
"""
self.in_fn = in_fn
self.text = text
self.pos = Position(-1, 0, -1)
self.cur_char = None
self.advance()
#基本的符號處理
self.char_pro_base = {
'+':TT_PLUS,
'-':TT_MINUS,
'*':TT_MUL,
'/':TT_DIV,
'^':TT_POWER,
'(':TT_LPAREN,
')':TT_RPAREN
}
def advance(self):
self.pos.advance(self.cur_char)
self.cur_char = self.text[self.pos.idx] if self.pos.idx < len(self.text) else None
def __char_process(self,tokens,TT):
"""
處理基本字符的方法,
添加Token,并且移動字符指針
:return:
"""
tokens.append(Token(TT))
self.advance()
def make_tokens(self):
"""
將文本當(dāng)中的字符添加到語法解析器當(dāng)中,將符合語法規(guī)范的內(nèi)容,封裝為Token,
(就像Spring將對象信息再封裝為Wapper一樣,方便后續(xù)進(jìn)行操作。)
:return:
"""
tokens = []
while self.cur_char != None:
if self.cur_char in ' \t':
#制表符(空格),沒有意義,往前移動
self.advance()
elif self.cur_char in DIGITS:
#如果是數(shù)字,自動往前搜索,并且將數(shù)字進(jìn)行添加,并且判斷類型,
#數(shù)字比較特殊,不是一個字符一個字符參與的(后面還要定義關(guān)鍵字也是類似的)
tokens.append(self.make_number())
else:
TT = self.char_pro_base.get(self.cur_char)
if(TT):
self.__char_process(tokens,TT)
else:
char = self.cur_char
self.advance()
return [], IllegalCharError(self.pos.ln,self.in_fn, "'" + char + "'")
return tokens, None
def make_number(self):
num_str = ''
dot_count = 0
while self.cur_char != None and self.cur_char in DIGITS + '.':
if self.cur_char == '.':
if dot_count == 1: break
dot_count += 1
num_str += '.'
else:
num_str += self.cur_char
self.advance()
if dot_count == 0:
return Token(TT_INT, int(num_str))
else:
return Token(TT_FLOAT, float(num_str))之后的話,別忘了還需要要一個run作為入口,run起來:
"""
語言解析,運(yùn)行入口
"""
def run(fn, text):
lexer = Lexer(fn, text)
tokens, error = lexer.make_tokens()
return tokens, error交互
最后的最后,就是我們的交互了:
"""
Hlang is a Sample Language shell
Just a sample example for learning by Huterox
"""
import basic
while True:
input_text = input("交互終端:")
result, error = basic.run('<標(biāo)準(zhǔn)輸入>', input_text)
if error: print(error.as_string())
else: print(result)然后搞定,so 簡單
以上就是基于Python編寫個語法解析器的詳細(xì)內(nèi)容,更多關(guān)于Python語法解析器的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Python簡單網(wǎng)絡(luò)編程示例【客戶端與服務(wù)端】
這篇文章主要介紹了Python簡單網(wǎng)絡(luò)編程,詳細(xì)介紹了客戶端與服務(wù)端的具體實現(xiàn)技巧與相關(guān)注意事項,需要的朋友可以參考下2017-05-05
python 刪除系統(tǒng)中的文件(按時間,大小,擴(kuò)展名)
這篇文章主要介紹了python 如何刪除系統(tǒng)中的文件,分別按時間,大小,擴(kuò)展名刪除,滿足不同需求,感興趣的朋友可以了解下2020-11-11
TensorFlow卷積神經(jīng)網(wǎng)絡(luò)之使用訓(xùn)練好的模型識別貓狗圖片
今天小編就為大家分享一篇關(guān)于TensorFlow卷積神經(jīng)網(wǎng)絡(luò)之使用訓(xùn)練好的模型識別貓狗圖片,小編覺得內(nèi)容挺不錯的,現(xiàn)在分享給大家,具有很好的參考價值,需要的朋友一起跟隨小編來看看吧2019-03-03
Pytorch訓(xùn)練過程出現(xiàn)nan的解決方式
今天小編就為大家分享一篇Pytorch訓(xùn)練過程出現(xiàn)nan的解決方式,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2020-01-01

