1 个不稳定版本

0.1.0 2021年1月23日

#502配置

MPL-2.0 许可证

625KB
420

很久以前,在一个遥远的地方...

... JSON 是城里的热门话题。其语法 可以放在名片上,一切都很美好。

... 每个人都在使用 JSON,用于数据交换和配置——配置文件很小,一切都很美好。

但我们厌倦了使用 JSON。我们很沮丧,因为它不适合它未被设计的任务。而且一切不再那么好了。

但我们没有修复 JSON。有些人坚持不懈,有些人转向了新的语言。但这些语言变得疯狂。我们不仅修复了 JSON 的缺陷,而且走得太远了。

我不想要63种字符串类型,也不想要图灵完备性,我想要增加了便利性的 JSON。

而 GoFF 将让一切变得美好。

/ɡɒθ/

一种配置语言。

语法

-- This is a comment
-- It is the only type of comment.
-- Multiline comments can span multiple lines using multiple comments.

-- Goff has types:
: Network
server   = 'example.com' -- String
useProxy = no            -- Boolean
timeout  = 5             -- Integer
proxy    = Nothing       -- Nothing

: Developer
revision = 6.66 -- Real
license  = '
As long as you retain this notice you can do whatever you want with this stuff. If we meet some day,
and you think this stuff is worth it, you can buy me a beer in return.
'                                   -- String (multiline!)
workDays = [ 'Monday'
           , 'Tuesday'
           , 'Wednesday']           -- Lists
hoursWorked = ( 'Monday'    -> 8.
              , 'Tuesday'   -> 7.5
              , 'Wednesday' -> 7.5) -- Map

-- What follows is Goff's lone 'magic' feature, Functions. They are not turing complete, and more
-- play the role of templates.
-- Functions are not represented in the final deserialised data, but may be used anywhere in a Goff
-- document to reduce boilerplate.

+ smallServer                      -- The Function name
| ip, supportsIpv6, bandwidthLimit -- These are fields that must be present when invoking the
                                   -- Function
cpus = 4                           -- These fields are applied automatically
location = 'us-east-1'

+ largeServer
| ip, supportsIpv6
cpus = 8
location = 'us-east-2'

: Server Info
HTTPCache = largeServer (ip -> '100.100.100.100', supportsIpv6 -> yes)
Seedbox   = smallServer (ip -> '200.200.200.200', supportsIpv6 -> no, bandwidthLimit -> Nothing)

内部结构(一致性)

有效性

所有不符合以下标准的 GoFF 文档都是 无效的。在遇到无效文件时,解析器实现应停止解析,并返回任何形式的反序列化数据。解析器实现应采取适当措施报告错误。

非类型表示

非类型通过在解析器的完成输出中自身不作为动态数据来定义。

键由一个或多个有效、非空白 UTF-8 字符组成。键用作它们分配的数据的常量名称。GoFF 中的键不区分大小写。如果解析器将数据反序列化为具有动态键的类型,如映射,则应通过将键转换为小写来规范化键。

键总是后面跟着零个或多个空格,一个等号,零个或多个空格和零个或一个换行符,然后是值。

结构

结构通过以冒号(:)开头,零个或多个空格,以及一个或多个有效 UTF-8 字符的行来表示。在视图中,结构类似于命名空间,例如:

: Network
server = 'example.com'

也许更好的理解是 network.server = 'example.com'

如果存在没有关联结构的键,则它们会被放置到全局命名空间中。给定以下文件的内容 config.gf

server = 'example.com'

: Network
server = 'example.com'

可能会产生以下内容

struct Config {
  server: String,
  network: Network,
}

struct Network {
  server: String,
}

...

Config {
  server: "example.com",
  network: Network {
    server: "example.com",
  },
}

结构名称可以包含空格,这些空格在代码中会被下划线替换。与键类似,结构名称也应通过将它们转换为小写来进行标准化。

许多语言都有 struct 类型,可以用来表示结构,或者可能有类似 data 的构造。

注释

注释从解析器在字符串外部遇到两个连续破折号时开始。解析器应该无条件地忽略该行的其余部分。

转义序列

转义序列在字符串内部匹配。它们始终以一个反斜杠开始,并立即后跟一个有效的 UTF-8 字符。如果该序列在列表中,则应在解析文本中使用其等效值或该语言的代码替换它。

转义序列 名称 UTF-8 代码点
\n 换行符 0x0A
\r 回车 0x0D
\t 水平制表符 0x09
\\ 字面反斜杠 0x5C
\' 字面单引号 0x27

后跟在此处未写出的字符的反斜杠应直接插入到输出中。

当遇到 \\ 时,应将单个字面 \ 插入到输出文本中。当遇到 \' 时,应将字面 ' 插入到输出文本中,并且解析器应继续读取字符串。

类型表示

类型是通过将有效数据分配给键的值来定义的。这意味着类型仅在键之后的有效位置。

字符串

字符串由零个或多个有效的 UTF-8 字符组成,每侧用单引号包围。

当解析器在有效位置遇到单引号时,它应继续读取,直到遇到第二个未转义的 单引号。这意味着它会通过换行符继续读取。

当字符串中遇到反斜杠时,解析器应识别其后的字符并检查它是否是有效的 Goff 转义序列。如果是,则应在输出数据中用该语言的转义序列等效值表示转义序列。否则,应忽略。

字符串的第一个换行符应被删除。

当可用时,解析器应将字符串反序列化为该语言的字符串类型:strstring。在没有字符串类型的语言中,字符串通常由字符数组表示。

布尔型

布尔型表示为两个原子之一的状态

在具有布尔类型的语言中(truefalse),布尔型是等价的。在没有布尔类型的语言中,它们应表示为该语言表示真和假值的惯用语,通常为 1 和 0。

整型

整型是一个没有小数部分的整数。

整型的容量取决于在代码中表示该键的类型。当整型的值超过其键类型的容量时,构成无效的 Goff 文件。

实型

实型是一个有小数部分的数字。

在定义上,实型可能包含无理数,尽管解析器可以安全地假设它永远不会遇到包含无限序列数字的完整的 Goff 文件。

此外,根据数学定义,实数也可能与整数匹配。整数应始终优先于实数。

实数必须包含一个点来表示它的分数部分。这意味着8.0可以表示为8.8.0,但不能表示为8

实数的容量取决于在代码中用于表示该键的类型。超出其键类型容量的实数构成无效的Goff文件。

列表

列表是一组零个或多个值。它们由一个开方括号后跟零个或多个段,以及一个闭方括号表示。

段由零个或多个空白或换行符、一个值、零个或多个空白或换行符和一个逗号组成。如果给定的段是列表的最后一个段,则可以省略尾随逗号。

列表中的所有值必须是同一类型。

这一定义意味着以下所有都是有效的列表

foo = ['bar',]
bar = [         


                                                                                     6




              ,

]
baz = [[[[[[[,],],],]]]]

但以下不是

bar = [, 5,] -- A comma without an associated value

列表通常在编程语言中以名为listarrayvector的类型表示。

映射

映射是一组零个或多个键及其相关值的集合,由一个开括号和一个段表示。

段由零个或多个空白或换行符、一个键(由一个有效的值表示),零个或多个空白或换行符、一个连字符符号直接跟一个右尖括号(->),零个或多个空白或换行符、一个值、零个或多个空白或换行符和一个逗号组成。

列表中的所有键必须是同一类型,所有值也必须是同一类型,但它们可以彼此不同。

映射通常在编程语言中以名为mapdicthash的类型表示。

无表示数据缺失。技术上,它等同于没有提供键。

在许多语言中,无可以通过名为nullnil的类型表示。在缺乏null类型的语言中,它们可能通过名为NothingNone的枚举表示。在需要显式可空类型的语言中,那些在Goff文件中以无表示但未明确标记为可空的成员构成无效的Goff文件。

贡献

提交前,请运行cargo fmt

许可证

license.txt

依赖项