loop_in_codes

低调做技术__欢迎移步我的独立博客 codemaro.com 微博 kevinlynx

实现一种解释性脚本语言(二)

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;
    }
}

posted on 2009-03-06 16:01 Kevin Lynx 阅读(4541) 评论(9)  编辑 收藏 引用 所属分类: kl脚本实现编译原理

评论

# re: 实现一种解释性脚本语言(二) 2009-03-06 16:31 陈梓瀚(vczh)

类型可以这么处理。假设你要处理operator>,理论上operator>的类型是一个表。譬如说C++语言的话有
<int,int,bool>
<float,float,bool>
<char,char,bool>
......
<int,float,bool>
<float,int,bool>

只要最终匹配到了唯一的一个,那么就能够得到第三个项也就是operator>的类型了。如果匹配多个有可能是错误(譬如函数重载),匹配不到一定是错误。  回复  更多评论   

# re: 实现一种解释性脚本语言(二) 2009-03-06 16:36 陈梓瀚(vczh)

另外,既然是无类型的,那么我建议你把函数也作为值处理。譬如说
pair=func(a,b)
{
return func(c)
{
return c(a,b);
};
};

first=func(p)
{
return p(func(a,b){return a;});
};

second=func(p)
{
return p(func(a,b){return b;});
};

main=func()
{
p=pair(pair(1,2),pair(3,4));
print(second(first(p)));//输出3
};  回复  更多评论   

# re: 实现一种解释性脚本语言(二) 2009-03-06 16:37 陈梓瀚(vczh)

于是你有了这种叫closure的东西,做垃圾收集器吧。引用计数不行的。  回复  更多评论   

# re: 实现一种解释性脚本语言(二) 2009-03-06 18:54 空明流转

我觉得类型推导是一个以操作符为边的有向无环图。  回复  更多评论   

# re: 实现一种解释性脚本语言(二) 2009-03-06 21:00 陈梓瀚(vczh)

@空明流转
你这重要建模成类似int×float ==(operator>)=> bool的才行。工程意义不大。而且没什么理由无环。  回复  更多评论   

# re: 实现一种解释性脚本语言(二) 2011-07-22 00:10 thircese

@Kevin Lynx

"我为什么要这样考虑"
能否回答下?

"就会和函数调用func(a)出现混淆"
func(a)如果出现在全局范围,
则是函数定义, 否则,
出现在局部范围, 就是函数调用.
而且, 函数调用后面还有分号,
而函数定义没有.
为什么会混淆呢?
  回复  更多评论   

# re: 实现一种解释性脚本语言(二) 2011-07-22 09:05 Kevin Lynx

@thircese
大概是因为在全局范围内也能写下a = func()这样的语句。分号虽然能作为区分,但在很简单的语法分析算法中,是希望由最开头的token来确定后面跟的是什么样的语法。在具体实现时:
if (tok == TK_FUNCTION) 就可以简单地知道是函数定义,而不是在扫描完函数名、参数列表、括号后发现还有分号,才能确定是函数调用,这多少会加大实现的复杂度  回复  更多评论   

# re: 实现一种解释性脚本语言(二) 2011-07-22 14:13 plagiarism detection

Writing your academic assignments usually utilize plagiarism detector. It can save your good name!   回复  更多评论   

# re: 实现一种解释性脚本语言(二) 2011-07-22 16:43 thircese

@Kevin Lynx
原来是为了简单.  回复  更多评论   


只有注册用户登录后才能发表评论。
【推荐】超50万行VC++源码: 大型组态工控、电力仿真CAD与GIS源码库
网站导航: 博客园   IT新闻   BlogJava   知识库   博问   管理