FlowG语言

2020-10-14  本文已影响0人  科研者

FlowG语言 是专为 FlowG框架 设计的形象化流程描述语言,尽管如此,FlowG语言仍具一定的普适性,适合绝大多数面向流程编程的框架。本文主讲 FlowG语言的设计及定义。

目录

内容

1. 语言能表达的内容

2. 元素标识符的意义

最终决定,FlowG语言采用 方案2

3. FlowG语言的示例

下面是 FlowG语言的示例:

node1 = NodeA[]   //创建 NodeA 类型的节点 node1
node2 = NodeB[key1=2,key2=true,key3="这是字符串"]   //创建 NodeB 类型的节点 node2,并给 NodeB 类传递选项(参数)
pipe1 = PipeA[]    //创建 PipeA 类型的管道 pipe1

/*
定义流程:node1的默认输出端口  连接到 管道 pipe1,管道 pipe1 连接到 node2 的输入端口 A,node2的输出端口 A 连接到 NodeC 类型的匿名节点
*/
node1 -> pipe1 -> A<:node2:>A -> NodeC[] -> node3


/*
定义包装元素 packNode,其包装流程是:节点 nodeA 的默认输出端口 连接到 nodeB 的默认输入端口,nodeB 的默认输出端口连接到管道 pipeA,pipeA 又连接到 节点 nodeC 的默认输入端口
*/
flow packNode {
    nodeA->nodeB->pipeA->nodeC
}

/*
定义流程:node2的输出端口 B 连接到管道 pipe2,管道 pipe2 连接到 包装元素 packNode ,包装元素 packNode 又分别连接到 节点 node3 的输入端口 B  和 节点 node4 的默认输入端口,节点 node3 的默认输出端口 和 节点 node4 的输出端口 A 都连接到了 由类型 NodeX 创建的 id 为 'node5' 的默认输入端口
*/
node2:>B -> pipe2 -> packNode -> {B<:node3,node4:>A} -> NodeX[id='node5']

这个示例描述的流程如下:


FlowG语言示例

其中 n1 表示 node1p1 表示 pipe1

4. FlowG语言的语法定义

为了规范、表达清晰 和 将来更方便地开发语法解析器,FlowG语言采用 EBNF范式 描述 FlowG语言的文法。

关于 EBNF 的详细信息,请看语法格式描述规范BNF、EBNF、ABNF

语句列表 = [ 语句 [ ';' ] 语句列表 ] ;(*语句以分号结束*)
语句 = 元素定义 | 关系语句 | 流程定义
流程定义 = 'flow' [名字] '{' 语句列表 '}' ;(*定义流程;Name 是流程的名字*)
元素定义 = 名字 [ (赋值符 | 默认值赋值符)  元素创建 ] ;(*有两种赋值方式*)
赋值符 = '='  ;(*将右值直接赋给左值*)
默认值赋值符 = '?='  ;(*只有当 左值 不存在时,才将右值接赋给左值*)
元素创建 = 类型 , 哈唏表 ;(*通过在类型后面加 [key=value] 的方式来调用类型的构建函数并给其传参数 来创建类型的实例 *)


哈唏表 = '[' [ 键值对列表 ] ']' ;(*带有一系列键值对的数据结构*)
键值对列表 = 键 '=' 值 [ ',' 键值对列表 ]
键 = 标识符
值 = 名字 | 字符串 | 数字 | 布尔 | 哈唏表

关系语句 = [ 元素|元素列表 ] 关系右值 {关系右值}  ;(*关系语句会将关系分别映射到元素 或 元素列表中的每一个元素上*)
关系右值 = '->' (元素|元素列表)  ;(*关系会分别映射到元素 或 元素列表中的每一个元素上*)
元素 = { 输入端口 } 名字 { 输出端口 }   ;(*元素可以指定输入端口 和 输出端口,输入端口写在节点的前端,输出端口写在节点的后面*)
输入端口 = 端口 '<:'  ;(*输入端口和节点的分隔符是 <: *)
输出端口 = ':>' 端口  ;(*节点和输出端口的分隔符是 :> *)
端口 = 名字

元素列表 = ’{' [元素序列] '}'   ;(*元素列表表示一组元素,元素与元素之间用 逗号 分隔*)
元素序列 = 元素 {',' 元素 }    ;(*元素与元素之间用 逗号 分隔*)


类型 = 名字
名字 = 标识符


注释 = 行注释 | 注释块
行注释 = '//' {Unicode字符}  ;(*单行注释*)
注释块 = '/*' { Unicode字符|换行符 }  '*/'  ;(*多行注释*)


标识符 = 字母 { 字母 | 数字 }
字母 = Unicode字母 | "_"
数字 = "0" … "9"
Unicode字母 = (* 类型为“字母”的Unicode解码点 *)


字符串 = 双引号字符串 | 单引号字符串
双引号字符串 = '"'...'"'
单引号字符串 = '''...'''

数字 = Unicode数字...

布尔 = 'true' | 'false'

5. 字符

具体的Unicode字符类别由以下术语表示:

换行符 = (* 即Unicode码点U+000A *)
Unicode字符 = (* 除换行符之外的任意Unicode编码点 *)
Unicode字母 = (* 类型为“字母”的Unicode解码点 *)
Unicode数字 = (* 类型为“十二进制数字”的Unicode解码点 *)
空白符 = 空格U+0020 | 跨制表符U+0009 | 回车符U+000D | 换行符U+000A

6. 字母和数字

下划线字符_(U + 005F)被视为一个字母。

字母 = Unicode字母 | "_"
数字 = "0" … "9"

7. FlowG语言的词法定义

7.1. 注释

注释有两种形式:

注释不可嵌入。

注释 = 行注释 | 注释块
行注释 = '//' {Unicode字符}
注释块 = '/*' { Unicode字符|换行符 }  '*/'

7.2. 标记

标记是构成语言的词汇。它有多种类型:标识符、关键字、运算符 与 分隔符 以及 字面量。

空白符 包括 空格 U+0020、跨制表符 U+0009、回车符 U+000D 和 换行符 U+000A,除非用它们来分隔会结合成一体的标记,否则将被忽略。从而,换行符 或 EOF(文件结束符)会触发分号的插入。把输入分解为标记时,可形成有效标记的最大化字符序列将作为下一个标记。

标记 = 标识符 | 关键字 | 运算符 | 分隔符 | 字面量

7.3. 分号

分号 ; 作为一条语句的终结符,但在没有歧义的情况下可省略;

7.4. 标识符

标识符命名程序实体。标识符是一个或多个字母和数字的序列。标识符中的第一个字符必须是字母。

标识符 = 字母 { 字母 | 数字 }

示例:

g
_g3
GuoBinYong
g_by
αβ

7.5. 关键字

以下关键字是保留关键字,不能用作标识符。

关键字 = 'flow'

7.6. 运算符

运算符 = '{' | '}' | '->' | '[' | ']' | ':' | '=' '?='

7.7. 字符串

由 单引号 '...' 或 双引号 "..." 包围的标识符称为字符串

字符串 = 双引号字符串 | 单引号字符串
双引号字符串 = '"'...'"'
单引号字符串 = '''...'''

7.8. 数字

以 Unicode数字 开头的标识符 都称为数字;

数字 = Unicode数字...

7.9. 布尔

布尔 = 'true' | 'false'

8. FlowG语言的语义定义

词法定义、语法定义都有了,为了接下来的语义分析并生成目标语言,还需要定义FlowG语言的属性文法,但由于时间关系,日后再来完善这块。

上一篇 下一篇

猜你喜欢

热点阅读