2010-03-30 31 views
7

我在這裏討論C和/或C++,因爲這是我認識的用於解釋器的唯一語言,其中以下可能是一個問題:如何用C和C++編寫的解釋器將標識符綁定到C(++)函數

如果我們有一個解釋語言X爲它編寫的庫如何爲語言添加函數,然後可以從該語言編寫的程序中調用該函數?

PHP例子:

substr($str, 5, 10); 
  • 如何SUBSTR加入到PHP的「函數庫」,所以它可以從腳本中調用的函數?

PHP很容易將所有註冊的函數名稱存儲在一個數組中,並在腳本中調用它作爲函數進行搜索。但是,由於C(++)中顯然沒有eval,那麼函數如何被調用呢?我假設PHP沒有100MB的代碼,如:

if(identifier == "substr") 
{ 
    return PHP_SUBSTR(...); 
} else if(...) { 
    ... 
} 

哈哈,這將是非常有趣的。我希望你能理解我的問題。

  • 用C/C++編寫的解釋器如何解決這個問題?
  • 我該如何解決這個問題,用我自己的用C++編寫的實驗玩具解釋器?
+0

你問什麼樣的戰略口譯一般使用?特別是C/C++的解釋器如何做到這一點?或者C/C++在編譯時如何執行此操作? – MtnViewMark 2010-03-30 18:56:38

+0

*口譯員如何解決這個問題? *我怎樣才能解決這個我自己的實驗玩具翻譯? – sub 2010-03-30 18:58:22

回答

7

實際上,腳本語言的功能與您所提到的類似。
它們包裝功能,並將這些功能註冊到解釋器引擎。

Lua的樣本:

static int io_read (lua_State *L) { 
    return g_read(L, getiofile(L, IO_INPUT), 1); 
} 


static int f_read (lua_State *L) { 
    return g_read(L, tofile(L), 2); 
} 
... 
static const luaL_Reg flib[] = { 
    {"close", io_close}, 
    {"flush", f_flush}, 
    {"lines", f_lines}, 
    {"read", f_read}, 
    {"seek", f_seek}, 
    {"setvbuf", f_setvbuf}, 
    {"write", f_write}, 
    {"__gc", io_gc}, 
    {"__tostring", io_tostring}, 
    {NULL, NULL} 
}; 
... 
luaL_register(L, NULL, flib); /* file methods */ 
+0

這是尷尬,但我不知道你可以在數組中存儲函數,這當然會改變一切; D – sub 2010-03-30 19:06:54

+0

@sub,是的,函數指針數組。檢查出來:) – 2010-03-30 19:16:06

+1

一注:許多語言不會爲每個電話都這樣做。通常,他們在解析過程中執行此查找,並立即將所有函數名稱轉換爲函數指針。有些甚至在運行時生成CALL彙編指令,這意味着它們的函數可以像其他任何本地函數一樣調用,並且只調用庫例程。 – uliwitness 2017-04-22 09:20:28

1

幾乎所有的編譯器都有一個「符號表」,用來查找標識符代表什麼。符號表將包含函數名稱,變量名稱,類型名稱等......任何具有名稱的名稱都會出現在符號表中,該符號表基本上是編譯器知道該名稱的所有內容的映射圖(我正在此處簡化)。然後,當編譯器遇到一個標識符時,它在符號表中查找它,並發現它是一個函數。如果您使用的是解釋器,那麼符號表將包含關於在何處找到該功能並繼續解釋的信息。如果這是一個編譯器,則符號表將具有該函數將在編譯代碼中的位置的地址(或稍後用於填充地址的佔位符)。然後可以生成組裝程序,實質上是這樣說的:將參數放在堆棧上,然後在某個地址恢復執行。

所以,你比如一個解釋就看

substr($str, 5, 10); 

,找到 「SUBSTR」 在它的符號表:

symbolTableEntry entry = symbolTable["substr"]; 

從那裏,它會聚集起來$str510作爲參數,並查看entry以查看參數對該函數有效。然後它會查找entry以查找編組參數的跳轉位置。

2

解釋器可能只是爲函數定義保留一個函數名稱的哈希表(它將包含參數信息,返回類型,函數位置/定義等)。這樣,您可以在函數名稱的hashmap上執行搜索(當你的翻譯遇到一個)。如果存在,使用散列表中的函數info來評估它。

您顯然需要爲不同級別的範圍添加條款等,但這是它的要點。

0

在C++中,你可能會使用類似的機制尼克d一樣,但利用其OO功能:

typedef luaFunction boost::function<void(*)(lua_State&)> 
std::map<std::string, luaFunction > symbolTable; 
symbolTable["read"] = f_read; 
symbolTable["close"] = f_close; // etc. 
// ... 
luaFunction& f = symbolTable[*symbolIterator++]; 
f(currentLuaState);