BNF(バッカス・ナウア記法:Backus-Naur Form)は、プログラミング言語、ファイル形式、自然言語などの文法(構文)を厳密に定義するためのメタ言語(記法)です。1950年代にジョン・バッカスとピーター・ナウアが、プログラミング言語ALGOLの文法を記述するために考案しました。
コンパイラやインタプリタの自作、言語仕様書の読解、パーサ(構文解析器)の設計などに欠かせない技術です。その具体的な用法と仕組みについて分かりやすく解説します。
1. BNFの基本構成要素
BNFのルール(生成規則)は、主に以下の記号と要素で構成されます。
| 要素・記号 | 名称(英語) | 意味・役割 |
<非終端記号> | Non-terminal | 不断に別の形へ展開・置き換えされる記号(例:<式>、<変数>) |
"終端記号" | Terminal | それ以上展開されない、実際の文字列や文字(例:"+", "if", 1) |
::= | Definition | 「〜で定義される(is defined as)」という意味 |
| ` | ` | Alternative |
2. 具体的な用法:簡単な例でみる文法の定義
最も分かりやすい例として、「整数と足し算・引き算のみで構成される数式」のルールをBNFで表現してみましょう。
BNF
<expression> ::= <term> | <expression> "+" <term> | <expression> "-" <term>
<term> ::= <digit> | <term> <digit>
<digit> ::= "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
読み解き方
<digit>の定義:"0"から"9"までのどれか1文字を表します。|は「または」なので、どれか1つを選べます。<term>(数値の単位)の定義:1桁の数字(<digit>)であるか、あるいは「これまでにできた<term>の後ろにさらに<digit>が続くもの」として定義されています。これにより、123のような複数桁の整数を表現できます。<expression>(数式)の定義:単体の数値(<term>)であるか、または「既存の式に+と新しい数値を加えたもの」「-で引いたもの」として再帰的(リカシブ)に定義されています。これにより、1+2-3のような連続した計算を表現できます。
3. 実践的な応用:どのような場面で使われるか
① プログラミング言語の仕様策定・コンパイラ開発
言語の仕様書(Python、Java、JavaScriptなど)では、文法の曖昧さを無くすためにBNFやその拡張(EBNF)が必ず使われます。
例えば、「もし文(if文)」の構造を簡略化して表すと、以下のようになります。
BNF
<if_statement> ::= "if" "(" <condition> ")" "{" <statement_list> "}"
これにより、パーサ(構文解析器)はこのルールに従ってソースコードが正しい並びになっているかを検証(パース)します。
② データフォーマット(JSONや独自設定ファイル)の定義
プログラミング言語だけでなく、データ構造の定義にも利用されます。例えば、JSONの「値(value)」のルールを模すと、次のように記述できます。
BNF
<json_value> ::= <object> | <array> | <string> | <number> | "true" | "false" | "null"
4. より実用的な「EBNF(拡張バッカス・ナウア記法)」への発展
実際のBNFは厳密ですが、長文になりがちなため、現代ではより簡潔に書けるEBNF(Extended BNF)が広く使われています。EBNFでは、よく使う「繰り返し」や「省略」を以下のように記号でスッキリ書けます。
[...]: 0回または1回(省略可能){...}: 0回以上の繰り返し(...): グループ化
例:整数の定義(EBNF)
EBNF
integer = digit { digit } ;
digit = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
(BNFだと何度も自分自身を呼び出す複雑な書き方をしなくてはならない部分が、
{...} を使うことで「数字が1文字以上続くもの」と直感的に表現できます)BNFを学ぶことで、「人間が書いたコードや文章の構造を、コンピュータがどのように解釈・分解しているか」という仕組みを論理的に理解できるようになります。
ご自身の開発されているツールや、特定の構文をどのように書き下したいかなど、具体的なイメージはございますか?