from __future__ import division
from pprint import pprint
from collections import defaultdict
import matplotlib.pyplot as plt
import nltk
from nltk.corpus import treebank

import lab3_fix
from lab3_fix import parse_grammar

from nltk.app import rdparser_app as rd

def production_distribution(psents):
    """ Creates a frequency distribution of lexical and non-lexical (grammatical) productions
    """
    lexdict = defaultdict(int)
    nonlexdict = defaultdict(int)
    for psent in psents:
        for production in psent.productions():
            if production.is_lexical():
                pass # students replace this
            else:
                pass # students replace this
    return lexdict, nonlexdict

#This function takes a single parsed sentence, 
#and prints the parse along with the list of all productions used in it. 
def print_parse_info(psent):
    print("\nFirst parsed sentence:\n{}".format(psent))
    print("\nProductions in the first sentence:")
    pprint(psent.productions())

#This function is not used in the current version of the lab, but you can
#play with it if you want. Unfortunately, for me it is giving an error
#from the nltk libraries.  It still outputs the parse but also the error,
#so the output is a bit messy.
#What you'll see in the output (besides the error) is a trace of the actions
#of the parser (Expand, Match, or + to indicate a completed parse) and,
#if the parse was successful, you will also see the Tree that was found.
#This function returns a generator object. If you call the next() method
#on that, it will return the next parse (if any), and the next, and so on. e.g.,
#
# pgen = recursive_descent_parser(g, s) #will print first parse
# pgen.next()  #will print next parse if there's another
def recursive_descent_parser(grammar, sentence):
    """ recursive_descent_parser takes grammar and sentence as input and 
    parses the sentence according to the grammar using recursive descent parsing technique.
    
    """
    # Loads the Recursive Descent Parser with the grammar provided
    rdp = nltk.RecursiveDescentParser(grammar, trace=2)
    # Parses the sentence and saves the generator object 'parse'
    parse = rdp.parse(sentence.split())
    # calling next() on the generator returns the next (here, first) parse
    return parse.next()

def app(grammar,sent):
    """ Create a recursive descent parser demo, using a simple grammar and
    text.
    """    
    rd.RecursiveDescentApp(grammar, sent.split()).mainloop()

## Main body of code ##

grammar1=parse_grammar("""
    # Grammatical productions.
     S -> NP VP
     NP -> Pro | Det N | N
     Det -> Art
     VP -> V | V NP | V NP PP
     PP -> Prep NP
   # Lexical productions.
     Pro -> "i" | "we" | "you" | "he" | "she" | "him" | "her"
     Art -> "a" | "an" | "the"
     Prep -> "with" | "in"
     N -> "salad" | "fork" | "mushrooms"
     V -> "eat" | "eats" | "ate" | "see" | "saw" | "prefer" | "sneezed"
     Vi -> "sneezed" | "ran"
     Vt -> "eat" | "eats" | "ate" | "see" | "saw" | "prefer"
     Vp -> "eat" | "eats" | "ate" | "see" | "saw" | "prefer"
    """)

sentence1 = "he ate salad"
app(grammar1, sentence1)
#sentence2 = "he ate salad with mushrooms"
#sentence3 = "he ate salad with a fork"

# Extracting tagged sentences using NLTK libraries
#psents = treebank.parsed_sents()
# print info for the 0'th parsed sentence
#print_parse_info(psents[0])

