Interesting, I do a similar thing for database upgrades - I extract related changes for a particular upgrade from the individual table descriptions, but they may express additional constraints with a "do this after that one", or "do this before that one". It looks like this:
[version 92 replace:
itemtype enum('publication') not null default 'publication'
flavour int(11) not null
using (do before publication):
# database upgrade code for this change
# which relies on the old version of the 'publication' table
I resolve the ordering using an approach similar to japhy's solution above, but at each pass I look for both things that can happen first and things that can happen last; when all constraints are satisfied, anything else can go in the middle. (If constraints remain, and a pass through the data finds neither a new 'first' nor a new 'last', there is a dependency loop.)