— соответствует строке, которая приведена в одинарных кавычках. Например,
'template'
соответствует строке
template
.
Терминалы могут использоваться совместно с нетерминальными конструкциями в более сложных выражениях.
□
A?
означает, что выражение
A
необязательно и может быть пропущено.
□
A | B
соответствует либо выражению
A
, либо выражению
B
, но не им обоим одновременно (строгое "или"). Выражения
такого вида называют иначе выбором.
□
A B
означает, что за выражением
A
следует выражение
B
. Последовательность имеет приоритет по сравнению с выбором —
A B | C D
означает последовательность выражений
A
и
B
или последовательность выражений
C
и
D
.
□
A - B
соответствует строке, которая соответствует выражению
A
, но не выражению
B
.
□
A+
означает последовательность из одного или более выражения
A
. Оператор "
+
" в EBNF старше оператора выбора,
A+ | B+
означает последовательность из одного или более выражения
A
или последовательность из одного или более выражения
B
.
□
A*
означает последовательность из нуля или более выражений
A
. Аналогично оператору "
+
", оператор "
*
" старше оператора выбора
□
(выражение)
— круглые скобки используются для группировки выражений. Выражения, заключенные в скобки, рассматриваются, как отдельная единица, которая может быть свободно использована в приведенных выше конструкциях. Например, выражение
A B C | B C | A D C | D C | C
можно переписать в виде
(A? (B | D) ) C
.
Нотация расширенных форм Бэкуса-Наура может с первого взгляда показаться очень сложной, однако, на самом деле это не так. Достаточно разобрать несколько примеров, как все встанет на свои места.
Пример
Рассмотрим реальную продукцию
Digits
языка XPath.
Digits
— это последовательность из нескольких цифр от
0
до
9
и определяется она следующим образом:
Digits ::= [0-9] +
Как правило, продукции в спецификациях языков пронумерованы для того, чтобы было легче на них ссылаться. Мы будем по возможности приводить эти номера так, как они указаны в технических рекомендациях — в квадратных скобках, например:
[31] Digits ::= [0-9]+
При помощи продукции Digits определяется такая продукция, как Number, которая соответствует числу. Число — это последовательность цифр, разделенная точкой на целую и дробную части:
[30] Number ::= Digits ('.' Digits?)?
| '.' Digits
Чтобы лучше понять EBNF, попробуем немного упростить эту продукцию. Выражение
Digits?
внутри круглых скобок означает, что
Digits
может как присутствовать, так и быть
опущенным, то есть
('.' Digits?) ?
равносильно
'.' ? | ('.' Digits)?
. Повторяя еще раз подобное упрощение с каждым из полученных выражений, в итоге преобразуем правило
Number
к виду:
Number ::= Digits
| Digits '.' Digits
| Digits '.'
| '.' Digits
Следовательно, число имеет четыре варианта синтаксиса:
□ последовательность цифр, например
12345
;
□ последовательность цифр, разделенная точкой на целую и дробную части, например
3.14
;
□ последовательность цифр, заканчивающаяся точкой, например
6.
— что эквивалентно
6.0
;
□ последовательность цифр, начинающаяся точкой, например
.5
, что эквивалентно
0.5
.
Разберем еще одну продукцию языка XPath — определение литерала. Литерал в XPath — это последовательность символов, заключаемая в одинарные или двойные кавычки, которая используется в качестве строкового параметра в функциях и т.д. Единственным и вполне логичным ограничением на синтаксис литерала является то, что он не может содержать символ собственных кавычек — в этом случае непонятно, где же на самом деле литерал кончается, а где начинается (например,
'ab'cd'
).
Конструкция
Literal
задается следующим образом:
[29] Literal ::= '"' [^"]* '"'
| "'" [^']* "'"
В первом случае синтаксис литерала начинается двойными кавычками (
'"'
), затем идет последовательность, состоящая из любых символов, кроме двойных кавычек (
[^"]*
), затем закрывающие двойные кавычки (
'"'
). Во втором случае синтаксис имеет точно такой же вид с точностью до замены одинарных кавычек двойными и наоборот.
Другим очень часто используемым правилом является правило, определяющее пробельное пространство (англ. space или whitespace). Пробельными символами в XML-языках считаются такие символы, как табуляция, перевод строки, возврат каретки и сам пробел. Продукция
S
пробельного пространства задается, как последовательность из одного или более пробельного символа:
[3] S ::= (#х20 | #х9 | #xD | #хА)+
Как правило, EBNF-продукции языков XML-группы составлены довольно просто, но в некоторых случаях они разбиты на несколько правил, которые определены в разных частях спецификации. В таких случаях мы будем по возможности упрощать продукции, записывая их в раскрытом виде.
Обозначения
Для того чтобы текст книги был более понятен, мы будем использовать некоторые соглашения.
Прежде всего, код программ и текст XML-документов будет выделяться моноширинным шрифтом
Courier
. Листингам многих примеров будут предшествовать заголовки вида
Листинг 2.1. Входящий документ
<!-- Текст входящего документа -->
Для того чтобы текст XML-документов был более наглядным, в листингах он будет форматироваться с пробельными отступами, например: