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