前面拍了好幾天的影片,偷懶一集來個名詞解釋,順便說一下前面的程式碼大概在做些什麼事。
我用一個國小生就會的四則運算為例:12 + 5 * 3
等於多少?
答案應該是 27
。為什麼不是 51
?因為「先乘除後加減」的規則,後面的 5 * 3
要先算,最後再回頭算前面的加法
這對你我來說,應該都不是什麼難事,但對程式語言來說就不一定了,程式語言是怎麼知道先乘除後加減的規則?
所以,第一件要做的事,就是要先能夠首先就得先要讀懂 12 + 5 * 3
這段文字。
首先登場的是 Tokenizer。舉例來說,我們人類肉眼看到 12
可以輕鬆的把它解讀成十進位的數字 12
,Tokenizer 的工作就是要做類似的事,把它解讀成「十二」,而不是「一」跟「二」。
接著的 +
也是,Tokenizer 要能夠把它解讀成一種 operator,而不單純就只是字串 +
而已。
以數字來說,在我前面幾集的影片中,我的 Tokenizer 就會把 12
解讀成:
{
type: "NUMBER",
value: "12"
}
而如果是 "hello world"
字串的話,則是解讀成:
{
type: "STRING",
value: `"hello world"`
}
但光是解讀出來沒什麼用,最終要讓電腦看的懂的我們的意圖話,還是得請 Parser 來幫忙解析語法。
Parser 會把我們寫的語法先轉換成另一種資料結構,稱之 AST(Abstract Syntax Tree)之所以會有 Tree
這個字,就是因為它的樣子看起來像個樹一樣:
圖片來源:維基百科
把原本的文字轉成這樣的資料結構後,後續才能知道哪些該先執行、哪些比較晚執行。以前面說到的 12 + 5 * 3
,透過 AST Explorer 幫我們解析出來的 AST 大概長這樣:
{
"type": "Program",
"body": [
{
"type": "ExpressionStatement",
"expression": {
"type": "BinaryExpression",
"left": {
"type": "Literal",
"value": 12,
},
"operator": "+",
"right": {
"type": "BinaryExpression",
"left": {
"type": "Literal",
"value": 5,
},
"operator": "*",
"right": {
"type": "Literal",
"value": 3,
}
}
}
}
]
}
我把部份的內容修掉,但看最下面部份:
{
"type": "BinaryExpression",
"left": {
"type": "Literal",
"value": 5,
},
"operator": "*",
"right": {
"type": "Literal",
"value": 3,
}
}
大概可以猜的出來這是一個 BinaryExpression
,它的左手邊(left
)是 5
,右手邊(right
)是 3
,而運算元(operator
)是 *
。再往上看,就會看到另一個類似的結構:
{
"type": "BinaryExpression",
"left": {
"type": "Literal",
"value": 12,
},
"operator": "+",
"right": {上面剛剛的內容}
}
左手邊(left
)是 12
,右手邊(right
)是上一段的內容... 以此類推,有了這個結構後,後續就有辦法決定原本的語法的執行順序囉...(待續)