So the best of both worlds, it sounds to me, would be parser combinators: They're both native to the language, and they're DSLs. So there's only one set of syntax for the programmer, and they still compose declaratively as opposed to writing recursive parsers manually.