Редактировать: короткий ответ, *
означает «ноль или более повторений» почти во всех синтаксисах регулярных выражений / грамматик, включая perl5 и RFC 5234. *
обычно связывает более тесно, чем объединение и чередование.
Youскажем, вы хотите язык над алфавитом (a, b), но включите в свои выражения c
и U
.Я собираюсь предположить, что вам нужна грамматика языка над алфавитом (a, b, c) в форме, подобной BNF, с регулярным выражением, где U
- оператор объединения с низким приоритетом, аналогично |
в perlre.
В этом случае
a|b*
эквивалентно BNF:
L := a
| <M>
M := epsilon
| b <M>
Оператор *
означает ноль илиболее того, первое предложение в M
является базовым случаем, а второе предложение - рекурсивное использование M
, которое включает в себя терминал b
.
L - это просто один терминал a
или нетерминал M
.
(ab*|c)
L ::= a <M>
| c
M ::= epsilon
| b <M>
M выводится так же, как и выше, а остальное не требует пояснений.
ab*|bc*
L ::= a <M>
| b <N>
M ::= epsilon
| b <M>
N ::= epsilon
| c <N>
N выводится так же, как и выше М.
a*bc*|ac
*
в большинстве языков регулярных выражений связывается более тесно, чем конкатенация, так что это то же самое, что
(a*b(c*))|(ac)
, который сводится к
L ::= <M> b <N>
| a c
M ::= epsilon
| a <M>
N ::= epsilon
| c <N>
В общем, чтобы преобразовать регулярное выражение в BNF, вы симply использует смежность в регулярном выражении для обозначения смежности в BNF, а U
или |
в регулярном выражении означает |
в BNF.
Если вы определяете нетерминал <X> ::= x
, тогда вы можете обрабатывать x*
Таким образом:
L ::= epsilon
| <X> <L>
С тем же нетерминалом <X> ::= x
, тогда вы можете обрабатывать x+
, таким образом:
L ::= <X>
| <L> <X>
, что дает вам операторы повторения *
и +
который оставляет ?
.x?
это просто
L ::= epsilon
| <X>