コンピュータサイエンスでは、拡張バッカス・ナウア記法( EBNF ) はメタ構文記法のファミリーであり、そのいずれも文脈自由文法を表現するために使用できます。EBNF は、コンピュータプログラミング言語などの形式言語の形式的な記述を作成するために使用されます。これらは、基本バッカス・ナウア記法(BNF) メタ構文記法の拡張です。最も初期の EBNF は、ニクラウス・ヴィルトによって開発され、ヴィルト構文記法の概念の一部 (異なる構文と記法で) を取り入れています。今日では、EBNF の多くのバリアントが使用されています。国際標準化機構は、1996 年にEBNF規格ISO/IEC 14977を採用しました。 [ 1 ] [ 2 ]しかし、ザイツェフによれば、この規格は「混乱にさらに 3 つの方言を追加しただけ」であり、その成功の欠如を指摘した後、ISO EBNF がすべての ISO 規格で使用されているわけではないことも指摘しています。[ 3 ]
本稿では、すべてのEBNFに共通する例として、ISO規格で規定されているEBNFを使用しています。他のEBNFバリアントでは、構文規則が若干異なります。
EBNFは形式言語の構文を表すコードです。 [ 4 ] EBNFは終端記号と非終端生成規則で構成され、非終端生成規則は終端記号を有効なシーケンスに組み合わせる方法を規定する制約です。終端記号の例としては、英数字、句読点、空白文字などがあります。
EBNFは、記号のシーケンスがそれぞれ非終端記号に割り当てられる生成規則を定義します。
0 を除く数字= "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;数字 = "0" | 0 を除く数字;この生成規則は、代入の左側にある非終端数字を定義します。縦棒は選択肢を表し、終端記号は引用符で囲まれ、セミコロンが終端文字として続きます。したがって、数字は0、または0以外の数字(1、2、3など9まで)になります。
生成規則には、コンマで区切られた一連の終端記号または非終端記号を含めることもできます。
12 = "1" 、"2" ; 201 = "2" 、"0" 、"1" ; 312 = "3" 、12 ; 12,201 = 12 、201 ;省略または繰り返し可能な式は、中括弧 { ... } で表すことができます。
正の整数=ゼロを除く数字、{数字} ;この場合、文字列1、2、...、10、...、10000 、... は正しい表現です。これを表現するには、波括弧内に設定されているすべての要素を、まったく繰り返さないことも含め、任意の回数繰り返すことができます。
オプションは角括弧 [ ... ] で表すことができます。つまり、角括弧内に設定されている内容は、一度だけ存在することも、まったく存在しないこともあります。
整数= "0" | [ "-" ]、正の整数;したがって、整数とは、ゼロ(0)または、オプションでマイナス記号が前に付く正の整数です。
EBNFは、とりわけ、繰り返し(指定された回数)を記述するための構文、生成規則の一部を除外するための構文、およびEBNF文法にコメントを挿入するための構文を提供する。
以下は、RS ScowenによるISO/IEC 14977規格案(7ページ、表1および表2)です。
EBNFでさえEBNFを用いて記述することができる。以下の文法を考えてみよう(集合の論理和を表すのに「-」、1つ以上の一致を表すのに「+」、オプション性を表すのに「?」などの規則を用いる)。
文字= "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" | "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" ;数字= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;記号= "[" | "]" | "{" | "}" | "(" | ")" | "<" | ">" | "'" | '"' | "=" | "|" | "." | "," | ";" | "-" | "+" | "*" | "?" | "\n" | "\t" | "\r" | "\f" | "\b" ;文字=文字|数字|記号| "_" | " " ;識別子=文字, {文字|数字| "_" } ;S = { " " | "\n" | "\t" | "\r" | "\f" | "\b" } ;ターミナル= "'" 、文字 - "'" 、{文字 - "'" } 、"'" | '"' 、文字 - '"' 、{文字 - '"' } 、'"' ;終端文字= ";" | "." ;term = "(" , S , rhs , S , ")" | "[" , S , rhs , S , "]" | "{" , S , rhs , S , "}" | terminal | identifier ;因子=項、S 、"?" |項、S 、"*" |項、S 、"+" |項、S 、"-" 、S 、項|項、S ;連結= ( S 、因子、S 、"," ? ) + ;交替 = ( S 、連結 、 S 、 "|" ? ) + ;rhs =交替; lhs =識別子;ルール= lhs 、S 、"=" 、S 、rhs 、S 、終端記号;文法= ( S 、ルール、S ) * ;代入のみを許容するPascalライクなプログラミング言語は、EBNFでは次のように定義できる。
(* EBNF のシンプルなプログラム構文 - Wikipedia *) program = 'PROGRAM' 、空白、識別子、空白、'BEGIN' 、空白、{代入、";" 、空白}、'END.' ;識別子=アルファベット文字、{アルファベット文字|数字} ;数値= [ "-" ]、数字、{数字} ; 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 A := 3 ; B := 45 ; H :=- 100023 ; C := A ; D123 := B34A ; BABOON := GIRAFFE ; TEXT := " Hello world !" ; END .この言語は、制御フロー、算術式、入出力命令などを容易に追加して拡張できる。そうすれば、小型で使いやすいプログラミング言語が開発されるだろう。
EBNFで定義された文法はすべてBNFでも表現できますが、BNFでの表現は一般的に長くなります。例えば、オプションと繰り返しはBNFでは直接表現できないため、中間規則または代替生成規則を使用する必要があります。代替生成規則は、オプションの場合は何もしないかオプション生成規則、繰り返しの場合は再帰的に自身を繰り返す生成規則のいずれかとして定義されます。EBNFでは、同じ構造を引き続き使用できます。
BNFでは記号(<、>、|、::=)を自身に使用しますが、終端記号文字列を引用符で囲みません。これにより、これらの文字が言語で使用されるのを防ぎ、空文字列には特別な記号が必要になります。EBNFでは、終端記号は厳密に引用符("..."または'... )で囲まれます。非終端記号'の山括弧(<... >)は省略できます。
BNF構文ではルールを1行でしか表現できませんが、EBNFでは終了文字であるセミコロンが;ルールの終わりを示します。
さらに、EBNFには、繰り返し回数の定義、代替案の除外、コメントなど、拡張のためのメカニズムが含まれています。
*繰り返し記号-例外記号、連結記号|定義区切り記号=定義記号;終端記号.終端記号(* 開始コメント記号 終了コメント記号 *) ' 1 番目の引用記号 1 番目の引用記号 ' (開始グループ記号 終了グループ記号 ) [開始オプション記号 終了オプション記号 ] {開始繰り返し記号 終了繰り返し記号 } ?特殊シーケンス記号 特殊シーケンス記号 ? " 2 番目の引用記号 2 番目の引用記号 "') です。ISO/IEC 14977:1996(E) で使用されているフォントでは、アキュートな Unicode U+00B4 ( ´) と非常によく似た表示になるため、混乱が生じることがあります。しかし、ISO Extended BNF 規格では、規範的参照として ISO/IEC 646:1991「情報交換のための ISO 7 ビット符号化文字セット」を参照しており、他の文字セットについては一切言及していないため、形式的には 7 ビット ASCII 範囲外の Unicode 文字との混同はありません。例として、以下の構文規則は、繰り返しを表現するための機能を示しています。
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 }, "G" ; hh = ( aa | bb | cc ), "H" ;これらの規則によって定義される終端文字列は次のとおりです。
aa: A bb: AAAB cc: C AC AAC AAAC dd: D AD AAD AAAD AAAAD など ee:AAE AAAE AAAAE AAAAE など ff: AAAF AAAAF AAAAAF AAAAAAF gg: G AAAG AAAAAAG など。 hh: ああああああああああああああ
ISO 14977規格によれば、EBNFは拡張可能であるべきであり、2つの機能が言及されている。1つ目はEBNF文法の一部である特殊シーケンスで、これは疑問符で囲まれた任意のテキストである。特殊シーケンス内のテキストの解釈はEBNF規格の範囲外である。例えば、スペース文字は次のような規則で定義できる。
スペース= ? ASCII文字32 ? ;拡張のための2つ目の機能は、EBNFでは括弧を識別子のすぐ隣に置くことができない(括弧は識別子と連結する必要がある)という事実を利用することです。以下は有効なEBNFです。
something = foo 、( bar );以下は有効なEBNFではありません。
something = foo ( bar );したがって、EBNFの拡張ではその表記法を使用できる。例えば、Lisp文法では、関数適用は次のような規則で定義できる。
function application = list ( symbol , { expression } );