And not even just parsing as most people interpret it. Most practical custom data types can be expressed using a BNF grammar or something close to it (formally in the language, or informally by understanding the language and its representations). The structure of the code falls out of that in many situations (though certainly not all) as it determines what can be done at any particular point.
Oh, how I wish more protocols in particular had been defined in something like BNF, and asked themselves for very good reasons why they insist on something that makes that hard.
So many abominations of data structure and protocol designs have come out of people not bothering to write down a grammar of any type until after they'd already come up with something broken.
In fact, I'm hacking on a Ruby implementation where just operator overloading and some simple methods is sufficient to get a BNF variant written as code to return a structure encoding parser combinators on execution.
(There's nothing new about that, it's been done before, other than perhaps the sick and twisted levels of abuse of the Ruby syntax I'm toying with thanks to a newish feature (refinements) to make it look closer to plain BNF).
And if course, automatically "compiling" bnf into parser combinators is easy.