如何進(jìn)行thriftpy+ply的源碼分析,很多新手對(duì)此不是很清楚,為了幫助大家解決這個(gè)難題,下面小編將為大家詳細(xì)講解,有這方面需求的人可以來學(xué)習(xí)下,希望你能有所收獲。
成都創(chuàng)新互聯(lián),為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)站營(yíng)銷推廣、網(wǎng)站開發(fā)設(shè)計(jì),對(duì)服務(wù)木托盤等多個(gè)行業(yè)擁有豐富的網(wǎng)站建設(shè)及推廣經(jīng)驗(yàn)。成都創(chuàng)新互聯(lián)網(wǎng)站建設(shè)公司成立于2013年,提供專業(yè)網(wǎng)站制作報(bào)價(jià)服務(wù),我們深知市場(chǎng)的競(jìng)爭(zhēng)激烈,認(rèn)真對(duì)待每位客戶,為客戶提供賞心悅目的作品。 與客戶共同發(fā)展進(jìn)步,是我們永遠(yuǎn)的責(zé)任!
thrift 使用ply做編譯和解析器,ply是編譯原理入門比較方便的源碼,代碼量少,且python文本就是代碼,解析方便
ex把每個(gè)掃面出來的單詞叫統(tǒng)統(tǒng)叫做token,token可以有很多類。對(duì)比自然語(yǔ)言的話,英語(yǔ)中的每個(gè)單詞都是token,token有很多類,比如non(名詞)就是一個(gè)類token,apple就是屬于這個(gè)類型的一個(gè)具體token。對(duì)于某個(gè)編程語(yǔ)言來說,token的個(gè)數(shù)是很有限的,不像英語(yǔ)這種自然語(yǔ)言中有幾十萬個(gè)單詞。
lex工具會(huì)幫我們生成一個(gè)yylex函數(shù),yacc通過調(diào)用這個(gè)函數(shù)來得知拿到的token是什么類型的,但是token的類型是在yacc中定義的。
lex的輸入文件一般會(huì)被命名成 .l文件,通過lex XX.l 我們得到輸出的文件是lex.yy.c
yacc是什么呢?
剛才說完lex了,那么yacc呢,教科書上把yacc做的工作叫做syntactic analysis。這次我們翻譯沒有直譯做句法分析,而是叫語(yǔ)法分析,這個(gè)翻譯能好一點(diǎn),意思也基本上比較清楚。
其實(shí)我們最開始學(xué)習(xí)英語(yǔ)的時(shí)候老師都會(huì)告訴我們英語(yǔ)其實(shí)就是“單詞+語(yǔ)法”,這個(gè)觀點(diǎn)放到編程語(yǔ)言中很合適,lex提取了單詞,那么是剩下的部分就是如何表達(dá)語(yǔ)法。那么yacc做的事情就是這一部分(實(shí)際應(yīng)該說是BNF來做的)。
yacc會(huì)幫我們生成一個(gè)yyparse函數(shù),這個(gè)函數(shù)會(huì)不斷調(diào)用上面的yylex函數(shù)來得到token的類型。
yacc的輸入文件一般會(huì)被命名成 .y文件,通過yacc -d XX.y我們得到的輸出文件是y.tab.h y.tab.c,前者包含了lex需要的token類型定義,需要被include進(jìn) .l文件中
lex和yacc的輸入文件格式
Definition section
%%
Rules section
%%
C code section
.l和.y的文件格式都是分成三段,用%%來分割,三個(gè)section的含義是:
Definition Section
這塊可以放C語(yǔ)言的各種各種include,define等聲明語(yǔ)句,但是要用%{ %}括起來。
如果是.l文件,可以放預(yù)定義的正則表達(dá)式:minus "-" 還要放token的定義,方法是:代號(hào) 正則表達(dá)式。然后到了,Rules Section就可以通過{符號(hào)} 來引用正則表達(dá)式
如果是.y文件,可以放token的定義,如:%token INTEGER PLUS ,這里的定一個(gè)的每個(gè)token都可以在y.tab.h中看到
Rules section
.l文件在這里放置的rules就是每個(gè)正則表達(dá)式要對(duì)應(yīng)的動(dòng)作,一般是返回一個(gè)token
.y文件在這里放置的rules就是滿足一個(gè)語(yǔ)法描述時(shí)要執(zhí)行的動(dòng)作
不論是.l文件還是.y文件這里的動(dòng)作都是用{}擴(kuò)起來的,用C語(yǔ)言來描述,這些代碼可以做你任何想要做的事情
C code Section
main函數(shù),yyerror函數(shù)等的定義
lex和yacc能幫我們做什么?
一句話:解釋執(zhí)行自定義語(yǔ)言。有幾點(diǎn)要注意:
自定義語(yǔ)言的要做的事情必須可以能通過C語(yǔ)言來實(shí)現(xiàn)。其實(shí)任何計(jì)算機(jī)能做的事情都可以用C語(yǔ)言來實(shí)現(xiàn),lex和yacc存在的意義在于簡(jiǎn)化語(yǔ)言,讓使用者能夠以一種用比較簡(jiǎn)單的語(yǔ)言來實(shí)現(xiàn)復(fù)雜的操作。比如:對(duì)于數(shù)據(jù)庫(kù)的查詢肯定有現(xiàn)成的庫(kù)可以來完成,但是使用起來比較麻煩,要自己寫成語(yǔ)調(diào)用API,編譯才行。如果我們想實(shí)自定義一個(gè)簡(jiǎn)單的語(yǔ)言(比如SQL)來實(shí)現(xiàn)操作,這個(gè)時(shí)候就可以用lex和yacc。
lex和yacc 做的事情只是:用C語(yǔ)言來實(shí)現(xiàn)另外一種語(yǔ)言。所以,他沒辦法實(shí)現(xiàn)C語(yǔ)言自己,但是可以實(shí)現(xiàn)java、python等。當(dāng)然你可以通過Antlr來實(shí)現(xiàn)C語(yǔ)言的解析和執(zhí)行,如果你這么做的話,C語(yǔ)言程序首先是通過java來執(zhí)行,然后java又變成了本地語(yǔ)言(C語(yǔ)言)來執(zhí)行,誰(shuí)叫我們的操作系統(tǒng)都是C語(yǔ)言實(shí)現(xiàn)的呢。
使用lex和yacc我們要做那幾件事情?
定義各種token類型。他們?cè)?y中定義,這些token既會(huì)被lex使用到,也會(huì)被.y文件中的BNF使用到。
寫詞匯分析代碼。這部分代碼在.l文件(就是lex的輸入文件)中。這塊的定義方式是:正則表達(dá)式-->對(duì)應(yīng)操作。如果和yacc一起來使用的話,對(duì)應(yīng)的操作通常是返回一個(gè)token類型,這個(gè)token的類型要在yacc中提前定義好。
寫B(tài)NF。這些東西定義了語(yǔ)言的規(guī)約方式。
關(guān)于BNF
是一種context-free grammars,請(qǐng)參考:http://en.wikipedia.org/wiki/Backus%E2%80%93Naur_Form 摘錄:
__expression__ consists of one or more sequences of symbols
more sequences are separated by the vertical bar, '|'
Symbols that never appear on a left side are terminals. On the other hand
symbols that appear on a left side are non-terminals and are always enclosed between the pair <>.
在yacc中定義的方式其實(shí)是:
| __expression__ {operation}
operation 是 滿足語(yǔ)法時(shí)要執(zhí)行的C語(yǔ)言代碼,這里的C語(yǔ)言代碼可以使用一些變量,他們是:$$ $1 $2等等。$$代表規(guī)約的結(jié)果,就是表達(dá)式__expression__的值,$1代表的是前面 __expression__ 中出現(xiàn)的各個(gè)word。舉個(gè)例子:
expr2:
expr3 { $$ == $1; }
| expr2 PLUS expr3 { $$ = plus($1, $3); }
| expr2 MINUS expr3 { $$ = minus($1, $3); }
看完上述內(nèi)容是否對(duì)您有幫助呢?如果還想對(duì)相關(guān)知識(shí)有進(jìn)一步的了解或閱讀更多相關(guān)文章,請(qǐng)關(guān)注創(chuàng)新互聯(lián)行業(yè)資訊頻道,感謝您對(duì)創(chuàng)新互聯(lián)的支持。