Skip to content

Latest commit

 

History

History
596 lines (451 loc) · 11.9 KB

语法说明.md

File metadata and controls

596 lines (451 loc) · 11.9 KB

语法文件整体层次说明

script

一段能完整描述一个客服机器人的脚本被定义为scripts,一个scripts由多个function组成, 整个客服机器人的逻辑行为由function共同规约组成

function

描述客服机器人某种行为的一个集合,类似于编程语言中的函数。function主要有以下几种类型

constance

常量,用于描述客服机器人的一些基本信息,如机器人的名字,机器人的头像等 此处的常量声明后提供给全局使用,其语法如下

constance {
    const_name1 := <expression>
}

hello

如果存在hello function,机器人会在初始化时自动执行hello function中的逻辑, hello function的语法为

hello {
    command1
    command2
    ...
    commandN
}

chatbox

客服机器人的入口。在用户第一次同机器人对话时,或者用户在其它地方给出了非预期输出,脚本又没有对应的处理逻辑时,机器人都会选择chatbox中的逻辑进行处理。 chatbox语法为

chatbox {
    pattern1 => {
        command1
        command2
        ...
        commandN
    }
    pattern2 => {
        command1
        command2
        ...
        commandN
    }
    ...
    default => {
        command1
        command2
        ...
        commandN
    }
}

示例如下:

chatbox {
    "你的性别是什么?" => {
        say "我是一个男孩子"
    }
    "你的名字是什么?" => {
        say "我叫小明"
    }
    default => {
        say "我不知道你在说什么,请你问我其它问题"
    }
}

chatbox本质上为一个分支选择语句,当用户输入的内容与某个分支的匹配时,机器人会执行该分支的逻辑,如果没有匹配的分支,机器人会执行default分支的逻辑,此处的default必须存在,且default为最后一个分支。如果default不为最后一个分支,则会报错。

topic

topic用于描述客服机器人谈论的一个话题,里面包含一系列指令序列,语法为

topic ID {
    command1
    command2
    ...
    commandN
}

示意如下

topic introduction {
    say "你好,我是小明"
    say "我是一个机器人"
    say "我可以回答你的问题"
    goto question
}

topic后需要跟随一个主题名,命名要求为字母开头,字母数字下划线组成,topic的主题名不能重复,否则会报错。topic的主题名可以在其它地方被引用,如上面的示例中,goto后跟随的就是一个topic的主题名。topic中的指令序列可以是任意的command,如say,goto,set等。

command

command是客服机器人的最小执行单元,command包含以下几种类型

say

客服机器人最基本的功能,表示机器人向用户输出一段文字,其语法如下

say <expression>

expression为一个表达式,程序会计算表达式的值,并将其结果对应的字符串输出 示例如下

say "你好,我是小明"
say 3+5
say hello_string
say `当前你的余额为${balance}元`

此处的"表达式"不仅仅是数学表达式,还可以是字符串,变量等,具体见表达式介绍

goto

goto用于跳转到某个topic,其语法如下

goto <topic_name>

如,我们想跳转到名为introduction的topic,可以这样写

goto introduction

goto后跟随的topic_name必须为在同一script出现过的topic名称,否则会报错

menu

menu用于向用户展示一个菜单,用户可以从菜单中选择一个选项,其语法如下

menu {
    "option1" => {
        command1
        command2
        ...
        commandN
    }
    "option2" => {
        command1
        command2
        ...
        commandN
    }
}

其中,选项显示的名称需要用双引号括起来,选项的内容为一个command序列,用户选择某个选项后,机器人会执行该选项对应的command序列。示例如下

menu {
    "我想要充值" => {
        say "请问你想充值多少钱?"
        goto recharge
    }
    "我想要提现" => {
        say "请问你想提现多少钱?"
        goto withdraw
    }
}

fetch

fetch用于向对应的url发送GET请求,其语法如下

fetch <url> => <variable_name>

其中,url为一个字符串,variable_name为一个变量名,fetch会将url对应的内容保存到variable_name对应的变量中,示例如下

fetch "http://api.myweb.com/info" => person_info

url支持模板,如

fetch `http://api.myweb.com/info?name=${name}&age=${age}` => person_info

如果获取到的结果为json格式,可以用.操作符获取对应的字段,如

fetch "http://api.myweb.com/info" => person_info
say `你的名字是${person_info.name}`

当然,也可以直接输出person_info,此时会将person_info转换为字符串后输出

post

post用于向对应的url发送POST请求,其语法如下

post <variable_name> => <url>

其中,variable_name会被转换为字符串发送

POST的响应结果会被返回存到 variable_name中,作用域为本地。

需要注意的是,回传结果作用域仅限于本花括号作用域。

set

set用于设置变量的值,其语法如下

# 声明并赋值
set <variable_name> := <expression>
# 仅赋值
set <variable_name> = <expression>

变量的作用域在对应的花括号包裹范围内,示例如下

{
    set name := "小明"
    say `你好,${name}`
    set name = "小红"
    say `你好,${name}`
}

只有在变量设置之后才能访问对应变量 你也可以加global关键字,将变量设置为全局变量,示例如下

{
    set global name := "小明"
    say `你好,${name}`
    set global name = "小红"
    say `你好,${name}`
}

这样子变量的作用域就变成了整个script

input

input用于获取用户输入,其语法如下

input <variable_name> <assertion> <when_silence>

其中,variable_name为变量名,assertion为断言,when_silence为用户长时间不说话时执行的操作 除了variable_name外,其它两个参数都可以省略

assertion

assertion为一个表达式,用于判断用户输入是否合法,如果用户输入不合法,机器人会一直要求用户重新输入,直到用户输入合法为止。示例如下

input name assert name <> ""

如果用户输入为空,则会一直要求用户重新输入,直到用户输入不为空为止 assert语句可以不存在,assert后跟着的表达式需要为逻辑表达式,如果表达式的值为true,则表示用户输入合法,否则表示用户输入不合法,不存在assert时默认所有输入均合法

when silence

when silence子句的对应语法如下

when silence <expression> => {
    command1
    command2
    ...
    commandN
}

当用户一段时间不说话时,机器人会执行when silence子句中的逻辑 用户说话的时间长短由expression计算得来,单位是秒,示例如下

input name when silence 10 => {
    say "你好像不想说话了"
    goto end
}

match

match用于匹配用户输入,并决定下一步行为,其语法如下

match input {
    pattern1 => {
        command1
        command2
        ...
        commandN
    }
    pattern2 => {
        command1
        command2
        ...
        commandN
    }
    ...
    default => {
        command1
        command2
        ...
        commandN
    }
}

其中, pattern表示一个正则表达式,当用户输入匹配时,机器人会执行对应的command序列,如果没有匹配的pattern,机器人会执行default分支的command序列,此处的default必须存在,且default为最后一个分支。如果default不为最后一个分支,则会报错。 同理,这里的input后还可以跟上when silence子句,示例如下

match input {
    "你的性别是什么?" => {
        say "我是一个男孩子"
    }
    "你的名字是什么?" => {
        say "我叫小明"
    }
    default => {
        say "我不知道你在说什么,请你问我其它问题"
        continue
    }
} when silence 10 => {
    say "你好像不想说话了"
    goto end
}

在match中,还可以同上使用continue,这会让机器人重新进入match的匹配流程,同时将计时器置零。

if

if用于判断某个条件是否成立,其语法如下

if <expression> => {
    command1
    command2
    ...
    commandN
}

当然,if也可以加else分支和elif分支,示例如下

if <expression> => {
    command1
    command2
    ...
    commandN
} elif <expression> => {
    command1
    command2
    ...
    commandN
} else => {
    command1
    command2
    ...
    commandN
}

loop

loop用于循环执行某个指令序列,其语法如下

loop {
    command1
    command2
    ...
    commandN
}

此时loop会进入死循环,如果想要跳出循环,可以使用break指令,示例如下

loop {
    say "你好"
    break
}

如果想要跳过本次循环,可以使用continue指令,示例如下

loop {
    say "你好"
    continue
    say "我不好"
}

在这种情况下,say "我不好"永远不会被执行

条件循环

loop可以加条件,示例如下

loop when <expression> {
    command1
    command2
    ...
    commandN
}

此时,当expression为true时,会执行command序列,否则不会执行

expression

在该脚本语言中,表达式被分为以下几种类型

变量名与常量名

同其它编程语言一样,变量名与常量名也是一种表达式,他们对应了一个值,示例如下

name
age
balance

你可以用set命令为变量赋值,示例如下

set name := "小明"
set age := 18
set balance := 100

常量表达式

常量表达式为一个常量,常量可以是字符串,数字,布尔值,null等,示例如下

"hello world"
3.14
true
null

只要是合法的javascript常量,都可以作为常量表达式 当然,同样可以为json对象,示例如下

{
    "name": "小明",
    "age": 18
}

同时,常量表达式也可以是一个数组,示例如下

[1,2,3,4,5]

算术表达式

算术表达式为一个算术运算,示例如下

1+2
3-4
5*6
7/8
9%10

算术表达式中可以使用括号,示例如下

(1+2)*3

逻辑表达式

逻辑表达式为一个逻辑运算,主要有关键字AND,OR和NOT示例如下

true and false
true or false
not true

同样,逻辑表达式可以使用括号,AND为与运算,OR为或运算,NOT为非运算 其计算结果为一个bool类型变量

比较表达式

比较表达式为一个比较运算,示例如下

1 == 2
1 != 2
1 > 2
1 < 2
1 >= 2
1 <= 2

比较表达式的计算结果为一个bool类型变量

后缀表达式

后缀表达式主要包括下标表达式和成员访问表达式。

下标表达式主要用于访问数组成员,示例如下

set arr := [1,2,3,4,5]
say arr[0]

成员访问表达式主要用于访问对象成员,示例如下

set obj := {
    "name": "小明",
    "age": 18
}
say obj.name

需要注意的是,目前的表达式不支持链式访问,如obj.name.age这种形式,故只能如下访问

set tmp := result.lives
set info := tmp[0]
set temp := info.temperature
say `现在的温度为${temp}`

同时,也不支持后缀表达式作为左值。如

set obj := {
    "name": "小明",
    "age": 18
}
set obj.name = "小红"

这种形式是不支持的。

模板字符串

模板字符串为一个字符串,其中可以包含变量,示例如下

`你好,${name}`

模板字符串中的变量会被替换为对应的值,示例如下

set name := "小明"
say `你好,${name}`

这时候的输出为"你好,小明"