Advertisement
dechicom

generative grammar and langage generation

Feb 12th, 2020
215
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 6.52 KB | None | 0 0
  1. #!/bin/python
  2. '''
  3. Dgramgen.py
  4. grammar generator
  5. '''
  6.  
  7.  
  8. import string as ST
  9. from operator import itemgetter
  10. import warnings as WA
  11. class Gramgen(object):
  12.     '''
  13.    '''
  14.     def __init__(self,Vn,Vt,R,S,max_len):
  15.         self.Vn = Vn
  16.         self.Vt = Vt
  17.         self.R = R
  18.         self.Vn.sort()
  19.         self.Vt.sort()
  20.         self.R.sort()
  21.         print self.R
  22.         self.d = dict()
  23.         self.L = list()
  24.         self.S = S
  25.         self.shringking_rules()
  26.         self.max_len=max_len
  27.     def shringking_rules(self):
  28.         for lr,rr in self.R:
  29.             l  = self.count_terminals(lr)
  30.             r  = self.count_terminals(rr)
  31.             if l > r:
  32.                 WA.warn("word length prediction not accurate due to shrinking rules")
  33.                 break
  34.        
  35.     def count_non_terminals(self,string):
  36.         n=0
  37.         for s in string:
  38.             if s in self.Vn:
  39.                 n+=1
  40.         return n
  41.     def count_terminals(self,string):
  42.         n=0
  43.         for s in string:
  44.             if s in self.Vt:
  45.                 n+=1
  46.         return n
  47.            
  48.     def non_terminal_pos(self,P,start=0):
  49.         post=0
  50.         nbr_Vn=0
  51.         for i in xrange(start,len(P)):
  52.             if P[i] in self.Vn:
  53.                 return i
  54.         return -1
  55.     def extend_R (self):
  56.         '''
  57.        copy the rules list and append information:
  58.        pos is the pos of the first non-terminal character
  59.        in lr (left part of the rule) or rr (right part of rule)
  60.        '''
  61.         self.ext_R=list()
  62.         for r in self.R:
  63.             lr,rr=r
  64.             lr_pos=self.non_terminal_pos(lr)
  65.             rr_pos=self.non_terminal_pos(rr)
  66.             lr_len=len(lr)
  67.             rr_len=len(rr)
  68.             self.ext_R.append((lr,lr_pos,rr,rr_pos,lr_len,rr_len))
  69.         #print self.ext_R
  70.     def order_R(self):
  71.         '''
  72.        '''
  73.         self.lr_poskey=dict()
  74.         for ext_r in self.ext_R:
  75.             try:
  76.                 lr_pos=ext_r[1]
  77.                 ext_r_list=self.lr_poskey[lr_pos]
  78.             except (KeyError):
  79.                 self.lr_poskey[lr_pos]=[ext_r]
  80.                 continue
  81.             ext_r_list.append(ext_r)
  82.         for key, value in self.lr_poskey.iteritems():
  83.             value=sorted(value,key=itemgetter(4))
  84.             self.lr_poskey[key]=value
  85.  
  86.         #print self.lr_poskey
  87.  
  88.     def order_R2(self):
  89.         '''
  90.        we want to produce 3 imbricated dictionaries
  91.        self.lr_pos_dic={lr_pos:{lr_len:{lr:[[rr1,rrpos1],[rr2,rrpos2]]}},.....}
  92.        '''
  93.         self.lr_pos_dic=dict()
  94.         for ext_r in self.ext_R:
  95.             lr,lr_pos,rr,rr_pos,lr_len,rr_len=ext_r
  96.             if lr_pos in self.lr_pos_dic:
  97.                 lr_len_dic=self.lr_pos_dic[lr_pos]
  98.             else:
  99.                 self.lr_pos_dic[lr_pos]=lr_len_dic=dict()
  100.             if lr_len in lr_len_dic:
  101.                 lr_dic=lr_len_dic[lr_len]
  102.             else:
  103.                 lr_len_dic[lr_len]=lr_dic=dict()
  104.             if lr in lr_dic:
  105.                 lr_dic[lr].append([rr,rr_pos])
  106.             else:
  107.                 lr_dic[lr]=[[rr,rr_pos],]
  108.  
  109.         for key, value in self.lr_pos_dic.iteritems():
  110.             value=list(value.iteritems())
  111.             value=sorted(value,key=itemgetter(0))
  112.             self.lr_pos_dic[key]=value
  113.                
  114.  
  115.     def gen (self):
  116.         '''
  117.        '''
  118.         self. extend_R()
  119.         self.order_R()
  120.         self.order_R2()
  121.         self.gen2D(self.S,0)
  122.        
  123.     def gen2(self,P,nt_pos):
  124.         '''
  125.        '''
  126.         if nt_pos <0:
  127.             if len(P) <= self.max_len:
  128.                 self.L.append(P)
  129.                 return
  130.             else:
  131.                 return
  132.         elif nt_pos >=self.max_len :
  133.             return
  134.         derivation=False
  135.         for lr_pos,ext_r in self.lr_poskey.iteritems():
  136.             start = nt_pos- lr_pos
  137.             if start  < 0 :
  138.                 continue
  139.             else:
  140.                 for er in ext_r:
  141.                     lr,lr_pos,rr,rr_pos,lr_len,rr_len=er
  142.                     end=start+len(lr)
  143.                     if end > len(P):
  144.                         print "P lr",P,lr
  145.                         break
  146.                     if P[start:end]==lr:
  147.                         derivation=True
  148.                         newP = P[:start] + rr + P[end:]
  149.                         if rr_pos < 0:
  150.                             new_nt_pos = self.non_terminal_pos(newP,start+rr_len)
  151.                         else:
  152.                             new_nt_pos = start + rr_pos
  153.                         self.gen2(newP,new_nt_pos)
  154.         if  derivation==False:
  155.             raise Exception("Derivation impossible")
  156.        
  157.     def gen2D(self,P,nt_pos):
  158.         '''
  159.        this is a more optimized algorithm that should work better
  160.        when there are a lot of rules. need further tests  
  161.        '''
  162.         if nt_pos <0:
  163.             if len(P) <= self.max_len:
  164.                 self.L.append(P)
  165.                 return
  166.             else:
  167.                 return
  168.         elif nt_pos >=self.max_len :
  169.             return
  170.         derivation=False
  171.         for lr_pos,lr_len_dic in self.lr_pos_dic.iteritems():
  172.             start = nt_pos- lr_pos
  173.             if start  < 0 :
  174.                 continue
  175.             else:
  176.                 for lr_len,lr_dic  in lr_len_dic:
  177.                    
  178.                     end=start+lr_len
  179.                     if end > len(P):
  180.                         print "P lr",P,P[start:end]
  181.                         break
  182.                     try:
  183.                         rr_list=lr_dic[P[start:end]]
  184.                     except:
  185.                         continue
  186.                     for rr,rr_pos in rr_list:
  187.                         derivation=True
  188.                         newP = P[:start] + rr + P[end:]
  189.                         if rr_pos < 0:
  190.                             new_nt_pos = self.non_terminal_pos(newP,start+len(rr))
  191.                         else:
  192.                             new_nt_pos = start + rr_pos
  193.                         self.gen2D(newP,new_nt_pos)
  194.         if  derivation==False:
  195.             raise Exception("Derivation impossible")
  196.        
  197. if __name__ =="__main__":
  198.     '''
  199.    exemple with rules generating langage with Na(P)=Nb(P)
  200.    same number of a and b in each word of L
  201.    '''    
  202.     S="S"
  203.     Vn=["S","A","B"] # non terminal
  204.     Vt=["a","b"]     # terminal
  205.     print Vn,Vt
  206.     R=[("S","aB"),  ("A","a"),("A","aS"),("A","bAA"),
  207.        ("S","bA"),("B","b"),("B","bS"),("B","aBB")]
  208.     Lg=Gramgen(Vn,Vt,R,S,16)
  209.     Lg.gen()
  210.     print Lg.L
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement