В информатике форма Бэкуса-Наура ( / ˌ b æ k ə s ˈ n aʊər / ) (BNF или нормальная форма Бэкуса ) — это обозначение, используемое для описания синтаксиса языков программирования или других формальных языков . Его разработали Джон Бэкус и Питер Наур . BNF можно описать как метасинтаксическую нотацию для контекстно-свободных грамматик . Форма Бэкуса-Наура применяется везде, где необходимы точные описания языков, например, в спецификациях официальных языков, в руководствах и учебниках по теории языков программирования. BNF может использоваться для описания форматов документов , наборов команд и протоколов связи .
Со временем было создано множество расширений и вариантов исходной нотации Бэкуса – Наура; некоторые из них точно определены, включая расширенную форму Бэкуса-Наура (EBNF) и расширенную форму Бэкуса-Наура (ABNF).
Спецификация BNF представляет собой набор правил вывода, записанных как
< символ > ::= __выражение__
где:
::=
означает, что символ слева необходимо заменить выражением справа.В качестве примера рассмотрим возможный BNF для почтового адреса в США :
< почтовый адрес > ::= < часть имени > < уличный адрес > < zip-часть > < часть имени > ::= < личная часть > < фамилия > < часть дополнительного суффикса > < EOL > | < личная часть > < часть имени > < личная часть > ::= < имя > | < начальный > "." < уличный адрес > ::= < номер дома > < название улицы > < номер opt-apt- num > <EOL> < почтовый индекс > ::= < название города > "," < код штата > < почтовый индекс > < EOL >< opt-suffix-part > ::= "Старший." | «Младший». | < римская цифра > | "" < номер-аппарата > ::= "Апт" < номер-аппарата > | ""
На английский это переводится как:
Обратите внимание, что многие вещи (например, формат имени, номера квартиры, почтового индекса и римских цифр) здесь оставлены неуказанными. При необходимости их можно описать с помощью дополнительных правил BNF.
Идея описания структуры языка с помощью правил переписывания восходит, по крайней мере, к работам Панини , древнего индийского грамматика санскрита и уважаемого ученого в индуизме, который жил где-то между 6-м и 4-м веками до нашей эры . [3] [4] Его обозначения для описания структуры санскритских слов эквивалентны по силе обозначениям Бэкуса и имеют много схожих свойств.
В западном обществе грамматика долгое время рассматривалась как предмет преподавания, а не научного изучения; описания были неформальными и ориентированы на практическое использование. В первой половине 20-го века такие лингвисты , как Леонард Блумфилд и Зеллиг Харрис, начали попытки формализовать описание языка, включая структуру фраз .
Тем временем правила переписывания строк как формальные логические системы были введены и изучены такими математиками, как Аксель Туэ (в 1914 году), Эмиль Пост (1920–40-е годы) и Алан Тьюринг (1936). Ноам Хомский , преподававший лингвистику студентам теории информации в Массачусетском технологическом институте , объединил лингвистику и математику, взяв за основу для описания синтаксиса естественного языка то, что по сути является формализмом Туэ . Он также ввел четкое различие между порождающими правилами (контекстно -свободными грамматиками ) и правилами преобразования (1956). [5] [6]
Джон Бэкус , разработчик языка программирования в IBM , предложил метаязык «металингвистических формул» [1] [8] [9] для описания синтаксиса нового языка программирования IAL, известного сегодня как АЛГОЛ 58 (1959). Его обозначения впервые были использованы в отчете ALGOL 60.
BNF — это обозначение контекстно-свободных грамматик Хомского. Бэкус был знаком с работами Хомского. [10]
По предложению Бэкуса, формула определяла «классы», имена которых заключены в угловые скобки. Например, <ab>
. Каждое из этих названий обозначает класс основных символов. [1]
Дальнейшее развитие АЛГОЛА привело к созданию АЛГОЛА 60 . В отчете комитета за 1963 год Питер Наур назвал нотацию Бэкуса нормальной формой . Дональд Кнут утверждал, что BNF скорее следует читать как форму Бэкуса-Наура , поскольку она «не является нормальной формой в общепринятом смысле слова» [11] в отличие, например, от нормальной формы Хомского . Название « форма Панини Бэкуса» также однажды было предложено ввиду того факта, что нормальная форма расширения Бэкуса может быть неточной, и что Панини независимо разработал аналогичную систему обозначений ранее. [12]
BNF описан Питером Науром в отчете ALGOL 60 как металингвистическая формула : [13]
Последовательности символов, заключенные в скобки <>, представляют собой металингвистические переменные, значениями которых являются последовательности символов. Знаки "::=" и "|" (последние со значением «или») являются метаязыковыми связками. Любой знак в формуле, не являющийся переменной или связкой, обозначает сам себя. Сопоставление знаков или переменных в формуле означает сопоставление обозначенной последовательности.
Другой пример из отчета ALGOL 60 иллюстрирует основное различие между метаязыком BNF и бесконтекстной грамматикой Хомского. Металингвистические переменные не требуют правила, определяющего их формирование. Их формирование можно просто описать на естественном языке в скобках <>. Следующая спецификация комментариев к разделу 2.3 отчета ALGOL 60 показывает, как это работает:
Для включения текста в число символов программы соблюдаются следующие соглашения о комментариях:
Эквивалентность здесь означает, что любая из трех структур, показанных в левом столбце, может быть заменена в любом случае вне строк символом, показанным в той же строке в правом столбце, без какого-либо влияния на действие программы.
Наур изменил два символа Бэкуса на общедоступные символы. Первоначально этот ::=
символ был :≡
. Первоначально символом |
было слово « или » (с чертой над ним). [8] : 14
БНФ очень похож на уравнения булевой алгебры канонической формы , которые в то время использовались при проектировании логических схем. Бэкус был математиком и разработчиком языка программирования FORTRAN. Изучение булевой алгебры обычно является частью учебной программы по математике. Ни Бэкус, ни Наур не назвали заключенные в них имена нетерминалами. Терминология Хомского изначально не использовалась при описании БНФ. Позже Наур описал их как занятия по материалам курса ALGOL. [1] В отчете ALGOL 60 они были названы металингвистическими переменными. Все, кроме метасимволов , и имен классов, заключенных в, является символами определяемого языка. Метасимвол следует интерпретировать как «определяется как». Используется для разделения альтернативных определений и интерпретируется как «или». Метасимволы представляют собой разделители, заключающие в себе имя класса. BNF описан Питером Науром и Солом Розеном как метаязык разговоров об АЛГОЛЕ . [1]< >
::=
|
< >
::=
|
< >
В 1947 году Сол Розен стал участвовать в деятельности молодой Ассоциации вычислительной техники , сначала в комитете по языкам, который стал группой IAL и в конечном итоге привел к созданию ALGOL. Он был первым ответственным редактором журнала Communications of ACM. [ нужны разъяснения ] BNF впервые использовался в качестве метаязыка для обсуждения языка АЛГОЛ в отчете АЛГОЛ 60. Именно так это объясняется в материалах курса программирования ALGOL, разработанных Питером Науром в 1962 году. [1] Ранние руководства по ALGOL от IBM, Honeywell, Burroughs и Digital Equipment Corporation следовали за отчетом по ALGOL 60, используя его в качестве метаязыка. Саул Розен в своей книге [14] описывает BNF как метаязык разговоров об АЛГОЛЕ. Примером его использования в качестве метаязыка может быть определение арифметического выражения:
< выражение > ::= < термин > | < выражение >< добавление >< термин >
Первым символом альтернативы может быть определяемый класс, повторение, как объяснил Наур, имеет функцию указания того, что альтернативная последовательность может рекурсивно начинаться с предыдущей альтернативы и может повторяться любое количество раз. [1] Например, приведенное выше <expr>
значение определяется как <term>
за которым следует любое количество <addop> <term>
.
В некоторых более поздних метаязыках, таких как META II Шорра , конструкция рекурсивного повторения BNF заменяется оператором последовательности и символами целевого языка, определенными с использованием строк в кавычках. Кронштейны <
и >
были сняты. (
)
Добавлены круглые скобки для математической группировки. Правило <expr>
появится в META II как
EXPR = TERM $('+' TERM .OUT('ADD') | '-' TERM .OUT('SUB'));
Эти изменения позволили META II и производным от него языкам программирования определить и расширить свой собственный метаязык за счет возможности использовать описание естественного языка, металингвистическую переменную и описание языковых конструкций. Многие побочные метаязыки были вдохновлены BNF. [ нужна цитация ] См. META II , TREE-META и Metacompiler .
Класс BNF описывает формирование языковой конструкции, причем формирование определяется как шаблон или действие по формированию шаблона. Имя класса expr описывается на естественном языке как <term>
последовательность, за которой следует <addop> <term>
. Класс — это абстракция; мы можем говорить о нем независимо от его формирования. Мы можем говорить о термине, независимо от его определения, как о добавлении или вычитании в выражении. Мы можем говорить о том, что термин представляет собой определенный тип данных и о том, как выражение должно оцениваться с использованием определенных комбинаций типов данных или даже о переупорядочении выражения для группировки типов данных и результатов оценки смешанных типов. Дополнение к естественному языку предоставило конкретные детали семантики языковых классов, которые будут использоваться реализацией компилятора и программистом, пишущим программу на ALGOL. Описание на естественном языке также дополняло синтаксис. Правило целых чисел — хороший пример естественного и метаязыка, используемого для описания синтаксиса:
< целое число > ::= < цифра > | < целое число >< цифра >
Выше нет никаких подробностей о пустом пространстве. Согласно правилу, между цифрами может быть пробел. В естественном языке мы дополняем метаязык БНФ, объясняя, что последовательность цифр не может иметь пробелов между цифрами. Английский — лишь один из возможных естественных языков. Переводы отчетов ALGOL были доступны на многих естественных языках.
Происхождение BNF не так важно, как его влияние на развитие языков программирования. [ нужна цитация ] В период сразу после публикации отчета об Алголе 60 BNF был основой многих систем компилятора-компилятора .
Некоторые, такие как «Компилятор с синтаксическим управлением для АЛГОЛА 60», разработанный Эдгаром Т. Айронсом, и «Система построения компилятора», разработанная Брукером и Моррисом, напрямую использовали BNF. Другие, такие как метакомпиляторы Шорре, превратили его в язык программирования лишь с небольшими изменениями. <class name>
стали идентификаторами символов, отбросив заключающий их <,> и используя строки в кавычках для символов целевого языка. Группировка, подобная арифметике, обеспечивает упрощение, исключающее использование классов, для которых группировка была единственным значением. Правило арифметического выражения META II показывает использование группировки. Выражения вывода, помещенные в правило META II, используются для вывода кода и меток на языке ассемблера. Правила в META II эквивалентны определениям классов в BNF. Утилита Unix yacc основана на BNF, а создание кода аналогично META II. yacc чаще всего используется в качестве генератора синтаксического анализатора , и его корни, очевидно, лежат в BNF.
BNF сегодня является одним из старейших компьютерных языков, которые до сих пор используются. [ нужна цитата ]
Сам синтаксис BNF может быть представлен с помощью BNF следующим образом:
< синтаксис > ::= < правило > | < rule > < синтаксис > < rule > ::= < opt-whitespace > "<" < имя-правила > ">" < opt-whitespace > " ::= " < opt-whitespace > < выражение > < конец строки > < opt-whitespace > ::= " " < opt-whitespace > | "" < выражение > ::= < список > | < список > < opt-пробелы > "|" < opt-whitespace > < выражение > < конец строки > ::= < opt-whitespace > < EOL > | < конец строки > < конец строки > < список > ::= < термин > | < термин > < opt-пробелы > < список > < термин > ::= < литерал > | "<" < имя-правила > ">" < литерал > ::= '"' < текст1 > '"' | "'" < текст2 > "'" < текст1 > ::= "" | < символ1 > < текст1 > < текст2 > ::= "" | < символ2 > < текст2 > < символ > ::= < буква > | < цифра > | < символ > < буква > ::=«А» | «Б» | «С» | «Д» | «Е» | «Ф» | «Г» | «Ч» | «Я» | «Дж» | «К» | «Л» | «М» | «Н» | «О» | «П» | «Кью» | "Р" | "С" | «Т» | «У» | «В» | «В» | «Х» | "Й" | "З" | "а" | "б" | "с" | "д" | "е" | "ф" | "г" | "ч" | "я" | "Дж" | "к" | "л" | "м" | "н" | "о" | "п" | "д" | "р" | "с" | "т" | «ты» | "в" | "ш" | "х" | "й" | "z" < цифра > ::= "0" | «1» | «2» | «3» | «4» | «5» | «6» | «7» | «8» | "9" < символ > ::= "|" | " " | "!" | "#" | "$" | "%" | "&" | "(" | ")" | "*" | "+" | "," | "-" | "." | "/" | ":" | ";" | ">" | "=" | "<" | "?" | "@" | "[" | "\" | "]" | "^" | "_" | "`" | "{" | "}" | "~" < символ1 > ::= < символ > | "'" < символ2 > ::= < символ > | '"' < имя-правила > ::= < буква > | < имя-правила > < символ-правила > < символ-правила > ::= < буква > | < цифра > | "-"
Обратите внимание, что «» — это пустая строка .
В оригинальном BNF не использовались кавычки, как показано в <literal>
правиле. Это предполагает, что для правильной интерпретации правила пробелы не требуются.
<EOL>
представляет соответствующий спецификатор конца строки (в ASCII , возврат каретки, перевод строки или и то, и другое, в зависимости от операционной системы ). <rule-name>
и <text>
должны быть заменены именем/меткой или буквальным текстом объявленного правила соответственно.
В приведенном выше примере почтового адреса США вся блок-кавычка представляет собой файл <syntax>
. Каждая строка или непрерывная группа строк — это правило; например, одно правило начинается с <name-part> ::=
. Другая часть этого правила (кроме конца строки) — это выражение, состоящее из двух списков, разделенных вертикальной чертой |
. Эти два списка состоят из нескольких терминов (три термина и два термина соответственно). Каждый термин в этом конкретном правиле является именем правила.
Существует множество вариантов и расширений BNF, как правило, либо ради простоты и краткости, либо для адаптации к конкретному приложению. Одной из общих черт многих вариантов является использование операторов повторения регулярных выражений, таких как *
и +
. Расширенная форма Бэкуса-Наура (EBNF) является распространенной.
Еще одним распространенным расширением является использование квадратных скобок вокруг необязательных элементов. Хотя эта нотация не присутствовала в исходном отчете по ALGOL 60 (вместо этого была введена несколькими годами позже в определении IBM PL/I ), теперь она общепризнана.
Расширенная форма Бэкуса-Наура (ABNF) и форма Бэкуса-Наура маршрутизации (RBNF) [15] — это расширения, обычно используемые для описания протоколов Инженерной группы Интернета (IETF) .
Грамматики синтаксического анализа основаны на нотациях BNF и регулярных выражений , образуя альтернативный класс формальных грамматик , которые по сути являются аналитическими , а не порождающими по своему характеру.
Многие спецификации BNF, которые сегодня можно найти в Интернете, предназначены для чтения человеком и являются неформальными. Они часто включают в себя многие из следующих синтаксических правил и расширений:
[<item-x>]
.*
), например <word> ::= <letter> {<letter>}
или <word> ::= <letter> <letter>*
соответственно.+
например <word> ::= <letter>+
.< >
, например <ab>
, обозначают классы, членами которых являются последовательности основных символов. Обозначения классов такого рода встречаются в любом описании языка. Для описания обычных естественных языков используются такие обозначения, как слово, глагол, существительное. . [7] : 5, примечание 1