使用markdown文档定义的poplang中文编译器(对话agent)
Poplang是OPCode Oriented Programming(即:面向opcode操作码编程语言)。语法简单,一行语句即是一个poplang编程语言代码行。
注:opcode是操作码,或者函数名。opval1-opval3等等即是操作的参数值,每一个参数均是可选的。可以是0-N个。
举例:
上面这句代码说的是:c = a + b ,即将a和b的和,存入到变量c中。
注:set即是赋值声明的opcode操作码,val是一个变量。constant是一个常量,例如数字、字符串、JSON对象。这里constant只能是常量,不能是变量
举例:
注:设置a的值为1,此语句是正确的
错误的用法:
注:b不能是变量,所以这个语句是错误的
设置b为JSON值。JSON属性name的值为"this is a string"。代码行中的"**"定义了字符串常量:从"**"之后的字符串常量值均为b的值。这里因为该字符串是JSON,故自动转化为JSON对象并赋值给b。
注:{这是一个字符串}本身是不需要使用双引号和单引号包裹字符串常量的。这里不要参考其他编程语言。假如字符串包含了空格或者其它不可见的字符,可以使用JSON对象赋值方式:例如 set obj **{"str":"this is a string"},然后通过后续提到的object.get来得到str字符串的值;或者使用set str **this is a string来字符包含空格的字符串:"**"代表了从此开始到行结束均是字符串的内容。
注:"**"代表从此开始至代码行结束,均是该str变量的字符串的值:这是一个带空格 的字符串常量
错误的用法:
正确的用法如下:
注:那么我们将得到user_name是:lee code
或者使用对象变量user_obj的属性user_name来实现,如下:
set user_obj **{"user_name":"lee code"}
object.get user_obj.user_name user_name
注:上面两行poplang代码运行后user_name的值为:lee code
错误的用法:
注:这里的opcode操作码是==,第二个参数**street只能是变量名,不能认为是字符串:street
修改后正确的用法:
set str2 **street is road 100
== str str2 result
注:先使用set语句来实现str2的字符串值为:street is road 100。再使用==逻辑判断str与str2是否相等,结果存于result变量中。
错误的用法举例如下:
注:字符串常量"**正确"、"**不正确"不能用于?=条件运算符中。
修正后正确的用法:
set reult_ok **正确
set result_notok **不正确
?= a result_ok result_notok result
举例1:
将变量c的值赋值给变量a
语法1:
注:判断是否a小于b,将比较的结果赋值给c
语法2:
注:判断是否a与b相等,将比较的结果赋值给c
语法3:
注:判断是否a大于b,将比较的结果赋值给c
语法4:
注:判断是否a不等于b,将比较的结果赋值给c
语法5:
注:将a的值逻辑取非得到的结果赋值给b
语法6:数值运算
+ a b c
- a b c
* a b c
/ a b c
% a b c
注:以上的+、-、*、/分别指加减乘除的opcode操作码。%是指整数取模,例如9%10的结果为9。
语法7:逻辑运算
|| a b c
&& a b c
> a b c
>= a b c
< a b c
<= a b c
== a b c
注:以上是将a与b进行逻辑opcode操作,结果赋值给c。
例如:&& a b c,其中a的值为真,b的值为假,则c的结果是真&&假,运行结果:c被赋值为假。
语法8:条件运算
注:判断a是否为真,给d赋值为b或c变量的值。1,如果a值是逻辑真,将变量变量b的值赋值给变量d;如果a值是逻辑假,将变量变量c的值赋值给变量d。这里的a、b、c、d均是变量,不能是opcode操作码、且均不能是**开头的字符串常量、并且不能是数值常量、并且不能是逻辑真与假的常量true或常量false。
语法9:位运算
| a b c # 按位或
& a b c # 按位与
^ a b c # 按位异或XOR
<< a b c # 数位左移
>> a b c # 数位右移
~ a b # 按位取反,a的取反运算结果赋予变量c
注:其中,|、&、^、<<、>>分别为位运算中的按位或、按位与、按位异或、左移、右移,将变量a、变量b的位运算结果赋予变量c。最后"~ a b"中的"~"取反运算opcode操作码,是将变量a按位取反,将取反的位运算结果赋予b变量。
特别注意:上述运算类型的opcode操作码,只能对变量进行操作,不能对数值常量、字符串常量、opcode操作码进行操作。
注:object.get操作码可以读取obj对象的属性或属性的属性值,赋值给dst_val变量。
举例1:
读取对象变量a的属性名为b的值,再读取这个值的c属性值,存入到dst_val变量中。
举例2:
假如a对象是一个JSON:{"a":{"b":{"c":{"d":{"e":{"f":{"g":"这是a.b.c.d.e.f.g的字符串值"}}}}}}},运行结果为:val的值为:这是a.b.c.d.e.f.g的字符串值
注:object.set操作码可以设置obj的属性property_name1的子属性sub_property_name01的值为val
举例1:
假定obj的值为{}空对象,val的值为1,则运行后obj的值是:{"a":1}
举例2:
假定obj的值为{"a":{}},val的值为2,则运行后obj的值是:{"a":{"b":2}}
注:常量仅在以下操作码opcode中使用:set
举例错误的用法:
1、数字运算中错误使用常量
正确的用法:
set one 1 # 先将常量数值1保存在变量one中
+ i one i # +加法运算只能使用变量,不能使用常量
2、条件判断中错误使用常量
正确的用法:
pop.func.define func_name
opcode1 ...
opcode2 ...
...
pop.func.end
注:pop.func.define是函数声明的预编译指令(不是opcode操作码),func_name即是被定义的函数名。opcode1、opcode2等等代表了函数func_name内部的每一行poplang代码行。可以是1行或者多行poplang代码行。最终函数定义的结束的预编译指令是:pop.func.end。
函数调用的语法:
注:这是一个函数调用的poplang代码行,func_name即是被定义的函数名(也是opcode操作码)。这是其中一个调用方式。另外还可以在pop.do.while循环指令中使用。下面会讲到循环语句的使用。
错误的用法:
pop.func.define outer_func
pop.func.define inner_func
pop.func.end
inner_func
pop.func.end
注:这是错误的函数声明,函数声明是不能嵌套的。
正确的用法:
pop.func.define inner_func
pop.func.end
pop.func.define outer_func
inner_func
pop.func.end
注:函数声明只能一个个来,并且被调用函数声明要在调用函数之前。
循环语句可用于执行条件循环,例如从1计算到100的和。
其中,pop.do.while是执行循环的opcode操作码,opcode是一个函数名或者操作码。先执行1次opcode,再判断flag是否为true。如果是true继续执行opcode,否则结束循环。
说明:# 是注释的操作码,代码本行代码不被poplang的代码执行器执行。用于注释代码给人类用户看。
注:pop.ifelse是条件判断的opcode操作码,这里的flag是条件判断的变量,当flag值为真时调用opcode_ok函数,当flag值为非时调用opcode_notok函数。opcode_ok函数中包含了poplang代码行,是flag为真时所执行的函数代码。opcode_notok函数中包含了poplang代码行,是flag为非时所执行的函数代码。pop.ifelse在poplang编程语言中只有这一种用法,没有其它的用法,不要使用其他编程语言的用法。
举例:使用pop.ifelse来判断flag的值,当为真时加1,当为非时加2。poplang代码如下。重点代码在:pop.ifelse flag opcode_ok opcode_notok。这行代码一行代码实现了判断flag实现opcode_ok和opcode_notokg函数的跳转。
set n 0
set max 100
# 定义函数opcode_ok:给n变量加上1pop.func.define opcode_ok
set one 1
+ n one n
pop.func.end
# 定义函数opcode_notok:用于检查n是否不为100pop.func.define opcode_notok
set two 1
+ n two n
pop.func.end
# flag为真,调用opcode_ok函数,加1set flag true
pop.ifelse flag opcode_ok opcode_notok # flag为非,调用opcode_notok,加2
! flag flag
pop.ifelse flag opcode_ok opcode_notok
# 此时,n的值为3(先加了1,再加上2)方法1:
注:new是创建数组对象的opcode操作码,array这个字符串,代表了new操作码创建的是array对象即数组对象。得到的新的数组对象默认保存在$ret变量中。
方法2:
注:使用set操作码opcode来给list变量赋值,将"**"后面的字符串转为JSON对象,即是一个数组对象,保存在list变量中。
7.2.1 数组的下标值的设置
注:array.set是数组元素位置i的值赋值操作码opcode,将val保存到list数组下标为i变量值的对象中。例如i变量的值为0,则说明将list[0]的值设置为val变量的值。
7.2.2 的元素的读取
注:array.get是数组元素位置i变量下的值的读取的操作码opcode,将list[i]的值存入到变量val中。
举例:
set list **[3,100,5,92]
set i 1
array.get list i val
# 此时结果:val的值为list[1],即100。set val 87
set i 2
array.set list i val
# 此时结果,list[i]的值被设置为新的val值即87,i为2。即:list[2]的值87。list数组为:[3,100,87,92]下面我们使用一个代码块,来解释如何使用poplang编程实现1+2+3一直加到100的结果。
set sum 0
set one 1
set n 1
set max 100
set flag true
# 定义了一个计算1-100的函数:addTo100pop.func.define addTo100
+ sum n sum
+ n one n
!= n 100 flag
pop.func.end
# 计算从1-100,直到n为100时退出循环pop.do.while flag addTo100
上述poplang代码行被poplang执行器逐句分析并执行,最终得到了结果:sum的值为5050。
set sum 0
set one 1
set n 1
set max 1000
set flag true
# 定义了一个计算1-1000的函数:addTo1000pop.func.define addTo1000
+ sum n sum
+ n one n
!= n max flag
pop.func.end
# 计算从1-1000,直到n为1000时退出循环pop.do.while flag addTo1000