Logic in parseModel could potentially be greatly simplified if a 3rd-party parser generator were used: you could supply a parser generator with a grammar to get back a parser then run this on the input string and get back a structured object representing the tokenised set of rules. A list of parser generators: http://www.wikiwand.com/en/Comparison_of_parser_generators. The key thing will be to determine what class of grammar needs parsing (regular, context free, context sensitive etc).
I thought about this of course when first writing the code, but it seemed like complete overkill for such a simple grammar and no simpler than simply writing the pushdown automaton parser I implemented...
Logic in parseModel could potentially be greatly simplified if a 3rd-party parser generator were used: you could supply a parser generator with a grammar to get back a parser then run this on the input string and get back a structured object representing the tokenised set of rules. A list of parser generators: http://www.wikiwand.com/en/Comparison_of_parser_generators. The key thing will be to determine what class of grammar needs parsing (regular, context free, context sensitive etc).
I had a brief look at arpeggio, which seems to have a simple API: http://www.igordejanovic.net/Arpeggio/stable/tutorials/calc/.