2.4 cfl

Refer to the exercise policy for details.
Do the exercises in sections 2.1 and 2.2 in the textbook.
Implement an interpreter for CFGs that takes their tuple representation and can generate strings from the language. I suggest implementing a mode that randomly generates one string and another version that generates all strings up to some depth.
Implement a compiler from general CFGs to CFGs in Chomsky normal form.
Implement a compiler from CFGs to PDAs.
Implement an interpreter for PDAs that takes their tuple representation and a string, then returns whether the string is accepted or not.
Implement a compiler from PDAs to CFGs.