语法表示说明
本文介绍的是一种 EBNF 的变体,用于描述字符写成的编程语言语法。这个变体将每一个非终结符的产生式都表示成了一个正则表达式,以此来使得语言定义写起来更加精炼。
本变体的格式大量参考了 Rust 的语法描述语言。
非终结符
非终结符由一段由字母、数字或下划线组成的字符串表示,例如 expr, if_stmt。其中,字母全大写的字符串,如 IDENT,表示这个非终结符是一个单词(token)。
终结符
终结符包括字符串、字符范围和正则表达式。其中:
-
字符串由双引号
"或单引号'包括,表示等同于内容的字符序列,如"while"、"y"、"+="。 -
字符范围由方括号包括,内部填写包括的字符或字符范围,表示符合要求的任一字符。其中,用短横线
-连接的两个字符表示字符编码中介于两个字符值之间(含端点)的字符。如[abcde](等同于[a-e])、[_0-9a-zA-Z]。以
^开头的字符范围表示不在范围内的任一字符,如[^abc]、[^A-Z]。 -
正则表达式由
regex()包括,内部是正则表达式,如regex(\w+)、regex(\w+://(\w+\.)+\.com)
字符范围和字符串遵循 C 风格的转义序列,即使用反斜线 \\ 后跟随字符组成。如果某个转义序列没有含义,则表示反斜线后的字符本身。
产生式
产生式左侧是非终结符,右侧是一个由终结符和非终结符组成的正则表达式,中间以箭头 -> 连接。一个产生式占一行和之后缩进的所有行,如:
sign -> [+-]
fractional_part -> "." dec_number
my_expression ->
this_is_a_very_long_keyword this_is_a_very_long_expression ";"
当一个非终结符有多个产生式时,右侧的不同产生式用竖线 | 分隔,表示“或”的关系。当产生式过长时,也可另起一行缩进书写。如:
my_keyword -> "fn" | "class"
binary_operator ->
"+" | "-" | "*" | "/"
| "=" | ">" | "<" | ">=" | "<=" | "==" | "!="
和正则表达式相同,可以省略的表达式用问号 ? 修饰,如 "public"? "class" identifier;
可以重复一次或多次的表达式用加号 + 修饰,如 [0-9a-f]+;
可以重复零次或多次的表达式用星号 * 修饰,如 [1-9] [0-9]*;
可以重复指定次数次的表达式后面用大括号括起来数字修饰,其中:
{m}表示指定重复m次;{m,n}表示重复m到n次;{m,}表示重复m次及以上;{,n}表示重复 0 到n次;
将一系列符号用小括号 ( ) 包括起来表示分组,分组内的符号作为一个整体看待,如 (item ",")+。