标题: 【cmd的未来】expr编写的可行性研究 [打印本页]
作者: plp626 时间: 2009-5-30 01:22 标题: 【cmd的未来】expr编写的可行性研究
为了让cmd对命令行的解释更加人性化,能处理接近于自然语言的中缀表达式,
expr.exe因此暂时将要诞生了(这个东西最终会越来越强大,强大到要替代cmd)
那么我们要解决那些问题?
我这里有个批处理版的:gcd子过程,以此为表达式要处理的问题作为例子
这个子过程用来求两个整数(包括负整数)最大公约数,用欧几里德算法递归实现, 可读性很差!
:gcd <integer> <integer> <ret> //code by plp626
setlocal & if %2 neq 0 (set/a p=%1%%%2) & if %1==0 (endlocal&set %3=%2&exit/b)
endlocal&(if %2==0 (set/a "%3=%1*(%1>>31)*2+%1") else call:gcd %2 %p% %3)&exit/b
为了便于大家理解,我把这个算法讲一下
关于两个数的最大公约数根据欧几里德辗转相除法,我们得到两个整数最大公约数的定义(递归定义)
设A,B是两个正整数,用(A,B)来表示它们的最大公约数
recursion : (A,B)=(B , A%B); //这里不必强调A,B那个绝对值大,即使B>A经过一次recursion后就变了
base case: (C,0)=|C| ; //C为整数
我们看c语言是怎么写的(可读性强):
int gcd(int a, int b){if (!b) return abs(a); else return (b,a%b);}
如果用expr我们设c为-24与256的最大公约数即c=gcd(-24,256)
命令行下键入expr c=gcd(-24, 256)搞定,这要们已经有gcd这个函数,如果没有这个函数
我们键入(由于cmd没有便利类型我们不必指定型参数据类型(但这要expr底层判断以便实现))
expr -def gcd(a, b){ if (!b) ret abs(a)) else ret gcd(b,a%b) } ;c=gcd(-24,256) ; //-def 开关表示我们要定义函数了
同gcc把那串C代码搞成汇编然后生成目标代码一样,我们要expr 去处理我们那串p语言,现在我们看看上面的
代码怎么一步一步分解,红色的字符就是我们的关键字,是expr要特别处理的字符
我们知道引号与空格的在命令行下的优先级仅次于%(cmd在处理时先把%预处理,然后再进行命令行操作)
引号与空格的优先级相同,那个在前面那个优先级高,当第一个双引号出现时,
为了匹配第二个引号,它不管后面的空格,当找到了第二个引号时,再找紧接着后面的参数
分隔符(“空格,;=”其中之一),找到后就是一个完整的参数(还有许多东西待研究,
我研究的方法就是printf("%s",argv[1]);printf("%c",argv[1][?]);来验证我的想法);
如果我们用纯p处理来写注意到p对参数空格的处理,想到加空格法,为了显示出空格字符我把上面的改写以便突出空格
expr -def gcd ( a , b ) { if ( ! b ) ret abs ( a ) else ret gcd ( b , a % b ) } ; c = gcd ( - 24 , 256 ) ;
"标准写法" expr 共接受到42个参数(expr 就是%0,cmd有shift可以处理任意多个参数),
所以需要有个预处理过程,来加上空格,我们用set %var:str1= str2 %来做,这里的
特殊字符有{} () % ,;= 我们用(这里我们还得要对,;=做特殊处理,因为cmd把它当作了参数分割符)
set s=%* & for %a in ({; }; ^(; ^); )do set s=!s:%a= %a !
可以做到,所以总的思路是:
加空格 》循环开始标志 》对%1的判断&shift 为空时endlocal &set .... 》分析优先级 》压栈 》出栈运算赋值》判断,执行命令》goto:循环
我们可以设定两个变量模拟栈空间,入栈,出栈,用set var=%s:~0,?%,
最后把我们要执行的操作命令存放在commond变量里,再设定一个临时变量储存运算的中间结果
对值得传递我们用endlocal & set %?=%返回值%
这中间有许多工作要做,对二元运算符,一元运算符优先级的处理,由于p处理没有数据类型+有可能也是变量,
如二元运算符-与命令行开关-混淆,许多,我想为了解决这些问题我们对变量的命名得有一地定的限制了
最后我们要面对的还有cmd最大递归层数1024,这严重影响了我们的信心
如果我们用C来写就要干脆些(现在又一次体会到C系统语言的称呼了),可是发现cmd对?的处理后
expr接收到的?后"失真"了(但这不是大问题),不管怎样方法还是得先把括号,关键字用
空格分开,以便分开参数,大家参考编译原理的词法分析器源代码,最后们还是
回避不开值的传递问题,我们遇到的障碍归根接地就是对system函数的问题,
那我们不用他了,自己写个试试
//题外话用free按钮也挺好的,便于大家阅读
[ 本帖最后由 plp626 于 2009-5-30 03:08 编辑 ]
作者: Batcher 时间: 2009-5-30 02:01
code标签没问题啊- gcd <integer> <integer> <ret> //code by plp626
- setlocal & if %2 neq 0 (set/a p=%1%%%2) & if %1==0 (endlocal&set %3=%2&exit/b)
- endlocal&(if %2==0 (set/a "%3=%1*(%1>>31)*2+%1") else call:gcd %2 %p% %3)&exit/b
复制代码
作者: zjw767676 时间: 2009-5-30 09:51
复制代码
[ 本帖最后由 zjw767676 于 2009-5-30 09:55 编辑 ]
作者: defanive 时间: 2009-5-30 09:57
想自写一个system啊,至少得先解剖掉cmd才行吧。。。
expr的难度非常高啊,还能够自定义函数了呢。。。
LZ不等于在做一种以批处理为内核的新语言形式?
作者: netbenton 时间: 2009-5-30 11:42
果真如此的话,绝对支持。
但想想,微软应该可以做到的,只是他们不这样做会不会有一定的原因呢?
作者: yslyxqysl 时间: 2009-5-30 11:45
微软似乎有点放弃cmd和vb的迹象,去开发语音和触控的了
作者: Batcher 时间: 2009-5-30 12:10
刚刚去看了看上学那会写的词法分析器,500+行C代码而已,语法分析器才400来行。当时确实花了不少精力来写,可惜最后只写完词法分析器和语法分析器就没有再继续下去了。一方面可能是学校教育体制问题,另一面就是自己心不够静,如果能坚持写完编译器就好了......转眼间几年时间过去了,不禁感概岁月蹉跎啊~
作者: plp626 时间: 2009-5-30 19:53
cmd的源代码应该能搞到,这个对ms并不是特别重要的东西,在google里搜索有不少相关网页,只是我的C语言还不到家。。。。。
我想到perl就可处理循环操作{if ... else ....} 而且也有开源代码,如果大家对linux在行(批处理之家有真的喜欢shell的基本对cmd就没了兴趣)里面那么多的开源代码,只要能想到的,理论上就能做到,如果愿意做,就成了
作者: defanive 时间: 2009-6-5 23:44
我在百度的结果已经基本上全部检索过了,没有cmd的源码。。。
google的结果是全球网页的吧,可能要好久的吧。。。
欢迎光临 批处理之家 (http://bbs.bathome.net/) |
Powered by Discuz! 7.2 |