巴科斯范式(Backus–Naur Form)介紹


簡介

巴科斯范式(Backus Normal Form簡稱為BNF),又稱為巴科斯-諾爾范式,是一種上下文無關的語言,廣泛地使用於程序設計語言、指令集、通信協議的語法表示中。在各種文獻中,還存在巴科斯范式的一些變體,如擴展巴科斯范式(ENBF)或擴充巴科斯范式。

上下文無關語言

 我們假定您已了解正則語言——一種通過有限狀態機或正則表達式表達的語言,這種語言是字符串集的子集。我們現在來介紹另一種語言——上下文無關語言。任何的正則語言都是一種上下文無關語言。

大部分程序語言可被定義為上下文無關語言。要定義上下文無關語言,我們需要使用上下文無關語法,上下文無關語法的一個例子是巴科斯范式。

巴科斯范式

巴科斯范式是一種上下文無關語法,它使用一系列符號和表達式來創建字符串生成規則。一個簡單的BNF生成規則類似如下:

<digit>::=0|1|2|3|4|5|6|7|8|9

上述文法代表任意一個0到9的任意一個數字。這里的尖括號“<>”是非終結符,如果一個非終結符出現在生成規則的右邊,這意味着會有另一條生成規則來解釋代替它的位置。考慮如下生成規則:

<fullname>::=<title><name><name>

這里<fullname>由<title>、<name>和另一個<name>字符串構成。例如,我們可以定義如下生成規則來代替<title>:

<title>::=Mr|Mrs|Ms|Miss|Dr

在這條規則中,Mr、Mrs、Ms、Miss和Dr均是終結符,它們是title的實際值,符號“|”在這里代表元字符,含義是“或"。這條規則的具體含義<title>可被解釋為Mr或Mrs或Ms或Miss或Dr中的一個。

當你在表達式右側看到非終結符時,就一定有一條生成規則,該非終結符是在左側的。這個一直持續到任一非終結符都出現在某一條生成規則的左側為止。讓我們來看另一組生成規則:

  <addition> ::= <number>+<number>
    <number> ::= <sign><integer>|<integer>
    <integer> ::= <digit>|<digit><integer>
    <digit>::=0|1|2|3|4|5|6|7|8|9
    <sign> ::= +|-

上述生成規則表示由任意兩個整數相加得到的表達式。

巴科斯范式生成規則中的遞歸

 巴科斯范式使用遞歸來表示一個或任意多個符號,例如一個正整數由一個或多個數字構成。尋常的表達式無法表達任意位數字構成的正整數,但通過遞歸,我們可以有個優美的方案:

 <number> ::= <digit>|<digit><number>        (1)
    <digit> ::= 0|1|2|3|4|5|6|7|8|9            (2)

通過上述文法,我們來判斷315是number。首先從(2)知5是digit,再從(1)知digit是number,從而正整數5是number。由(2)知1是digit,而5是number,從而由(1)15可表達成<digit><number>知15也是number。再由3是digit,而15是number,知315可表達為<digit><number>,從而315也是number。上述遞歸生成規則(1)包含一個基本的生成規則<digit>和一個通用的生成規則<digit><number>,在通用的生成規則中我們使用了遞歸定義。

語法解析樹

當需要判斷一個字符串是否滿足某個生成規則時,語法解析樹非常有用,因為可以將字符串解析成一個個簡單的部分。考慮如下一組生成規則

<addition> ::= <number>+<number>
<number> ::= <sign><integer>|<integer>
<integer> ::= <digit>|<digit><integer>
<digit>::=0|1|2|3|4|5|6|7|8|9
<sign> ::= +|-

我們來通過語法解析樹來判斷57+85是否是加法表達式。首先57+85包含一個終止符“+”,要滿足上述加法表達式<addition> ::= <number>+<number>,57+85需要表達成

 

接下來要判斷57和85都是數字(<number>),而數字的表達式是<number> ::= <sign><integer>|<integer>,只要57和85是正整數(<integer>)或者是正整數前面帶上符號,那57和85就是數字(<number>)。由於57和85前面既沒有“+”也沒有“-”,因此接下來要判斷的是57和85是否是正整數(<integer>)。

由於正整數(<integer>)的表達式是<integer> ::= <digit>|<digit><integer>,這是一個遞歸表達式,代表正整數(<integer>)要么是0-9的數字(<digit>),要么是0-9的數字加上一個正整數(<digit><integer>)。因為57和85都不是0-9的數字(<digit>),因此必定是0-9的數字加上一個正整數(<digit><integer>)

我們觀察57,發現5是0-9中的數字,接下來要判斷的是7是否是正整數,由於7確實也是0-9中的數字,因此7也是正整數,同理可判斷85也是正整數。

由上述分析可知57+85確實是一個加法表達式。

 

上圖即是表達式“57+85”的語法解析樹。

 

語法圖

除了巴科斯范式符號,您還可以通過語法圖的形式來描述巴科斯范式語法。

讓我們先來看一個簡單表達式

<special> ::= @ | ? | & | *

其語法圖如下:

這個語法圖代表表達式可以是“@”、“?”、“&”或“*”中的任意一個符號。當您從語法圖的開始節點出發,可以挑選任意一條路徑,從而選擇是“@”、“?”、“&”或“*”中的任意一個字符達到結束節點。

我們再來看一個較為復雜例子的語法圖,表達式如下:

    <date> ::= <day-name><month-name>|<day-name><month-name><year>

    <day-name> ::= Monday|Tuesday|Wednesday|Thursday|Friday|Saturday|Sunday

 語法圖如下:

 

 我們先看,表達式<date>的語法圖,語法圖總是從左到右開始,順着箭頭流動方向進行閱讀的。我們看到<date>首先包含<day-name>,然后包含<month-name>。從month-name節點出來后,可以選擇直接打到結束,或者選擇下面這條經過year節點的路徑。這根表達式的含義是一致的:

 <date> ::= <day-name><month-name>|<day-name><month-name><year>

必須包含表達式<day-name>,接下來是表達式<month-name>,然后可以選擇性地包含表達式<year>。

再看<day-name>的語法圖,它的含義十分簡明,就是代表周一到周日中的任意一天:Monday或Tuesday或Wednesday或Thursday或Friday或Saturday或Sunday。

最后,我們來看下遞歸表達式的語法圖,因為在巴科斯范式中唯一能表達循環的 就是遞歸。

我們來看表達式

 <number> ::= <digit>|<digit><number>


的語法圖:

這表示,從開始節點出發,經過digit節點。在從digit節點出來后,可以選擇直接流向結束節點,或者選擇再次流向digit節點。簡潔來說,就是從開始節點出發,可以經過digit節點若干次后到達結束節點。在語法圖中,我們使用流向重新返回到已經歷過節點的方式來表達遞歸。

巴科斯范式與正則表達式之間的關系

正則表達式和有限狀態機常用來描述正則語言。BNF是一個上下文無關語法的例子,它被用來描述上下文無關語言。因為所有的正則語言都一定是上下文無關語言,因此你可以將任意的正則表達式轉換成BNF文法規則(或者是一個規則,或者是一組規則),當然反過來往往不成立。他們之間的關系如下:

舉一個是上下文無關語言但不是正則語言的例子。當你想描述一個左右括號匹配正確的表達式時,每當出現一個左(開)括號,就一定有一個右括號與之對應。由於有限狀態機除了自身處於當前狀態外無法記住任何狀態,因此可以描述有有不能匹配的左括號的狀態,因此可以描述到底是有一個左括號沒有匹配,還是兩個或者三個等等。但正如有限狀態機含義描述的那樣,它只有有限個狀態,無法描述無限個不匹配的左括號。

因此只要有無限個要計算的字符串元素,就需要使用上下文無關語言來進行描述。

 

 

 擴展閱讀:

[1] 正則語言:https://brilliant.org/wiki/regular-languages/#:~:text=A%20regular%20language%20is%20a,alphabet%2C%20or%20set%20of%20symbols.

[2] 正則表達式:https://isaaccomputerscience.org/concepts/dsa_toc_regex?examBoard=all&stage=all

[3] 正則表達式可視化工具:http://tool.rbtree.cn/regtool/

[4] 巴科斯范式:https://isaaccomputerscience.org/concepts/dsa_toc_bnf?examBoard=aqa&stage=all

[5]繪圖工具:https://www.processon.com/diagrams

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM