Cleanup and idiomaticize rule/expression dot graph output.

This idiomaticizes the rule printing code a bit. I didn't end up using templates for the multi-line Sprintfs() because I think it would have been uglier (having to define multiple one-use struct types just for the templates) than just using Sprintf().