> ... that will be used to parse: `string -> object`

Em, no. The output of a parser is not an "arbitrary object". It is **parse tree** (and a boolean indicating if the input string matched the given grammar or not).

> I haven't seen any data structures for defining how stringifying would work (similar to a PEG), but I think this would be possible.

That is because there is **no datastructure needed** to stringify a parse tree. Just do a depth-first in-order tree traversal and concatenate the string representation of the terminal nodes - that should result in the same string as you started with (assumed your parser did not swallow characters like whitespaces from the tree).