在上一篇文章裡我們講解了直譯器的基本架構,並實作出一個可以進行基礎四則運算的直譯器。但這個直譯器遇到正負號、空白字元、小數點、括號等等字元時會因為無法解析而出錯,因此本篇文章將會著手解決這些問題。
空白字元
要解決空白字元的問題非常簡單,只需要在讀取到空白字元時自動跳過就可以了,因此需要對我們的lexer稍加修改 :
lexer在讀取文字時若遇到空白字元,直接呼叫advance()跳過。
執行程式進行測試 :
js> 1 + 2
3
js> 12 + 345 * 2 / 10
81
測試成功 !
小數點
要能夠解析小數點的話,需要擴展我們lexer裡面的number()定義,在解析數字時遇到第一個小數點,可以接受這個字元並繼續向後解析,但若是同一個數字中出現多個小數點則會拋出錯誤 :
同樣的執行測試 :
js> 1.3 + 2.45
3.75
js> 345.2 + 9.8
355
測試成功 !
括號
括號處理起來會稍微麻煩一點,因為它會改變我們的語法規則,當初我們的規則是先乘除後加減,但括號的優先程度又要大於這些四則運算符號,因此我們會需要改變我們的parser,但在修改parser之前,需要先新增代表左右
接著修改parser的factor()解析方式 ,讓我們遇到到左括號時,會重新呼叫expr()來解析括號中的內容,解析完畢後再檢查是否有出現右括號,並將解析出來的子樹回傳 :
最後別忘了也要修改lexer,讓遇到括號時能夠解析並產生對應的token :
開始進行測試 :
js> (1+2)*3
9
js> (1+2*3)*4-5*6
-2
測試成功 !
上一篇文章有提到過,括號的出現會影響我們的抽象語法樹結構,因此我們可以將剛剛測試用的案例當作目標,練習建構出對應的抽象語法樹 :
正負號
若要處理正負號的狀況,我們需要一個新的抽象語法樹節點類型 : 一元運算符 unary,unary接受一個子節點,而我們可以在走訪的時候將子節點的值先進行正負操作再回傳,以此達到我們想要的效果,我們首先在src/ast
接著在parser解析時,實作unary的建構,我們在factor()裡面處理他,因為正負號的優先度是最高的 :
最後在interpreter裡面實作走訪到unary時的行為 :
這樣就完成正負號的部份了,一樣執行專案進行測試 :
js> +++---+-+-++---87
87
js> -(2+3)*-5
25
js> -2 * -(3-11) / ---4
4
測試成功 !
本篇文章的內容到這裡就結束了,這次我們將一些簡單但是重要的功能實作出來,雖然內容篇幅不長,但是剛好lexer、parser、interpreter這三個最重要的核心功能都有涵蓋到,正好能藉此機會更加熟悉直譯器的整個解析與執行流程。
下一次我們會介紹javascript程式碼的基本組成,包含函數、作用區塊、變量的型別、賦值與計算等等,並開始以真正的文本來進行解析,讓我們的直譯器更有架式。
這個系列的完整內容可以到我的github repo上參考。
참조:
간단한 통역사를 만들어 봅시다.
如果對於我的文章或程式碼有任何問題,歡迎在下方留言指教。
若有幫助到你,也歡迎給文章拍手一下,讓我在寫文章的路上更加進步!
'javascript' 카테고리의 다른 글
Mapas con 자바스크립트 (0) | 2021.12.29 |
---|---|
몰랐던 5가지 JavaScript 기능 (0) | 2021.12.29 |
응답 NextJS Instagram UI 클론 생성 - 프로파일 페이지 6부 (0) | 2021.12.29 |
Javascript 알고리즘: 역추적 (0) | 2021.12.29 |
면접관 대부분이 프런트엔드 개발자에게 질문을 했다. (0) | 2021.12.29 |
댓글