title: OOP design of tool for teaching formal languages & automata
body: <p>I am thinking of using some spare time to play around with designing and implementing a teaching tool for a course on formal languages and automata theory. I am trying to decide whether an OOP implementation would be appropriate and, if so, whether anyone can suggest high-level improvements to the design I outline below.</p>
  
  <p>There are lots of potential classes revealed in the linguistic analysis. Some (and please let me know if I've missed anything fundamental) are: grammar; nonterminal; terminal; production; regular grammar; context-free grammar; context-sensitive grammar; unrestricted grammar; automaton; state; symbol; transition; DFA; NFA; NFA-Lambda; DPDA; PDA; LBA; Turing machine.</p>
  
  <p><strong>Question 1: Should each kind of grammar get its own class in the implementation, or should an over-arching grammar class have methods to determine what kind of grammar it is (e.g., "isRegular()", "isContextFree()", etc.)</strong> <em>(more generally, should classes which differ only a little in the domain model, and only in terms of behavior, be represented via inheritance in the implementation, or is it better to simply push different kinds of behavior into the parent class?)</em></p>
  
  <p><strong>Question 2: Should things like "Symbol", "State", "Nonterminal", etc. get their own classes in the implementation, or should these be dominated by their containers?</strong> <em>(more generally, should very simple classes in the domain model be given their own classes in the implementation - e.g. for extensibility - or should that be pushed into the container class?)</em></p>
  
  <p><strong>Question 3: Should Transition be its own class in the implementation and, if so, will I need to subclass it in order to support each kind of automaton (since, besides differing in terms of the state, they also differ in terms of what happens during transitions)?</strong> <em>(more generally, is it good practice to have two abstract parent classes where there is a bijection between the children of one and the children of another... coupling?)</em></p>
  
  <p>I realize that, at the end of the day, a lot of these decisions are simply design decisions, but I would like to know what you guys think about best practices in OOP design. Moreover, and the reason I'm not just asking the "more generally" questions as pure OOP design questions is that I'd like special perspective from people who have experience with this kind of domain (languages &amp; automata).</p>
  
  <p>Any help is greatly appreciated.</p>