Extra Credit Problem (5% of final grade) Due on Canvas *Tuesday Dec 1* (extended), 11:59pm. No late submission will be graded. You just need to submit your cky.py. After submission you'll need to demonstrate it to a TA in 5 minutes. * Implement the CKY parsing algorithm: for a given grammar in CNF and no epsilons, print *all* parse trees (if any) for input strings (this implies we can use CKY to test if a string is ambiguous). Your must code in Python, and you will need to demo it to a TA. Plagiarism will be severely punished. * Grading: 1% for membership test (whether string is in the language, i.e., whether it has at least one parse tree) 1% for correct implementation of dynamic programming (DP) note: it might be doable w/o DP, but _extremely_ slow (exponential-time) 1% for correctly printing (at least) one parse tree 1% for correctlly printing *two* parse trees (challenging!) 1% for efficiently printing the number of parse trees (very challenging!) * Command-Line (strictly enforced): input/output should be from/to standard IO via piping and output redirect (to read from standard input in Python you use "sys.stdin"): cat | python cky.py > where and are discussed below. * Input format (strictly enforced): First the CFG in CNF (no epsilons). One non-terminal each line. Each rule within a nonterminal is separated by a bar "|". The first nonterminal is assumed the start symbol. After a blank line which ends the CFG, there are a few lines of strings to be parsed. Each string occupies a line, and each terminal ("a", "b") is separated by a space. Note a terminal can sometimes have more than one characters. Here is an example (the "==="s are NOT part of input/output): ===================================== S -> A C | S S | A B A -> a B -> b C -> S B a b a b a a b b a b a b a b a a a b a b a b a b a b a b a b a b a b a b a b a b a b a b a b a b a b a b ===================================== * Output format (strictly enforced): For each string in the input, first output how many parse trees, and then print *up to two* parse trees, each on a line. the tree format is: ( ... ) where is the root symbol and the subtrees follow the same format. Note: if there are more than two parse trees, you should only print the first two. Here is the expected output for the above input: ===================================== a b a b: 1 parse tree (S (S (A a) (B b)) (S (A a) (B b))) a a b b: 1 parse tree (S (A a) (C (S (A a) (B b)) (B b))) a b a b a b: 2 parse trees (S (S (A a) (B b)) (S (S (A a) (B b)) (S (A a) (B b)))) (S (S (S (A a) (B b)) (S (A a) (B b))) (S (A a) (B b))) a a: 0 parse trees a b a b a b a b a b a b a b a b a b a b a b a b a b a b a b a b a b a b: 129644790 trees (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (A a) (B b))))))))))))))))))) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (A a) (B b)) (S (S (S (A a) (B b)) (S (A a) (B b))) (S (A a) (B b)))))))))))))))))) ===================================== See more input/output testcases in http://classes.engr.oregonstate.edu/eecs/fall2015/cs321/cfg.tgz