CombinedParsers.BNF.ebnf โ Constant
ebnf

Parser to create a CombinedParser from EBNF syntax:

julia> p = ebnf"""
digit excluding zero = "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
digit                = "0" | digit excluding zero ;
natural number       = digit excluding zero, { digit } ;
integer              = "0" | [ "-" ], natural number ;
"""
|๐ Either
โโ |๐ Either |> with_name(:integer)
โ  โโ 0
โ  โโ ๐ Sequence
โ     โโ \-? |
โ     โโ ๐ Sequence |> with_name(:natural number) # branches hidden
โโ ๐ Sequence |> with_name(:natural number)
โ  โโ |๐ Either |> with_name(:digit excluding zero) # branches hidden
โ  โโ |๐* Either |> with_name(:digit) |> Repeat
โ     โโ 0
โ     โโ |๐ Either |> with_name(:digit excluding zero) # branches hidden
โโ |๐ Either |> with_name(:digit)
โ  โโ 0
โ  โโ |๐ Either |> with_name(:digit excluding zero) # branches hidden
โโ |๐ Either |> with_name(:digit excluding zero)
โโ 1
โโ 2
โโ 3
โโ 4
โโ 5
โโ 6
โโ 7
โโ 8
โโ 9
::Union{SubString{String}, Tuple{SubString{String}, Vector{SubString{String}}}, Tuple{AbstractString, Tuple{SubString{String}, Vector{SubString{String}}}}}

julia> p[:integer]("42")
("", ("4", SubString{String}["2"]))

A (too complicated) result type is derived implicitly. You can map transform results of parts of a EBNF parser with the deepmap function:

julia> deepmap(MatchedSubSequence, p, :integer)[:integer]("42")
"42"
Note

I want to support more BNF variants. Contributions of test cases are welcome! A EBNF Syntax draft built from Wikimedia Ebnf-syntax-diagram.

Warn

Left recursion is not yet supported (will lead to a stack overflow).