VxMatScript语言帮助
VxMatScript脚本语言是本人独立开发的一个基于文本内容的实时解析的脚本语言。
3个月前,我本人还是一个零基础的C/C++的代码爱好者。
如果您想吐槽这个语言有多难用,请您先了解以下信息:
1、VxMatScript是我才花几天,用时不到1个月完全靠自己从0开始写出来的一门语言
2、我完全没有任何参照、参考、摘抄任何其它语言的代码,所有的代码全部都是我一个人从0开始写出来的!我甚至都没有看过任何一个语言的实现代码,因为我是真的看不懂。
3、我从c/c++零基础开始到写出来这个语言,也才用时不到3个月的时间!
4、我写下这个帮助并且发布第一个0.1版本的时间为2023年10月6日
VxMatScript语言的一些特性和帮助:(由于我不善于写文档,就先想到哪写到哪了)
1.每个语句由换行符结束,程序一定是自上而下逐一运行,包括自定义函数,也必须要在使用前定义,即定义语句一定要在使用前。
2.每行语句由 命令+空格+参数 组成,部分命令的空格可以用换行,即在下一行中写入参数内容
目前将命令类型分为3类,第1类是赋值类,第2类是其参数为字符串方式引用,第3类为其参数为运算表达式方式引用。每一类命令会根据其不同的类别对其参数进行不同方式的变量的引用方式的处理。
3.本语言的变量、赋值、字符串以及表达式的实现方式、条件语句判断以及分支方式、循环一般的语言的实现方式完全不一样,有自己独特的语法,使用时必须要遵守,否则可能会得不到所期待的结果!
4.变量名
(1)变量名不能有空格,名称中的空格会被删除
(2)变量名不能为数值,比如 123,123.4,-123.4,但如果是 123.4.5 可能是可以的,因为 123.4.5 不是合法的数值,名称校验模块就不会拦截。仅校验名称如果是合法数字就拦截,否则都可以做为变量名
(3)变量名不区分大小写
(4)在赋值语句中,变量名部分可以是静态的字符,也可以是一个引用其它变量值的字符串表达式,也可以是一个具有返回结果的一个代码段模块。
(5)变量名是可以动态拼接的:此功能应该是可以实现类似于数组等功能,甚至是一些很奇怪的功能。
i = 1
a[i] = 2 等同于 a1 = 2
(6)自定义函数实际上也只是内部的一个特殊的变量,它保存的就是这个函数的代码行文本内容。所以自定义函数也是随时可以改变的。
5.变量引用:有两种方式:在算术运算表达式中引用以及在字符串拼接运算表达式中引用
(1)在字符串拼接中引用:[变量名]
a=123
str b=ABC[a]DEF
此时 b 的内容就是ABC123DEF,如果A或F之后有空格,空格也都会保存在变量b里。
(2)在算术运算表达式中引用:不需要加方括号。如果变量值是数字,则加了方括号也可以得出结果,但如果变量值是另一个变量的名称,则如果加了方括号,就会引用另一个变量的值
a=1
b=2
c=a+b
c就等于1+2=3
str a=b
b=123
c=3
d=[a]+c,则就会计算 d=b+c,最终d=123+3=126
(3)除非是在text文本块定义赋值中,否则方括号引用方式在变量名和变量内容中都可以使用。
i=2
str b=abc
abc=3
a[i]=[b] 此处的a[i] 前面没有str命令,所以等号=后面的[b]实际上就会先被引用解析成abc,等同于
a2=abc 而abc实际上的值是3,所以
a[i]=[b] 就等同于 a2=abc,最终该语句就等同于 a2=3,即把3存入a2中。
(4)自定义函数的调用方式跟变量的引用一致。区别只是变量在引用时会直接返回其值,而函数在被引用时,会把其保存的值提交到核心里运行,并根据return返回的结果做为该引用的值。
6.每行语句的 “命令 空格 参数” 中的参数部分:参数至少有以下几种
(1)赋值语句
(2)表达式
(3)字符串
(4)由大括号{}分隔的语句模块
(5)空白
7.赋值语句格式:命令 变量名 =内容
内容里可以包含对变量或函数的引用,其引用方式根据命令的不同而不同。
8.字符串的定义和赋值
str 变量名=变量内容
(1)str命令不能省略
(2)等号后面的变量内容可能前后都会有空格,这些空格都不会被忽略
(3)变量内容不需要用双引号或单引号来分隔,如果输入了单引号或双引号,则这些引号都会完整的存入变量中
(4)变量内容如果需要拼接其它变量的内容,需要用方括号将该变量隔开,如
abc=000
str a=abc[abc]123
则a的内容就是 abc000123
(5)如果想在内容中包含有方括号,请用 \[和\] 代替
(6)特殊:如果在方括号前有\但并不想让它对方括号进行转义
a=123
b=abc\[a] 本意是想让 b=abc\123,但由于\[被转义,此时b实际上是等于 abc[a] ,其中的[a]并没有使用123替代,需要改成
c=\ 先将一个\存入c中
a=123
b=abc[c][a] 即可实现。
9.数值变量及表达式运算结果的赋值
var a=算术运算表达式
其中的var可以省略:在后续的版本中,如果加入了变量的作用域,则省略和不省略时,变量的作用域不一样:因为在自定义函数模块中,如果有var命令,则表示在函数中再定义一个变量,即使是在外部中已经存在有这个变量也不影响这个外部的变量,且新定义的变量在退出函数后就会销毁;而如果没有var,则表示如果在函数外部中已经定义过这个变量,则会修改这个外部变量,如果外部没有,就会在函数内部建立一个局部变量。写到这里的时候,想到有一个字符串定义赋值的BUG可能会存在于以后的有局部变量的版本中,此为后话了,因为现在咱这个版本还不支持局部变量作用域。
如果省略或使用var命令赋值,则表达式就会当成算术运算表达式进行计算,表达式中的每个元素都最终转成数字进行运算,如果该元素的值不是数字,则被转换成0代入进行运算。
var a=1
str b=c
c=2
d=a+[b]实际上就相当于
d=a+c
d=1+2 最终d=3
10.算术运算表达式:
按一般的算术优先级逐级进行运算,如
8-2*(3+4)^2
=8-2*7^2
=8-2*49
=8-98
=-90
11.字符串拼接表达式:
除了var和if等特殊标注的命令后面跟的是算术运算表达式之外,一般的命令后面跟的都是字符串拼接表达式,如
show 需要发送的内容[需要被引用的变量][自定义函数]....
str 变量名=字符串拼接表达式
12.由大括号{}分隔的语句模块:
{
命令语句 ...
...
return 算术运算表达式
returnstr 字符串拼接表达式
}
13.条件分支语句:此功能模块与一般的语言的实现方式不一样!
if a>b
iftrue 条件为真时运行的语句
iffalse 条件为真时运行的语句
iftrue和iffalse为命令名,跟随在if语句之后,可以多次出现,出现顺序也可以随意。
一般的语言的实现方式是
if (表达式)
{为真时运行的语句}
else
{为假时运行的语句}
格式是固定的,而本语言的方式是
if 表达式
iftrue {为真时执行的语句}
iftrue {为真时执行的语句} ...可以多次出现
iffalse {为真时运行的语句}...可以多次出现
如果忘记写iftrue或者是iffalse,则if后面的语句不管是真是假都会被执行。
iftrue或iffalse模块不是必须的,但如果全部都没有的话,那么if语句实际就没什么作用
由于判断字符串和数值的方式不一样,目前需要分开判断,不能写在同一个if语句里,比如可以先判断字符串:
compstr 字符串
ifmatch 匹配正则表达式
iftrue {
if 算术运算表达式
iftrue {
此处就相当于当字符串匹配并且算术表达式为真时运行的代码...
}
}
14.循环:
loop{
if 退出循环条件
iftrue break 或者是 return
...continue...
}
目前仅支持loop 这一种循环,必须要在循环内自己判断退出条件,并用 break 或 return或 returnstr退出循环。否则循环就不会停止。
15.自定义函数
自定义函数的定义一定要在使用之前。
fun testfun={
return 1+2+3
或 returnstr abc[a][b][c]
}
testfun //直接调用
a=1+2+testfun
16.赋值text数据
text abc={
此处内容可以是某个函数内执行的语句
...
}
17.将text或字符串转为函数
fun abcfun=[abc]
abcfun //调用
18.主要命令列表
(1)字符串赋值命令
str 变量名=字符串拼接表达式
(2)算术运算赋值表达式
var 变量名=算术运算表达式
(3)循环
loop{
if 退出循环条件
iftrue break
...continue...
}
(4)条件
if 算术运算表达式
compstr 字符串运算表达式
if= 字符串运算表达式 //判断compstr中被判断的字符串是否与当前字符串相等
if!= 字符串运算表达式 //判断compstr中被判断的字符串是否与当前字符串不相等
ifmatch 正则字符串
iftrue {以上条件判断为真时运行}
iffalse {以上条件判断为假时运行}
还有一些比如如果判断的字符串不区分大小写时,用
ifNcase=
ifNcase!=
等等。。。以后会根据情况陆续增加。
(5)从代码块中返回数据
{
return 算术运算表达式 //返回运算结果,该结果也是以字符串方式返回的,不管它的值是什么,即使是bool也是
returnstr 字符串运算表达式
}
任何一个由大括号{}分隔的代码块里面都可以有return命令,当return命令在if或loop循环体内时,它会逐层退出,直到它退出它最近的一层的自定义函数或者是自定义模块。
(6)直接把某个字符串变量里的内容当成自定义函数来运行
call 或者是run [变量名]
如果运行成功并有数据返回,则返回数据保存在[%%return]
19.关于代码块
不知道是否应该保留这一个功能。挺复杂的。
fun test={
{
代码块1
}
{
代码块2
}
str a=abc{
代码块3
returnstr 000
}123
show 在上面的代码块中含有return后,此行语句仍被运行
...后面的语句仍然被运行...
iftrue {
代码块4
returnstr 111
}
show 在代码块4中return后,此行语句不会被运行,因为iftrue代码块里的return被定义为退出它上一层的非if和非loop的代码块。
。。。后面的语句不会被运行...
}
每个代码块里如果有显式的return,则会返回return后面的结果,如果没有return,则默认会返回空白。
在代码块里的return,不会造成它外部的函数退出,即在上面的test函数中,代码块后面的show命令仍然会被运行。
20、变量的作用域:
变量支持作用域,需要根据表达式变量或者是字符串变量:
(1)在代码块里使用var命令定义的变量,该变量的有效范围为本代码块及本代码块中包含的子代码块;
(2)未使用var定义的变量,将往上寻找该变量的定义位置,如找不到,则在本代码块中等同于var定义;
(3)使用str和text定义并赋值的变量,均为本代码块中的局部变量,不会改写其上层代码块中的值;可能后续会在str和text定义中加入特殊的标识,用以识别该赋值的变量是否已在上层代码块中存在,如不存在才会在本地中建立,如存在则会在该代码块中赋值,类似于不使用var的表达式变量赋值;
(4)fun自定义函数的定义,永远都是最外层的
所以,会有可能出现,在funname1中重新定义funname1的代码体,然后在后续的访问该函数的过程中,访问到的都是最后定义的代码体,包括在函数体自身内。
fun test={
var i=1
var m=0
loop {
m=m+i
if i>=n
iftrue
break
i=i+1
}
sh 在test里循环完成后I的值:[i]
sh 在test里循环完成后m的值:[m]
return m
}
i=555
m=123
n=100
sh 1-100之和:[test]
sh test函数调用完成后I:[i]
sh test函数调用完成后M:[m]启动脚本任务:[31]
[31]在test里循环完成后I的值:100
[31]在test里循环完成后m的值:5050
[31]1-100之和:5050
[31]test函数调用完成后I:555
[31]test函数调用完成后M:123
[31]===脚本结束===
21、暂未实现自定义函数的参数传递
(1)在传递参数入函数之前,可以先定义多个外部变量,在函数内的第1行先将外部参数变量先在函数内部重新赋值,即可完成参数的传递;
(2)函数支持递归:由于支持了本地变量,递归就得以实现
由于递归所需要的特殊内存过多,并且此内存并不由操作系统的总内存来决定
所以,递归的层数有限,目前经测试可能只支持千次左右的递归调用。需合理使用。
转载请注明 : 文章转载自不了阁-飞哥 blog.forbs.cn
本站文章除注明转载/出处外,均为本站原创或翻译。若要转载务必注明出处,尊重他人劳动成果共创和谐网络环境。


