author: Kevin Lynx email: zmhn320#163.com date: 3.6.2009
語言特性
在正式討論實現細節前明確下這個腳本語言的一些語言特性,基本上可以讓我們預見將
來會遇到哪些難題。總的來說,它(腳本)將同我們平時接觸的如lua一樣的腳本語言:擁
有一般的編程語言特性,如變量、各種控制流程、也許還有函數,另一方面它還應該和它的
宿主語言結合,如作為一個庫被用進C,這還涉及到給這門語言設計一種插件方式,最好能
通過獨立的解釋程序讓腳本載入一些插件運行。
以下在描述我寫的這個腳本語言時,將以kl表示它的名字,以方便描述。
代碼塊:
首先從整體風格上,kl如同C語言一樣被劃分為函數塊,如:
function func1()
{
}
function func2()
{
}
...
kl支持以{}隔離代碼塊,但是這并不意味著kl有多個獨立的局部堆棧,如同C語言一樣。
這些細節暫不討論。本節描述的所有內容你都不必深究,因為我只要求你對kl有個感性上的
認識。
函數塊之外沒有可執行的語句(statement)。那么你可能會想到程序的入口點也許會是
main。事實上從kl提供的庫來看,并沒有這種硬性要求。但是,kl的獨立解釋程序是這樣要
求的。
變量:
kl允許你在任何地方使用一個變量。變量不需要事先定義,任何地方出現一個合
法的標識符時,就意味著kl內部會增加這個變量,并給予初值。變量也沒有靜態類型,也不
會固定為某一類型。就一門最簡單的語言來看,我覺得數據類型無非就是字符串和數字類型
。
所以,kl的變量在某一時刻必然是數字,或者字符串。在腳本里,你無法獲知一個變量
的類型,事實上也沒這個必要。說變量擁有一個類型屬性,倒不如說值(value)有一種類型
屬性。
當字符串值與數字值參與運算時,如1+"a",其運算結果將自動轉換為字符串,也就是
"1a"。
一個只有標識符的語句(statement)通常意味著你想定義一個變量。這種無聊的手段通
常被用于定義全局變量。
運算符:
kl支持一般的C語言風格的算術、比較、邏輯運算符。例如加減乘除、大于小于、邏輯
與邏輯或。
作用域:
kl腳本里只有兩個作用域:全局的和局部的。
位于所有函數塊外的變量處于全局作用域;位于函數內的變量處于局部作用域,位于函
數塊內的代碼塊變量,還是處于局部作用域。
當局部作用域內出現一個全局里的同名變量時,優先取局部作用域里的變量。這同C語
言一樣。
控制語句if:
if的語法同C語言一樣,如:
if( a > 10 )
{
}
else
{
}
if( a > 10 )中的a>10被我成為條件語句,所有條件語句,包括下面的while,都不能
為字符串。例如if( "a" )將被視為非法語句。(我為什么要這樣考慮?- -!)
控制語句while:
c-like while:
while( a > 10 )
{
}
很遺憾,我暫時沒有加入對for的支持。因為我覺得既然有了while,有了循環控制,在
沒有更多無聊時間的前提下,我沒有必要加入for。
函數:
很遺憾,函數的定義和調用和C語言有點不一樣。這是因為kl沒有變量類型,那就意味
著函數定義如果和C語言一樣,就會出現語法歧義,如:
func( a )
{
}
就會和函數調用func(a)出現混淆。所以,我加入了function關鍵字。定義函數的語法
為:
function func( a, b )
{
}
如你所見,函數支持參數傳遞,當然也支持return a;返回值。kl是簡陋的,因為它沒
有指針之類的概念,所以你無法為函數傳遞一塊數據。當然,kl也不能像lua一樣讓函數可
以返回多個值。
函數調用的語法相對熟悉:
func( 1, 3 );
數組:
從一開始我就沒考慮為kl加入數組。事實證明加入數組是一個不明智的做法。數組的支
持讓代碼在很多地方變得臟亂。無論如何,kl后來支持一維數組了。為了讓代碼保持那么一
點點的干凈,我甚至為定義數組加入dim的關鍵字。這意味著,在kl里,數組和一般的變量
總有點不一樣:變量無需定義,數組卻必須事先定義。
數組的長度不支持動態擴充。如果支持,我得讓kl內部更好地去管理內存。
數組元素的類型沒有硬性的規定,這意味著a[0] = 1; a[1] = "a";是允許的。
語言特性上就描述這些,在本節末尾我決定貼一段kl計算階乘的代碼:
/* fac.kl */
function main()
{
n = input( "%d" );
print( "fac(" + n + ") = " + fac( n ) );
}
function fac( n )
{
if( n == 1 )
{
return 1;
}
else
{
return fac( n - 1 ) * n;
}
}