__author__  = "Hugo Liu <hugo@media.mit.edu>"
__version__ = "1.3.1"
import sys,string
import MontyUtils
from types import *
class ContextualRuleParser:


    contextualrules_filename = 'CONTEXTUALRULEFILE'
    rules = []
    rule_names = ['PREVTAG','NEXTTAG','PREV1OR2TAG','NEXT1OR2TAG','PREV1OR2OR3TAG','NEXT1OR2OR3TAG','SURROUNDTAG','PREVBIGRAM','NEXTBIGRAM','PREV2TAG','NEXT2TAG']
    def __init__(self):

        self.contextualrules_filename = MontyUtils.MontyUtils().find_file(self.contextualrules_filename)
        if self.contextualrules_filename == '':
            print "ERROR: could not find CONTEXTUALRULEFILE"
            print "in current dir, %MONTYLINGUA% or %PATH%"
        self.populate_from_file(self.contextualrules_filename)
        print "ContextualRuleParser OK!"
        return
    def apply_rules_to_all_words_brill(self,text_arr):

        rules = self.rules
        for i in range(len(rules)):
            rule = rules[i]
            for j in range(len(text_arr)):
                self.apply_rule(rule,text_arr,j)
        return
    def apply_rules_to_all_words(self,text_arr,depth_or_breadth_first_firing='depth'):

        if depth_or_breadth_first_firing=='breadth':
            exhaustive_p = 0
        else:
            exhaustive_p = 1
        dirtyBit = 1
        while (dirtyBit):
            dirtyBit = 0
            for i in range(len(text_arr)):
                res = self.apply_rules_to_one_word(text_arr,i,exhaustive_p)
                if res:
                    dirtyBit = 1
        return
    def apply_rules_to_one_word(self,text_arr,word_index,exhaustive_p=0):

        rules = self.rules
        wordLevelDirtyBit = 0
        dirtyBit = 1
        while (dirtyBit):
            dirtyBit = 0
            for i in range(len(rules)):
                rule = rules[i]
                cur_pos = text_arr[word_index]['pos']
                res = self.apply_rule(rule,text_arr,word_index)
                if res:
                    dirtyBit = 1
                    wordLevelDirtyBit = 1
                    print "DEBUG: POS of word",text_arr[word_index]['word'],"changed from",cur_pos,"to",text_arr[word_index]['pos']
                    if not exhaustive_p:
                        return wordLevelDirtyBit
        return wordLevelDirtyBit
    def apply_rule(self,rule,text_arr,word_index):

        dirtyBit = 0
        pos = text_arr[word_index]['pos']
        all_pos = text_arr[word_index]['all_pos']
        pred = rule[0]
        args = rule[1]
        from_tag = args[0]
        to_tag = args[1]
        real_args = args[3:]
        if from_tag != pos:
            return dirtyBit
        if 'UNK' not in all_pos and to_tag not in all_pos:
            return dirtyBit
        prevprevprev = ''
        prevprev = ''
        prev = ''
        next = ''
        nextnext = ''
        nextnextnext = ''
        if word_index > 2:
            prevprevprev = text_arr[word_index-3]['pos']
        if word_index > 1:
            prevprev = text_arr[word_index-2]['pos']
        if word_index > 0:
            prev = text_arr[word_index-1]['pos']
        if word_index < len(text_arr)-3:
            nextnextnext = text_arr[word_index+3]['pos']
        if word_index < len(text_arr)-2:
            nextnext = text_arr[word_index+2]['pos']
        if word_index < len(text_arr)-1:
            next = text_arr[word_index+1]['pos']
        if pred == 'PREVTAG':
            if real_args[0] in [prev]:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        elif pred == 'NEXTTAG':
            if real_args[0] in [next]:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        elif pred == 'PREV1OR2TAG':
            if real_args[0] in [prev,prevprev]:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        elif pred == 'NEXT1OR2TAG':
            if real_args[0] in [next,nextnext]:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        elif pred == 'PREV1OR2OR3TAG':
            if real_args[0] in [prev,prevprev,prevprevprev]:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        elif pred == 'NEXT1OR2OR3TAG':
            if real_args[0] in [next,nextnext,nextnextnext]:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        elif pred == 'SURROUNDTAG':
            if real_args[0] is prev and real_args[1] is next:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        elif pred == 'PREVBIGRAM':
            if [real_args[0],real_args[1]] is [prevprev,prev]:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        elif pred == 'NEXTBIGRAM':
            if [real_args[0],real_args[1]] is [next,nextnext]:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        elif pred == 'PREV2TAG':
            if real_args[0] in [prevprev]:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        elif pred == 'NEXT2TAG':
            if real_args[0] in [nextnext]:
                text_arr[word_index]['pos'] = to_tag
                dirtyBit = 1
        return dirtyBit
    def populate_from_file(self,filename):

        try:
            f = open(filename,'r')
            line = f.readline()
            while line:
                toks = string.split(line)
                pred = toks[2]
                args = toks
                rule = [pred,args]
                self.rules.append(rule)
                line = f.readline()
            f.close()
        except:
            print "Error parsing contextual rule file!"
            sys.exit(-1)
        return