摘要:詞法分析它是編譯過程的第一個(gè)階段。可以使用等自動(dòng)化詞法分析工具,來幫助我們完成。在中,使用的詞法分析器是,語(yǔ)法分析器是。其實(shí)進(jìn)行詞法分析和語(yǔ)法分析并生成某種數(shù)據(jù)結(jié)構(gòu)的過程,就是一個(gè)解碼的過程。
baiyan
全部視頻:https://segmentfault.com/a/11...
原視頻地址:http://replay.xesv5.com/ll/24...
基本概念在PHP7中,當(dāng)一個(gè)腳本運(yùn)行請(qǐng)求或到來時(shí),PHP代碼首先會(huì)被加載到內(nèi)存中,隨后進(jìn)行詞法分析和語(yǔ)法分析并生成抽象語(yǔ)法樹(AST),然后進(jìn)行深度優(yōu)先遍歷并生成opcodes,并在zend虛擬機(jī)中執(zhí)行這些opcode,返回最終的執(zhí)行結(jié)果。
詞法分析:它是編譯過程的第一個(gè)階段。這個(gè)階段會(huì)將代碼從左到右按字符掃描并讀入,然后將代碼劃分成一個(gè)又一個(gè)的詞法單元(token),方便后續(xù)的語(yǔ)法分析以及編譯優(yōu)化等操作。這就好比用菜刀去切一塊肉,將這塊大肉切分成一小塊一小塊肉,方便人們后續(xù)食用。可以使用Re2c、lex等自動(dòng)化詞法分析工具,來幫助我們完成。
語(yǔ)法分析:語(yǔ)法分析是編譯過程的一個(gè)邏輯階段。語(yǔ)法分析的任務(wù)是在詞法分析的基礎(chǔ)上將詞法單元token,組合成各類語(yǔ)法短語(yǔ),如“程序”,“語(yǔ)句”,“表達(dá)式”等等,它能夠判斷源程序在結(jié)構(gòu)上是否正確。
在PHP中,使用的詞法分析器是Re2c,語(yǔ)法分析器是Bison。
其實(shí)進(jìn)行詞法分析和語(yǔ)法分析并生成某種數(shù)據(jù)結(jié)構(gòu)的過程,就是一個(gè)解碼的過程。
之所以需要做這種從字符串到數(shù)據(jù)結(jié)構(gòu)(AST)的轉(zhuǎn)換,是因?yàn)榫幾g器是無法直接操作“1+2”這樣的字符串的。實(shí)際上,代碼的本質(zhì)根本就不是字符串,它本來就是一個(gè)具有復(fù)雜拓?fù)涞臄?shù)據(jù)結(jié)構(gòu),就像電路一樣。“1+2”這個(gè)字符串只是對(duì)這種數(shù)據(jù)結(jié)構(gòu)的一種“編碼”,就像ZIP或者JPEG只是對(duì)它們壓縮的數(shù)據(jù)的編碼一樣。
這種編碼可以方便你把代碼存到磁盤上,方便你用文本編輯器來修改它們(對(duì)人友好,方便人們編寫代碼,但是對(duì)編譯器不友好),然而你必須知道,文本并不是代碼本身。所以從磁盤讀取了文本之后,你必須先“解碼”,才能方便地操作代碼的數(shù)據(jù)結(jié)構(gòu)。比如,如果上面的Java代碼生成的AST節(jié)點(diǎn)叫node,你就可以用node.operator來訪問加號(hào)ADD,用node.left來訪問1,node.right來訪問2。這是很方便的。對(duì)于程序語(yǔ)言,這種解碼的動(dòng)作就叫做parsing,用于解碼的那段代碼就叫做parser。
關(guān)于語(yǔ)法分析與詞法分析的具體概念解釋,這篇文章寫得較好:對(duì) Parser 的誤解
我們先利用PHP內(nèi)置函數(shù)token_get_all()來取出一段PHP代碼的token:
打印結(jié)果為:
Line 1: T_OPEN_TAG ("觀察以上結(jié)果,可以看有OPEN_TAG/VARIABLE/WHITESPACE等等詞法單元token。
如何取出token
那么讓我們你自己去設(shè)計(jì)一個(gè)算法,從一個(gè)字符串中識(shí)別并取出token,應(yīng)該怎么做?
使用兩個(gè)指針,一個(gè)標(biāo)記開始位置,一個(gè)往后挪,然后回溯。(較麻煩)
使用正則表達(dá)式進(jìn)行匹配
當(dāng)用較簡(jiǎn)單的字符串匹配正則表達(dá)式的時(shí)候,可以用人眼很容易地看出來。但是如果用很復(fù)雜的字符串(成千上萬行代碼)去匹配一個(gè)正則,是相當(dāng)麻煩并且非常慢的,編譯原理中提出了這樣一個(gè)概念用以解決這個(gè)問題:有窮狀態(tài)機(jī)。
有窮狀態(tài)機(jī):必須有一個(gè)起始狀態(tài),用一個(gè)箭頭加圓圈表示;也得有一個(gè)結(jié)束,用兩個(gè)圓圈表示。 如果滿足某個(gè)條件,就會(huì)從一個(gè)狀態(tài)躍遷到另一個(gè)狀態(tài),也用箭頭來表示。
例:觀察下面這個(gè)正則表達(dá)式:
(a|b)*abb根據(jù)這個(gè)正則表達(dá)式,我們可以畫出它的有窮狀態(tài)機(jī):
- 對(duì)于a,只能到狀態(tài)0或者1,不能到達(dá)結(jié)束的3,所以不匹配 - 對(duì)于abb,第一個(gè)a可以使?fàn)顟B(tài)0躍遷到1,第二個(gè)b可以從1躍遷到2,最后一個(gè)b結(jié)束,所以匹配 - 對(duì)于aabb,第一個(gè)a可以選擇從0躍遷到0,第二個(gè)從0躍遷到1,后面兩個(gè)b同上,匹配 - 對(duì)于cabb,第一個(gè)c就無法滿足,不匹配這里有個(gè)問題,輸入第一個(gè)a的時(shí)候,可以從0躍遷到自己,也可以從0躍遷到1,所以這種狀態(tài)機(jī)就叫不確定有窮狀態(tài)機(jī)(NFA)
NFA是有缺陷的,比如aabb,有可能一直從0躍遷到0,共重復(fù)了4次這樣的操作,也沒有到達(dá)最終的結(jié)束狀態(tài)3。這就會(huì)導(dǎo)致本應(yīng)該符合匹配要求的字符串,在不確定有窮狀態(tài)機(jī)中,錯(cuò)誤地被判定為不符合匹配要求。解決此問題的辦法就是將不確定有窮狀態(tài)機(jī)轉(zhuǎn)化為確定有窮狀態(tài)機(jī)(DFA)。
這樣一來,一個(gè)確定的輸入就對(duì)應(yīng)著一個(gè)確定的輸出(假設(shè)如給一個(gè)a,一定躍遷到1;給一個(gè)b,一定躍遷回0),不存在歧義問題。
但是,將一個(gè)NFA轉(zhuǎn)化成DFA是相當(dāng)復(fù)雜的,所以有工具已經(jīng)為我們做好了這個(gè)事情:Re2c。你只需要輸入一個(gè)正則表達(dá)式,就能夠?yàn)槟闵梢粋€(gè)確定有窮狀態(tài)機(jī)(DFA),在Re2c工具中以C/C++代碼體現(xiàn),詳情見:re2c中文手冊(cè)
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://specialneedsforspecialkids.com/yun/31326.html
摘要:此文用于匯總跟隨陳雷老師及團(tuán)隊(duì)的視頻,學(xué)習(xí)源碼過程中的思考整理與心得體會(huì),此文會(huì)不斷更新視頻傳送門每日學(xué)習(xí)記錄使用錄像設(shè)備記錄每天的學(xué)習(xí)源碼學(xué)習(xí)源碼學(xué)習(xí)內(nèi)存管理筆記源碼學(xué)習(xí)內(nèi)存管理筆記源碼學(xué)習(xí)內(nèi)存管理筆記源碼學(xué)習(xí)基本變量筆記 此文用于匯總跟隨陳雷老師及團(tuán)隊(duì)的視頻,學(xué)習(xí)源碼過程中的思考、整理與心得體會(huì),此文會(huì)不斷更新 視頻傳送門:【每日學(xué)習(xí)記錄】使用錄像設(shè)備記錄每天的學(xué)習(xí) PHP7...
摘要:全部視頻原視頻地址引入抽象語(yǔ)法樹是中新引入的,在許多其他語(yǔ)言中早已有實(shí)現(xiàn)。例,怎么用抽象語(yǔ)法樹來表達(dá)那么使用中序遍歷就可以得到上述表達(dá)式。 baiyan 全部視頻:https://segmentfault.com/a/11... 原視頻地址:http://replay.xesv5.com/ll/24... 引入 抽象語(yǔ)法樹(AST)是PHP7中新引入的,在許多其他語(yǔ)言中早已有實(shí)現(xiàn)。 ...
摘要:在中,源代碼首先將進(jìn)行詞法分析,將源代碼切割為多個(gè)字符串單元,分割后的字符串稱之為。圖以為例解釋型語(yǔ)言的執(zhí)行示意圖第步源碼通過詞法分析得到第步基于語(yǔ)法分析器生成抽象語(yǔ)法樹第步抽象語(yǔ)法樹轉(zhuǎn)換為指令集合,解釋執(zhí)行。 順風(fēng)車運(yùn)營(yíng)研發(fā)團(tuán)隊(duì) 李志 發(fā)表在程序人生 公眾號(hào)我們常用的高級(jí)語(yǔ)言有很多種,比較出名的有CC++、Python、 PHP、Go、Pascal等。而這些語(yǔ)言根據(jù)運(yùn)行的方式不同,...
閱讀 1039·2021-11-18 13:23
閱讀 746·2021-11-08 13:16
閱讀 855·2021-10-11 10:58
閱讀 3510·2021-09-22 15:26
閱讀 1732·2021-09-08 10:42
閱讀 1807·2021-09-04 16:45
閱讀 1733·2019-08-30 15:54
閱讀 2564·2019-08-30 13:45