在C语言中存在一种选择运算符:? ... : ... 该类运算符可以代替if...else...结构,让语句更加简短,本节v1.0.6的版本就来添加这种运算符,同时还添加了endswitch和 endclass两个关键字,endsw...

    在C语言中存在一种选择运算符:? ... : ... 该类运算符可以代替if...else...结构,让语句更加简短,本节v1.0.6的版本就来添加这种运算符,同时还添加了endswitch和 endclass两个关键字,endswitch等价于endswt ,endclass等价于endcls 。

    下载地址:http://pan.baidu.com/share/link?shareid=414251&uk=940392313 (此为百度盘的共享链接地址),进入v1.0.6的共享文件夹中,在该目录下有两个代码压缩包:zengl_lang_v1.0.6_forXP.rar (XP系统下的vs2008解决方案和源代码),zengl_language_v1.0.6_forLinux.tar.gz (Linux系统下的源代码和makefile)

    SourceForge.net上的仓库地址为:https://sourceforge.net/projects/zengl/files/  从里面可以看到各个版本的代码压缩包,比如本节的zengl_lang_v1.0.6_forXP.rar zengl_language_v1.0.6_forLinux.tar.gz

    v1.0.6-v1.0.5-diffs.txt(v1.0.6和v1.0.5版本的代码变化情况)文件放在zengl_lang_v1.0.6_forXP.rar压缩包里,同时zl.stx(本版本的editplus语法高亮文件,其中包含高亮各个模块的函数和关键词等信息)也放在该压缩包中。至于zl.stx的用法请查看前面的"zengl编程语言 中序"的文章。

    先来看下本版本的描述(在linux代码包里的usage.txt里有这段描述,v1.0.6-v1.0.5-diffs.txt和git log中也有这段描述):

    zengl v1.0.6的版本,该版本增加了问号冒号的选择运算符,同时增加了endswitch和endclass两个关键字,endswitch等价于endswt,endclass等价于endcls
   
    在main.c词法扫描阶段增加了问号运算符的解析,冒号运算符在以前就添加过,之前冒号运算符只用于switch case结构中,现在增加问号运算符后,就可以和问号构成条件选择语句,例如c=a>b?a:b这条语句就是从a,b中获取最大的值赋值给c
   
    另外在main.c中的reserves数组中还添加了endswitch和endclass两个关键字,这两个关键字在词法扫描时会通过 lookupReserve函数转为endswt和endcls的token值,所以endswitch关键字等价于endswt关键字,而 endclass则等价于endcls,之所以添加这两个关键字,是因为有的用户觉得endswt和endcls不好看,也不好记,之所以继续保留 endswt和endcls是为了和原来的脚本相兼容。所以你既可以使用endswt也可以使用endswitch,endcls同理。
   
    在parser.c语法解析文件中,添加了问号和冒号运算符的优先级。问号冒号选择运算符的优先级比赋值和逗号的优先级高,比其他运算符的优先级低,所以 如果问号冒号中间的表达式有赋值语句时,需要使用括号将赋值语句括起来,例如:a>b?(c=a):c=b这个表达式中间(c=a)就用括号括起来 了,c=b这句里的赋值语句因为在冒号的右侧所以优先级比冒号高,所以无需使用括号,其实如果记不清楚,就都用括号括起来即可。
   
    问号冒号的语法和c语言的差不多。
   
    在assemble.c文件里对应添加了问号冒号运算符的汇编代码。
   
    global.h头文件中添加了和问号冒号有关的一些宏定义。
   
    zenglrun根目录下的test.zl是问号冒号的测试脚本,里面有问号冒号的几条测试语句,包括在问号冒号中再嵌套问号冒号的写法。
   
    另外在gui_Tetris目录中的俄罗斯方块脚本tetris.zl中将两个if...else...endif结构使用问号冒号结构来代替,同时将 tetris.zl和tetris_def.zl两个脚本中的endswt和endcls关键字使用endswitch和endclass来代替。
   
    具体的改动请使用git log -p或gitk等软件来查看。

    作者:zenglong
    时间:2013年4月24日
    官网:www.zengl.com

    测试脚本test.zl的代码如下:

def KeyDown 274;

class clsTetris
    direct;
    speed;
endcls

fun test(str,ret)
    print str + ' in test fun!';
    return ret;
endfun
c = 17;
d = 3.14159;
a = c > d ?  test(c + ' > ' + d,c) :  test(c + ' < ' + d,d); //问号冒号测试
print 'max is ' + a;
c = 3;
d = 7;
a = c > d ?  test(c + ' > ' + d,c) :  test(c + ' < ' + d,d); //问号冒号测试
print 'max is ' + a;
c = 3;
d = 2;
m = 5;
a = c > d ?  (test(c + ' > ' + d,c) > m ? test(c + ' > ' + m,c) :  test(c + ' < ' + m,m)) :
    (test(c + ' < ' + d,d) > m ? test(d + ' > ' + m,d) :  test(d + ' < ' + m,m)); //问号冒号的嵌套测试
print 'c d m max is ' + a;
c = 4.569;
d = 18;
m = 50.153;
a = c > d ?  (test(c + ' > ' + d,c) > m ? test(c + ' > ' + m,c) :  test(c + ' < ' + m,m)) :
    (test(c + ' < ' + d,d) > m ? test(d + ' > ' + m,d) :  test(d + ' < ' + m,m)); //问号冒号的嵌套测试
print 'c d m max is ' + a;

clsTetris tetris;
//tetris.direct = KeyDown;
tetris.direct = 274;
tetris.speed = tetris.direct == KeyDown ? 2 : 1; //问号冒号测试
print 'direct: ' + tetris.direct + ' speed: ' + tetris.speed;
mixvy = -1;
vy = 5;
print 'mixvy: ' + mixvy;
mixvy == -1 ? (topvy = mixvy = vy) : topvy = vy;  //问号冒号测试,注意中间的(topvy = mixvy = vy)需要用括号括起来,否则会出现语法错误。因为前面说过冒号的优先级比左侧的赋值符优先级高。
print 'mixvy: ' + mixvy + ' topvy: ' + topvy + ' vy: ' + vy;
mixvy = -1;
vy = 5;
print 'mixvy: ' + mixvy;
topvy = mixvy == -1 ? (mixvy = vy) : vy; //问号冒号测试,注意中间的括号
print 'mixvy: ' + mixvy + ' topvy: ' + topvy + ' vy: ' + vy;
mixvy = -1;
topvy = mixvy == -1 ? c + d /4 + 5 : vy; //问号冒号测试
print 'mixvy: ' + mixvy + ' topvy: ' + topvy + ' vy: ' + vy;

m = 12;
switch(m)
case 11:
    print 'you are right 11';
    break;
default:
    print 'you are wrong ' + m;
endswitch //测试endswitch关键字

    上面的代码中绿色的注释是原脚本中的,棕色的注释是这里额外添加的需要注意的地方,运行截图如下:

    在gui_Tetris/tetris.zl俄罗斯方块的游戏脚本中,对两处if...else...endif结构使用问号冒号选择结构来代替:

/*if(tetris.direct == KeyDown) //如果按了下方向键,则设置初始速度为2,即每次移动两格来加速下落。
      tetris.speed = 2;
else
      tetris.speed = 1; //否则按照常规的1格速度。
endif*/

tetris.speed = tetris.direct == KeyDown ? 2 : 1; //使用问号冒号结构来代替上面的if..endif的写法,两种做法都可以。

/*if(mixvy == -1) //mixvy是需要消除的最低下的行
    topvy = mixvy = vy;
else
    topvy = vy; //topvy是需要消除的最上端的行
endif*/

topvy = mixvy == -1 ? (mixvy = vy): vy; //使用问号冒号结构来代替上面的if...endif的写法,因为问号,冒号的优先级比赋值语句的优先级高,所以? ... :中间的语句如果有赋值运算符,就需要用括号括起来,如本句的 ... ? (mixvy = vy): ...

    具体的C文件代码部分,请结合源代码中的注释,再加上git工具以及vs2008或者eclipse+CDT插件或者gcc,gdb等工具进行分析。

    在Debug配置下,请确保在zenglrun项目属性的配置里,命令行参数配置的是test.zl -d -s -p (问号冒号的测试脚本) 或者 gui_Tetris/tetris.zl -d -s -p (俄罗斯方块游戏脚本)

    在Release配置下,确保在zenglrun项目属性的配置里,命令行参数配置的是test.zl -n -p 或者 gui_Tetris/tetris.zl -n -p

    对于vs2008的用户,我在项目属性里:[配置属性>>>>C/C++ >>>> 高级] 部分设置了禁用特定警告:4013,4715,4996 ,这几个警告会显示一些某某函数是非安全的函数,或者函数没有返回值等,这里禁用掉,防止出现过多的警告。另外还有个警告是显示某某变量没被使用过的, 这个警告我没禁用,可以不用管它。我最开始是在Linux系统中使用eclipse+CDT插件以及gcc等开发的zengl ,在我的GCC下面并没有显示过这些讨厌的警告,所以就没处理,不过还好这些警告都无关痛痒,无需理会。
    还有一个地方:VS2008项目中,在[配置属性>>>> C/C++ >>>> 预处理器] 部分都设置了预处理器定义的宏:OS_IN_WINDOWS ,之所以需要OS_IN_WINDOWS,是因为源代码既要在WINDOWS下编译,又要在LINUX下编译,所以需要通过这个宏来告诉编译器当前的环境 是windows还是linux,在windows下面,会加入一些和windows平台相关的特性,另外,zenglrun项目里设置了很多SDL相关 的依赖库,头文件等信息。
    Release版本的程序是采用/MT多线程运行时编译的,所以可以直接在别的没有安装调试工具的电脑上运行。

    linux系统下的用户请结合usage.txt的说明,先运行make clean 将原来生成的libzengl.so zenglrun 和 func.o run.o debug.o builtin.o sdlLib.o文件删除。

    再运行make

    生成libzengl.so zenglrun 和 func.o run.o debug.o builtin.o sdlLib.o。(在生成过程中如果出现一些警告,暂不管他)

    最后运行 ./zenglrun test.zl (运行问号冒号测试脚本) 或./zenglrun gui_Tetris/tetris.zl(运行俄罗斯方块游戏脚本) 直接编译运行,如果要调试可以在后面加个-d参数。使用-h来查看所有可用的参数,参数都必须放在脚本文件名后面。

    最后的最后,如果转载请注明来源 www.zengl.com , OK , 先到这里,休息,休息一下 O(∩_∩)O~

上下篇

下一篇: zengl v1.2.0 嵌入式编程语言

上一篇: zengl编程语言v1.0.5 编译,执行,源码调试一体化,开发俄罗斯方块

相关文章

zengl v1.8.3 修复ReUse接口缺陷及段错误,完善语法检测,使用Android Studio开发android项目

zengl v1.2.1 修复函数调用BUG

v1.3.1 Android编译执行zengl脚本

zengl编程语言v0.0.21汇编级调试

zengl v1.6.0-v1.7.1, zenglServer v0.1.0

zengl编程语言v0.0.10实现流程嵌入结构