Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

zero-api language specification (Draft, Simplified Chinese version) #1

Open
kevwan opened this issue Apr 20, 2022 · 0 comments
Open

Comments

@kevwan
Copy link
Contributor

kevwan commented Apr 20, 2022

介绍(Introduction)

zero-api 是一种声明 HTTP API 的语言,他可以通过 goctl 翻译成基于 go-zero 的服务代码。

标记(Notation)

语法使用Extended Backus-Naur Form (EBNF)指定, 实例如下:

Production  = production_name "=" [ Expression ] "." .
Expression  = Alternative { "|" Alternative } .
Alternative = Term { Term } .
Term        = production_name | token [ "" token ] | Group | Option | Repetition .
Group       = "(" Expression ")" .
Option      = "[" Expression "]" .
Repetition  = "{" Expression "}" .

结果是由术语和以下操作符构造的表达式,优先级递增:

|   交替
()  分组
[]  可选(0 或 1 次)
{}  重复(0 到 n 次)

源码表示(Source code representation)

原代码需要使用 UTF-8 编码,我们会区分大小写。

字符(characters)

以下术语用来表示特定的 Unicode 字符类:

newline        = /* Unicode 码位U+000A */ .
unicode_char   = /* 除了换行符的其他任意 Unicode 码位 */ .
unicode_letter = /* 分类为 “Letter” 的 Unicode 码位 */ .
unicode_digit  = /* 分类为“Number, decimal digit”的Unicode码位 */ .

字母与数字(Letters and digits)

下划线 _(U+005F) 被认为字母。

letter        = unicode_letter | "_" .
decimal_digit = "0""9" .
binary_digit  = "0" | "1" .
octal_digit   = "0""7" .
hex_digit     = "0""9" | "A""F" | "a""f" .

词法元素

注释

注释作为文档,有 2 种格式:

  1. 单行注释以 // 开头,并且在行尾停止。
  2. 多行注释以字符 /* 开头,并且以随后第一个 */ 结尾。

注释不能在 runestring literal 中出现、

Tokens

Tokens 组成了 API 语言的词汇表。有四个分类: 标识符 、 关键字 、 运算符和标点以及字面值 。 空白 是由空格(U+0020)、水平制表(U+0009)、回车(U+000D)和新行(U+000A)所组成的,空白一般会被忽略,除非它分隔了组合在一起会形成单一 token 的 tokens. 并且,新行或者文件结尾可能会触发 分号 的插入。当把输入的内容区分为 tokens 时,每一个 token 都是可组成有效 token 的最长字符序列。

分号

正式的语法使用分号 ; 作为一定数量的语句终结符。

TODO: api 分号可以忽略的 case

标识符(Identifiers)

标识符用于命名程序中的实体——比如变量和类型。它是一个或者多个字母和数字的序列组合。标识符的第一个字符必须是一个字母。

identifier = letter { letter | unicode_digit } .
a
_x9
ThisVariableIsExported
αβ

TODO: 预声明标识符

关键字

如一下关键字是固定保留的,不可以用作标识符。 因为 API 将会翻译成 GO 语言,所以 API 关键字包含 GO 语言的关键字。

break        default      func         interface    select
case         defer        go           map          struct
chan         else         goto         package      switch
const        fallthrough  if           range        type
continue     for          import       return       var

TODO: 添加 API 关键字

字符串字面值(String literals)

string_lit             = raw_string_lit | interpreted_string_lit | value_string_lit .
raw_string_lit         = "`" { unicode_char | newline } "`" .
interpreted_string_lit = `"` { unicode_value | byte_value } `"` .
value_string_lit = { unicode_value | byte_value } .
`abc`                // 同 "abc"
`\n
\n`                  // 同 "\\n\n\\n"
"\n"
"\""                 // 同 `"`
"Hello, world!\n"
"日本語"
"\u65e5本\U00008a9e"
"\xff\u00FF"
"\uD800"             // 非法: 代理了一半
"\U00110000"         // 非法: 无效的 Unicode 码位

源文件组织(Source file organization)

每个源文件都是由以下的组成:

SourceFile = SyntaxDecl ";" { ImportDecl ";" } [ InfoDecl ";" ] { TypeDecl | ServiceDecl ":"}

语法版本(syntax)

语法版本控制 API 的语法版本。

SyntaxDecl = "syntax" "=" SyntaxName .
SyntaxName = string_lit .

语法版本示例

syntax = "v1";

导入声明(Import declarations)

导出声明用于 当前 API 文件导入其他 API 的时候使用。

ImportDecl       = "import" ( ImportPath | "(" { ImportPath ";" } ")" ) .
ImportPath       = string_lit .

信息声明(Info declaration)

信息声明用于声明 API 的一些额外信息。

InfoDecl    = "info" "(" { InfoElement ";"} ")" .
InfoElement = identifier ":" string_lit .
info (
    auth: "dylan"
    desc: `desc`
)

类型声明(Type declarations)

一个类型声明绑定了一个标识符(也就是 类型名 )到一个 类型 。目前 API 只支持类型定义。

TypeDecl = "type" ( TypeDef | "(" { TypeDef ";" } ")" ) .
TypeDef = identifier Type .

类型(Types)

类型确定一组值。

Type      = TypeName | TypeLit | "(" Type ")" .
TypeName  = identifier | QualifiedIdent .
TypeLit   = ArrayType | StructType | PointerType |
	    SliceType | MapType .

结构体类型(Struct types)

结构是命名元素的序列,称为字段,每个字段有一个名称和一个类型。字段名可以显式指定(IdentifierList)或隐式指定(EmbeddedField)。在结构中,非空字段名必须是唯一的。

StructType    = [ "struct" ] "{" { FieldDecl ";" } "}" .
FieldDecl     = (identifier Type | EmbeddedField) [ Tag ] .
EmbeddedField = [ "*" ] TypeName .
Tag           = string_lit .

指针类型(Pointer Type)

指针类型表示指向一给定类型的 变量 的所有指针的集合,这个给定类型称为该指针的 基础类型 。

PointerType = "*" Type .

数组类型(ArrayType)

ArrayType   = "[" ArrayLength, "]" Type .
ArrayLength = Expression .

分片类型(SliceType)

SliceType = "[", "]", Type .

映射类型(MapType)

映射是由一种类型的元素所组成的无序组,这个类型被称为元素类型, 其元素被一组另一种类型的唯一 键 索引,这个类型被称为键类型。

MapType = "map" "[" Type "]" Type .

服务定义

服务为 API 定义的路由服务,一个 API 可以有多个 Service, 但是必须 ServiceName 必须同名。

ServiceDecl = (ServiceExtDecl) ServiceBody
ServiceBody = "service" identifier "(" { RouteDecl } ")"
RouteDecl = (Doc) ";" Handler ";" Method Path (Request) (Response)
Doc = "@doc" string_lit
Handler = "@handler" identifier
Method = "get" | "post" | "put" | "header"
Path   = "/" (":") identifier { Path }
Request = "(" identifier ")"
Response = "returns" "(" identifier ")"

服务额外扩展定义

服务 @service 扩展信息定义。

ServiceExtDecl = "@service" "(" { ServiceExtElement } ")"
ServiceExtElement = identifier ":" string_lit .
@kevwan kevwan changed the title zero-api language specification zero-api language specification (CN) Apr 20, 2022
@kevwan kevwan changed the title zero-api language specification (CN) zero-api language specification (Draft, Simplified Chinese version) Apr 20, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant