[譯] 用javascript實現一門程式語言-寫一個解析器

Alongite發表於2018-08-03

目錄

  1. 用javascript實現一門程式語言-前言
  2. 用javascript實現一門程式語言-語言構想
  3. 用javascript實現一門程式語言-寫一個解析器
  4. 用javascript實現一門程式語言-字元輸入流

寫一個解析器

解析器的實現是需要根據語言特性來實現的,是一個較為複雜的任務。事實上,我們需要將一段程式碼或者字母轉換為抽象語法樹 (abstract syntax tree, AST)。抽象語法樹是程式在記憶體中展現的一種形式,抽象表示它不關心是由什麼原始碼構成的,但是他很確信是符合語義學的。

例如:

sum = lambda(a, b) {
    a + b;
}
print(sum(1, 2));
複製程式碼

解析器會將上面的程式碼轉換為一個javascript物件:

{
  type: "prog",
  prog: [
    // 第一行
    {
      type: "assign",
      operator: "=",
      left: { type: "var", value: "sum" },
      right: {
        type: "lambda",
        vars: [ "a", "b" ],
        body: {
          // body 部分也應該是 prog 型別,因為它包含一個表示式
          type: "binary",
          operator: "+",
          left: { type: "var", value: "a" },
          right: { type: "var", value: "b" }
        }
      }
    },
    // 第二行
    {
      type: "call",
      func: { type: "var", value: "print" },
      args: [{
        type: "call",
        func: { type: "var", value: "sum" },
        args: [ { type: "num", value: 1 },
                { type: "num", value: 2 } ]
      }]
    }
  ]
}
複製程式碼

寫一個解析器最大的困難在於如何合理的組織程式碼。解析器應該站在比讀取字元更高的層面。這裡有一些建來控制程式的適度的複雜性:

  • 寫小而精的函式。每個函式只做一件事,並把它做好。
  • 不要用正規表示式去解析。在寫詞法分析器的時候正規表示式很有用,但是建議儘量不要把它用在很簡單的事情上
  • 不要嘗試去猜。當不確定解析什麼的時候,丟擲一個包含位置的錯誤,比如: 第2行25列錯誤

為了保持膽碼的簡潔性,我將程式碼分割成了三部分,將來會被分割成更小的函式:

  • 字元輸入流
  • token輸入流
  • 解析器

原文連結: lisperator.net/pltut/parse…

相關文章