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).