惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

阮一峰的网络日志
阮一峰的网络日志
D
Darknet – Hacking Tools, Hacker News & Cyber Security
S
Schneier on Security
The Last Watchdog
The Last Watchdog
Cyberwarzone
Cyberwarzone
S
Securelist
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
C
Cyber Attacks, Cyber Crime and Cyber Security
L
Lohrmann on Cybersecurity
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
博客园 - 司徒正美
The Cloudflare Blog
V
V2EX
博客园_首页
博客园 - 聂微东
Vercel News
Vercel News
人人都是产品经理
人人都是产品经理
G
GRAHAM CLULEY
T
Tenable Blog
Last Week in AI
Last Week in AI
Y
Y Combinator Blog
L
LINUX DO - 最新话题
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
SecWiki News
SecWiki News
博客园 - 三生石上(FineUI控件)
S
Secure Thoughts
N
News | PayPal Newsroom
T
The Blog of Author Tim Ferriss
The GitHub Blog
The GitHub Blog
T
Troy Hunt's Blog
博客园 - 【当耐特】
Forbes - Security
Forbes - Security
H
Hacker News: Front Page
A
About on SuperTechFans
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
MongoDB | Blog
MongoDB | Blog
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
罗磊的独立博客
D
DataBreaches.Net
P
Privacy & Cybersecurity Law Blog
Schneier on Security
Schneier on Security
Application and Cybersecurity Blog
Application and Cybersecurity Blog
Google DeepMind News
Google DeepMind News
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Jina AI
Jina AI
D
Docker
P
Proofpoint News Feed

lzw-723's blog

raylib基础学习 | lzw-723's blog Lojban教程 - 逻辑语学习中常见专有名词列表 | lzw-723's blog Lojban基础教程 - 字母 | lzw-723's blog 【译】5分钟入门Nim编程语言 | lzw-723's blog Cakewalk安装无反应的解决办法 | lzw-723's blog C语言教程 - while循环 | lzw-723's blog C++ FAQ | lzw-723's blog 《Moe Era》 - 时代潮流中不值一提的我 | lzw-723's blog C语言教程 - for循环 | lzw-723's blog
扩充巴科斯范式(ABNF)初识 | lzw-723's blog
2021-12-07 · via lzw-723's blog

2021-12-07 7 min read # 教程 # 笔记

巴科斯范式是以美国人巴科斯(Backus)和丹麦人诺尔(Naur)的名字命名的一种形式化的语法表示方法,用来描述语法的一种形式体系,是一种典型的元语言

起步

一个ABNF规范是一些推导规则的集合:

规则 = 定义;注释CR LF

可细分为以下几个部分:

  • 规则
  • 定义
  • 注释 (可选)
  • CR LF(回车、换行)结束

规则名

大小写不敏感

规则名字不区分大小写:
<rulename>, <Rulename>, <RULENAME><rUlENamE>指的都是同一个规则。
规则名由一个字母或多个字母数字连字符(减号)组成。

尖括号非必须

用尖括号(<>)包围规则名不是必需的(与BNF一样),它们可以用来在文中方便识别出规则名。

最终值

最终值为一个或多个数值字符。

数值字符可按下面的方式指定:先是一个百分号%,紧跟着基数(b=二进制, d = 十进制, x = 十六进制),再其后是这个数值或数值串(用.来指示串联)。例如:回车可以用十进制的%d13或十六进制的%x0D来指定,而回车换行则可以用%d13.10来指定。

字面文本通过包含在在双引号"中字符串指定。这些字符串不区分大小写,使用 (US-)ASCII字符集。所以字符串abc将匹配abcAbcaBcabCABcAbCaBCABC
区分大小写的匹配必须定义明确的字符,例如:若要匹配aBc,定义必须是%d97 %d66 %d99

操作符

空白字符

空白字符被用来分隔定义中的各个元素:要使空格被识别为分割符则必须明确的包含它。

串联

规则1规则2

规则可以通过列出一系列的规则名来定义。

要匹配字符串aba可以使用下列规则:

foo = %x61 ; a
bar = %x62 ; b
mumble = foo bar foo

选择 /

规则1 / 规则2

一个规则可以通过用斜杠(/)分隔的可供选择的子规则列表来定义。

要接受规则或规则可构造如下规则:

foobar = foo / bar

增量选择 =/

规则1 =/ 规则2

可以通过在规则名和定义之间使用=/来向一个规则增加补充选择。

规则

ruleset = alt1 / alt2 / alt3 / alt4 / alt5

等价于

ruleset = alt1 / alt2
ruleset =/ alt3
ruleset =/ alt4 / alt5

值范围%c##-##

%c##-##

数值范围可以通过使用连字符(-)来指定。

规则

OCTAL = "0" / "1" / "2" / "3" / "4" / "5" / "6" / "7"

等价于

OCTAL = %x30-37

序列组合 ()

(规则1规则2)

在定义中,元素可以放置在圆括号中来将规则组合起来,该组合视为单个元素。

要匹配elem foobar snafooelem tarfoo snafoo可以构造下列规则:

group = elem (foobar / tarfoo) snafoo

要匹配elem foobartarfoo snafoo可以构造下列规则:

group = elem foobar / tarfoo snafoo
group = (elem foobar) / (tarfoo snafoo)

不定量重复m*n

元素前面的星号*表示重复,其完整形式如下:

m*n规则

要表示一个元素的重复,就要使用<m>*<n>元素形式。可选的<m>给出要包含的元素的最小数目,默认为0;可选的给出要包含的元素的最大数目,默认为无穷大。

例子:

*元素 ; 表示零个或更多元素
1*元素 ; 表示一个或更多元素
2*4元素 ; 表示两个至四个元素

定量重复n

n规则

要表示特定数目的元素可使用形式<n>元素,相当于用不定量重复形式表示的<n>*<n>元素。

使用2DIGIT得到两个数字,使用3DIGIT得到三个数字。(DIGIT在下面的核心规则中定义,也见例子中的zip-code)。

可选序列[]

[规则]

要表示可选元素,下列构造等价:

[foobar snafoo]
*1(foobar snafoo)
0*1(foobar snafoo)

注释;

;注释

注释从一个分号(;)开始,并持续到此行的结束。

操作符优先级

下面的操作符给出了从高(结合最紧密)到低(结合最松散)的优先级:

  1. 规则名、最终值
  2. 注释;
  3. 值范围%c##-##
  4. 重复*
  5. 组合 ()、可选[]
  6. 串联
  7. 选择 /

选择操作符与串联一起使用会造成混淆,因此建议使用组合来确保串联组的明确。

例如:

我们 = 你 我/他 她

会产生下面两种歧义:

(你 我)/(他 她)
(你) (我/他) (她)

所以,使用组合来确保不会产生歧义:

(你 我)/(他 她)

核心规则

核心规则定义于 ABNF 标准中。

规则 形式定义 意义
ALPHA %x41-5A / %x61-7A 大写和小写 ASCII 字母(A-Z, a-z)
DIGIT %x30-39 数字(0-9)
HEXDIG DIGIT / "A" / "B" / "C" / "D" / "E" / "F" 十六进制数字(0-9, A-F, a-f)
DQUOTE %x22 双引号
SP %x20 空格
HTAB %x09 横向制表符
WSP SP / HTAB 空格或横向制表符
LWSP *(WSP / CRLF WSP) 直线空白(晚于换行)
VCHAR %x21-7E 可见(打印)字符
CHAR %x01-7F 任何 7 - 位 US-ASCII 字符,不包括 NUL(%x00)
OCTET %x00-FF 8 位数据
CTL %x00-1F / %x7F 控制字符
CR %x0D 回车
LF %x0A 换行
CRLF CR LF 互联网标准换行
BIT "0" / "1" 二进制数字

实践

电子邮箱地址

email = 1*( atext / "." ) "@" label *( "." label ) label = let-dig [ [ ldh-str ] let-dig ]

JSON

// 语法树的跟【Root是系统内置,必须定义Root作为语法根节点,没有定义会报错】
Root = Value?;
// 字符串
Text : "\""@ = "\"([^\"\\]|\\.)*\"";
// 整型数值
Number : "[0-9]" = "0x[0-9a-fA-F]+" | "[0-9]+(%.[0-9]+)?";
// 空
Null [53,155,185] = <null>;
// bool
Bool = <true> | <false>;
// Json值
Value = Text | Bool | Number | Null | Array | Object;
// 数组
Array = '['@ (Value ArrayValuePair*)? ']';
// Array元素
ArrayValuePair = ','@ Value;
// 映射表
Object = '{'@ (ObjectValue ObjectValuePair*)? '}';
// 键
ObjectKey = Text;
// 键值对
ObjectValue = ObjectKey ':'@ Value;
// Object元素
ObjectValuePair = ','@ ObjectValue;

参考资料

  1. 扩充巴科斯范式 - 维基百科,自由的百科全书
  2. 从零开始的 JSON 库教程(一):启程
  3. RFC 5234: Augmented BNF for Syntax Specifications: ABNF
  4. 从零开始设计一门属于自己的开发语言
    • 起步
      • 规则名
      • 最终值
      • 操作符
        • 空白字符
        • 串联
        • 选择 /
        • 增量选择 =/
        • 值范围%c##-##
        • 序列组合 ()
        • 不定量重复m*n
        • 定量重复n
        • 可选序列[]
        • 注释;
        • 操作符优先级
      • 核心规则
    • 实践
      • 电子邮箱地址
      • JSON
    • 参考资料