While the features of EBNF are straightforward, the actual notation can appear in a few different forms. I'll be using the terminology and notation of ISO/IEC 14977 : 1996(E) (it's available as a PDF if you Google for it).
The regular expression a+
is a Terminal-string (§5.2) followed by a Repeated-sequence (§5.6). The EBNF form would be:
"a", {"a"}
The regular expression a((xa)*ya)
is a bit more complicated. If you first look at just a(ya)
, you have a Terminal-string followed by a Grouped-sequence (§5.4). It would look like this:
"a", ("y", "a")
The subexpression (xa)*
by itself is a Repeated-sequence containing a sequence of two Terminal-strings. It alone would look like this:
{"x", "a"}
You can combine the previous two items to obtain the EBNF form for the complete expression:
"a", ({"x", "a"}, "y", "a")
The final expression introduces two additional concepts, specifically the Definitions-list (§5.10) and the Optional-sequence (§5.5). The subexpression (bb|(p)*d)
includes a Definitions-list. The EBNF for this subexpression alone is the following:
("b", "b" | {"p"}, "d")
When you include the optional quantifier, which expands this to the subexpression (bb|(p)*d)?
, you update the EBNF to the following:
[("b", "b" | {"p"}, "d")]
Since the Optional-sequence also serves as a grouping construct, you can remove the unnecessary start-group-symbol and end-group-symbol to obtain the following:
["b", "b" | {"p"}, "d"]
By combining the steps used above, you can obtain the EBNF form for the complete third regular expression:
"e", {"e"}, ["b", "b" | {"p"}, "d"], "c"