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