文章目錄
巴科斯範式(也稱為巴科斯-瑙爾範式、巴克斯-諾爾範式)即 BNF 是一種用於表示上下文無關文法的語言,上下文無關文法描述了一類形式語言。儘管巴科斯範式也能表示一部分自然語言的文法,它還是更廣泛地使用於程式設計語 言、指令集、通訊協定的文法表示中。大多數程式設計語言或者形式語義方面的教科書都採用巴科斯範式。在各種文獻中還存在巴科斯範式的一些變體,如擴充巴科斯範式EBNF或擴充巴科斯範式 ABNF。
BNF 規定是推導規則(產生式)的集合,寫為:
<code><符號> ::= <使用符號的運算式>
這裡的<符號> 是非終結符,而運算式由一個符號序列,或用指示選擇的豎杠 ‘|’ 分隔的多個符號序列構成,每個符號序列整體都是左端的符號的一種可能的替代。從未在左端出現的符號叫做終結符。
擴充巴科斯範式
擴充巴科斯-瑙爾範式(EBNF)是表達作為描述電腦程式設計語言和形式語言的正規方式的上下文無關文法的元文法符號標記法。它是基本巴科斯範式(BNF)元文法符號標記法的一種擴充。
它最初由尼古拉斯·沃斯開發,最常用的 EBNF 變體由標準,特別是 ISO-14977 所定義。
基本
代碼,如由終結符即可視字元、數字、標點符號、空白字元等組成的電腦程式的原始碼。
EBNF 定義了把各符號序列分別指派到非終結符的產生規則:
digit excluding zero = "1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9" ; digit = "0" | digit excluding zero ;
這個產生規則定義了在這個指派的左端的非終結符 digit。豎杠表示可供選擇,而終結符被引號包圍,最後跟著分號作為終止字元。所以 digit 是一個 0 或可以是 1 或 2 或 3 直到 9 的一個 digit excluding zero。
產生規則還可以包括由逗號分隔的一序列終結符或非終結符:
twelve = "1" , "2" ; two hundred one = "2" , "0" , "1" ; three hundred twelve = "3" , twelve ; twelve thousand two hundred one = twelve , two hundred one ;
可以省略或重複的運算式可以通過花括弧 { … } 表示:
natural number = digit excluding zero , { digit } ;
在這種情況下,字串 1, 2, …,10,…,12345,… 都是正確的運算式。要表示這種情況,於花括弧內設立的所有東西可以重複任何次,包括根本不出現。
可選項可以通過方括弧 [ ... ] 表示:
integer = "0" | [ "-" ] , natural number ;
所以 integer 是一個零(0)或可能前置可選的負號的一個自然數。
EBNF 還包括描述指定次數的重複,和排除產生式的某部分或向 EBNF 文法插入注釋的文法。
依據 ISO 的擴充
依據 ISO 14977 標準,提供了兩個設施來擴充 EBNF。其一是在 EBNF 文法部分的特殊序列,它是在問號包圍內的任意文本,其解釋超出了 EBNF 標準的範圍。例如,空白字元可以用如下規則定義:
space = ? US-ASCII character 32 ?;
其二利用圓括弧在 EBNF 中不能放置到緊隨標識符之後的事實。下列不是有效 EBNF:
something = foo ( bar );
所以 EBNF 的擴充可以使用這種標記法。例如,在 Lisp 文法中,函數應用可以用如下規則定義:
function application = list( symbol , [ { expression } ] );
擴充 BNF 的動機
BNF 有著可選項和重複不能直接表達的問題。作為替代,它們需要利用中介規則或兩選一規則,對於可選項,定義要麼是空的要麼是可選的產生式的規則,對於重複,遞迴的定義要麼是被重複的產生式要麼是自身的規則。同樣的構造仍可用在 EBNF 中。
可選項:
signed number = [ sign , ] number ;
可按 BNF-風格定義為:
signed number = sign , number | number ;
或
signed number = optional sign , number ; optional sign = ε | sign ; (* 使用 ε 來更清晰的指示空產生式 *)
重複:
number = { digit } ;
可按 BNF-風格定義為:
number = digit | number digit;
其他增加和修改
EBNF 排除了 BNF 的一些缺陷:
- BNF 為自身使用了符號 (<, >, |, ::=)。當它們出現在要定義的語言中的時候,BNF 不能不加以修改或解釋的使用。
- BNF-文法在一行中只表示一個規則。
EBNF 解決了這些問題:
- 終結符被嚴格的包圍在引號 (“…” 或 ‘…’) 中。給非終結符的角括弧 (“<…>”)可以省略。
- 通常使用終止字元分號結束一個規則。
進一步還提供了定義重複次數,排除法選擇(比如除了引號的所有字元)和注釋等的增強機制。
不管所有這些增強,EBNF 在能定義的語言的意義上不比 BNF 更強大。在原理上用 EBNF 定義的任何文法都可以用 BNF 表達。但是經常導致可觀的更多規則的表示。
EBNF 已經被ISO用代碼 ISO/IEC 14977:1996(E) 標準化了。
在某些場合任何擴充的 BNF 都被稱為 EBNF。例如 W3C 使用 one EBNF 來規定 XML。
另一個例子
只允許賦值的簡單程式設計語言可以用 EBNF 定義為:
(* a simple program in EBNF − Wikipedia *) program = 'PROGRAM' , white space , identifier , white space , 'BEGIN' , white space , { assignment , ";" , white space } , 'END.' ; identifier = alphabetic character , [ { alphabetic character | digit } ] ; number = [ "-" ] , digit , [ { digit } ] ; string = '"' , { all characters − '"' } , '"' ; assignment = identifier , ":=" , ( number | identifier | string ) ; alphabetic character = "A"|"B"|"C"|"D"|"E"|"F"|"G" |"H"|"I"|"J"|"K"|"L"|"M"|"N" |"O"|"P"|"Q"|"R"|"S"|"T"|"U" |"V"|"W"|"X"|"Y"|"Z" ; digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9" ; white space = ? white space characters ? ; all characters = ? all visible characters ? ;
一個文法上正確的程式:
PROGRAM DEMO1 BEGIN A0:=3; B:=45; H:=-100023; C:=A; D123:=B34A; BABOON:=GIRAFFE; TEXT:="Hello world!"; END.
這個語言可以輕易的擴充上控制流程,算術運算式和輸入/輸出指令。就可以開發出一個小的、可用的程式設計語言了。
使用了在標準中提議為正規表示的下列字元:
| 用途 |
符號表示 |
| 定義 |
= |
| 串接 |
, |
| 終止 |
; |
| 分隔 |
| |
| 可選 |
[ ... ] |
| 重複 |
{ … } |
| 分組 |
( … ) |
| 雙引號 |
” … “ |
| 單引號 |
‘ … ‘ |
| 注釋 |
(* … *) |
| 特殊序列 |
? … ? |
| 除外 |
- |
約定
- 使用了如下約定:
- 擴充 BNF 每個元標識符都被寫為用連字號串連起來的一個或多個字;
- 結束於“-symbol” 的元標識符是擴充 BNF 的終結符的名字。
- 表示擴充 BNF 的每個操作符的正常字元和它所蘊涵的優先順序(頂部為最高優先順序)為:
* repetition-symbol - except-symbol , concatenate-symbol | definition-separator-symbol = defining-symbol ; terminator-symbol
- 下列括弧對超越正常優先順序:
' first-quote-symbol first-quote-symbol ' " second-quote-symbol second-quote-symbol " (* start-comment-symbol end-comment-symbol *) ( start-group-symbol end-group-symbol ) [ start-option-symbol end-option-symbol ] { start-repeat-symbol end-repeat-symbol } ? special-sequence-symbol special-sequence-symbol ?
作為例子,下列文法規則展示了表達重複的設施:
aa = "A"; bb = 3 * aa, "B"; cc = 3 * [aa], "C"; dd = {aa}, "D"; ee = aa, {aa}, "E"; ff = 3 * aa, 3 * [aa], "F"; gg = {3 * aa}, "D";
這些規則定義的終結字串如下:
aa: A bb: AAAB cc: C AC AAC AAAC dd: D AD AAD AAAD AAAAD etc. ee: AE AAE AAAE AAAAE AAAAAE etc. ff: AAAF AAAAF AAAAAF AAAAAAF gg: D AAAD AAAAAAD etc.
有關工作
- W3C 使用一種不同的 EBNF 來指定 XML 文法。
- British Standards Institute 在1981年出版了一個 EBNF 標準: BS 6154。
- IETF 使用在 RFC 4234 中規定的擴充 BNF (ABNF)。
ps,由於中文維基百科尚不可訪問,所以就原文轉載了其中關於巴科斯範式和擴充巴科斯範式的詞條。