Beispiel #1
0
 def parse(self, ee):
     self.name = ee.tag
     for e in e.findall(slpsns.bgf_('*')):
         if e.tag == 'expression':
             ne = BGF3.Expression()
         elif e.tag == 'production':
             ne = BGF3.Production()
         else:
             print('Unknown parameter of type', e.tag)
             ne = None
         ne.parse(e)
         self.params.append(ne)
Beispiel #2
0
def projectSymbols(xs,ss):
	if xs.who() == 'Sequence':
		e = BGF3.Sequence()
		for x in xs.data:
			# TODO: now works only for nonterminals
			if x.wrapped.who() == 'Nonterminal' and x.wrapped.data in ss:
				m = BGF3.Marked()
				m.setExpr(BGF3.Expression(x))
				e.add(m)
			else:
				e.add(x)
		return e
	else:
		print('projectSymbols not implemented for',xs.who())
		print('■')
		sys.exit(1)
Beispiel #3
0
def renameNinExpr(namemap,expr):
	if expr.who() == 'Sequence':
		e = BGF3.Sequence()
		for el in expr.data:
			e.add(BGF3.Expression(renameNinExpr(namemap,el.wrapped)))
		return e
	elif expr.who() == 'Nonterminal':
		e = BGF3.Nonterminal()
		if expr.data in namemap:
			e.setName(namemap[expr.data])
		else:
			e.setName(expr.data)
		return e
	else:
		print('Unfinished implementation of renameNin for',expr.who())
		print('■')
		sys.exit(1)
Beispiel #4
0
					print('id')
				elif (e1,e2) in [('*','+'),('*','?'),('*','!'),('+','!'),('?','!')]:
					ren = XBGF3.Step('narrow')
					yes = True
				elif (e2,e1) in [('*','+'),('*','?'),('*','!'),('+','!'),('?','!')]:
					ren = XBGF3.Step('widen')
					yes = True
				else:
					print('ERROR: not in narrowing relation!')
					sys.exit(1)
				if yes:
					print(ren.name+'('+wrapexp(exp,e1)+','+wrapexp(exp,e2)+')')
					if e1=='!':
						ren.addParam(exp)
					elif e1=='+':
						p = BGF3.Plus()
						p.setExpr(exp)
						ren.addParam(BGF3.Expression(p))
					elif e1=='*':
						p = BGF3.Star()
						p.setExpr(exp)
						ren.addParam(BGF3.Expression(p))
					elif e1=='?':
						p = BGF3.Optional()
						p.setExpr(exp)
						ren.addParam(BGF3.Expression(p))
					else:
						print('ERROR: unknown in modifier!')
						sys.exit(1)
					if e2=='!':
						ren.addParam(exp)
Beispiel #5
0
def checkCandidates(indent,key,nt,candidates,masterprods):
	good = []
	for c in candidates:
		myprods = bgf.getProdsOfN(c)
		if myprods:
			print(indent,'√',c,'is defined as',ppseplist(';',map(lambda x:str(x.expr),myprods)))
		elif c in ['string','int']:
			# value => compose a fake rule that "defines" value as value
			# the condition above is hacky (what if there is a nonterminal called "string" or "int"?)
			print(indent,'√',c,'is a built-in')
			p = BGF3.Production()
			p.setNT(c)
			v = BGF3.Value()
			v.data = c
			p.setExpr(BGF3.Expression(v))
		else:
			print(indent,'√',c,'is undefined')
			if masterprods:
				print(indent,' ⇒ not a good candidate because its master counterpart is defined')
				continue
			else:
				print(indent,' ⇒ good candidate because both are undefined')
				good.append(c)
				continue
		#print('###my    prods:',ppseplist(';',map(lambda x:str(x.expr),myprods)))
		#print('###masterprods:',ppseplist(';',map(lambda x:str(x.expr),masterprods)))
		if masterprods:
			if len(myprods)==1 and len(masterprods)==1:
				if sameThing(key,myprods[0].expr,None,masterprods[0].expr):
					print(indent,' ⇒ good candidate because both definitions are identical')
					good.append(c)
				elif moreLiberal(myprods[0],masterprods[0]):
					print(indent,' ⇒ good candidate because it is defined more liberally')
					good.append(c)
				else:
					print(indent,' ⇒ not a good candidate because two definitions do not match')
			else:
				cx1 = cx2 = 0
				for p in masterprods:
					for q in myprods:
						if sameThing(key,q.expr,None,p.expr):
							cx1 += 1
						elif moreLiberal(q,p):
							cx2 += 1
				if cx1 and cx2:
					print(indent,' ⇒ good candidate because at least',cx1,'rules are identical to and at least',cx2,' rules are more liberal than the master\'s')
					good.append(c)
				elif cx1:
					print(indent,' ⇒ good candidate because at least',cx1,'rules are identical to the master\'s')
					good.append(c)
				elif cx2:
					print(indent,' ⇒ good candidate because at least',cx2,' rules are more liberal than the master\'s')
					good.append(c)
				else:
					print(indent,' ⇒ not a good candidate because multiple unrelated rules are found')
		elif not nt and len(myprods) == 1 and myprods[0].expr.wrapped.who() == 'Value':
			# TODO: check this code
			print(indent,' ⇒ good candidate because',c,'is defined as a built-in')
			good.append(c)
		else:
			print(indent,' ⇒ not a good candidate because',nt,'is undefined')
	return good
Beispiel #6
0
def match(ident,key,xnt,xs,ynt,ys):
	global cvdict
	# Input: sequences
	xsign = makeSignature(xnt,xs)
	ysign = makeSignature(ynt,ys)
	#print('    ~>',xsign)
	#print('    ~>',ysign)
	matches = {}
	alltriplets = []
	for k in appnd(fst(xsign),fst(ysign)):
		triplets = []
		if k in fst(xsign):
			xk = fetch(xsign,k)
		else:
			xk = [None]
		if k in fst(ysign):
			yk = fetch(ysign,k)
		else:
			yk = [None]
		for x in xk:
			for y in yk:
				triplets.append((k,x,y))
		alltriplets.append(triplets)
	alltriplets = cartesian(alltriplets)
	# some sort of verification/robustness check:
	# making sure each version touches all nonterminals of both sides
	xnts = snd(xsign)
	ynts = snd(ysign)
	for version in alltriplets:
		xntsl = xnts[:]
		yntsl = ynts[:]
		for triplet in version:
			if triplet[1] in xntsl:
				xntsl.remove(triplet[1])
			if triplet[2] in yntsl:
				yntsl.remove(triplet[2])
		for x in xntsl:
			version.append((getSign(xsign,x),x,None))
		for y in yntsl:
			version.append((getSign(ysign,y),None,y))
	#
	if len(alltriplets) == 1:
		# only one version to assume
		print(ident,'√ Only one version:')
		version = alltriplets[0]
		cvdict = {m[1]:m[2] for m in version}
		unmatched = list(map(lambda a:a[2],filter(lambda a:a[1]==None,version)))
		disregard = appnd(setmin(snd(xsign),snd(version)),list(map(lambda a:a[1],filter(lambda a:a[2]==None,version))))
		#print('      ~version~>',version)
		for un in unmatched:
			#print('     ! Unmatched',un)
			# TODO: now works with only one candidate (cannot make more version out of one)
			for dis in disregard:
				sign_un  = list(filter(lambda a:a[1]==un,ysign))[0]
				sign_dis = list(filter(lambda a:a[1]==dis,xsign))[0]
				#print('sign_un=',sign_un,'sign_dis=',sign_dis)
				if moreLiberalSign(sign_dis[0],sign_un[0]):
					print(ident,'☯ Disregarding more liberal signature,')
					ver2 = []
					for m in version:
						if m[2]==un:
							ver2.append((sign_un[0] + ' <: ' + sign_dis[0],dis,un))
						elif m[1]==dis:
							#version.remove(m)
							pass
						else:
							ver2.append(m)
					version = ver2
					disregard = appnd(setmin(snd(xsign),snd(version)),list(map(lambda a:a[1],filter(lambda a:a[2]==None,version))))
		for dis in disregard:
			print(ident,'☯ Disregarding',dis+',')
		#print('DICTS:',dicts[key])
		for match in version:
			if match[2]:
				print(ident,' ⇒ in',key+':',match[2],'maps to',match[1],'with signature',match[0])
				bind(key,match[2],match[1])
				#renameNin(match[1],match[2],key)
			else:
				bind(key,None,match[1])
		#print('DICTS:',dicts[key])
		cvdict = {}
	else:
		print(ident,'⇒ Multiple mapping versions:')
		cx = 0
		for version in alltriplets:
			cvdict = {m[1]:m[2] for m in version}
			cx +=1
			print(ident,'? Version',cx,':',joinsort(', ',[str(t[2])+' is '+str(t[1]) for t in version]))
			unmatched = list(map(lambda a:a[2],filter(lambda a:a[1]==None,version)))
			disregard = appnd(setmin(snd(xsign),snd(version)),list(map(lambda a:a[1],filter(lambda a:a[2]==None,version))))
			disq = False
			#print(ident,' ~version~>',version)
			for match in version:
				good = checkCandidates(ident+' ',key,match[2],[match[1]],master.getProdsOfN(match[2]))
				if len(good)!=1:
					print(ident,'  ✗ stop checking')
					disq = True
					break
			if disq:
				#print('unmatch=',unmatched,'disregarded=',disregard)
				# TODO: should be any combination
				cs1 = cs2 = ''
				for y in unmatched:
					cs1 += getSign(ysign,y)
				for x in disregard:
					cs2 += getSign(xsign,x)
				# extra normalisation
				cs1 = joinsort('',list(cs1))
				cs2 = joinsort('',list(cs2))
				if cs1 == cs2:
					ver2 = [(cs1,'+'.join(disregard),'+'.join(unmatched))]
					for m in version:
						if m[2] not in unmatched and m[1] not in disregard:
							ver2.append(m)
					alltriplets.append(ver2)
					print(ident,' ✗ version disqualified, an adapted variant is proposed')
				else:
					print(ident,' ✗ version disqualified')
			else:
				print(ident,' √ version approved')
				#print('VERSION:',version)
				disregardednow = setmin(disregard,'+'.join(list(map(lambda x:x[1],filter(lambda x:x[1] and x[1].find('+')>-1,version)))).split('+'))
				for dis in disregardednow:
					print(ident,'☯ Disregarding',dis+',')
				#print('DICTS:',dicts[key])
				nxs = projectSymbols(xs,disregardednow)
				step = CBGF3.Step('project-inject')
				p = BGF3.Production()
				p.nt = nt
				p.expr = nxs
				step.addParam(p)
				cbgfs[key].addStep(step)
				for match in version:
					if match[2]:
						if match[1].find('+')>-1:
							print(ident,'  ⇒',match[2],'maps to',match[1].replace('+',' and '),'with signature',match[0])
							bind(key,match[2],match[1])#.split('+')
							#renameNin(match[1],match[2],key)
						else:
							print(ident,'  ⇒',match[2],'maps to',match[1],'with signature',match[0])
							bind(key,match[2],match[1])
							#renameNin(match[1],match[2],key)
					else:
						bind(key,None,match[1])
				#print('DICTS:',dicts[key])
			cvdict = {}
Beispiel #7
0
# -*- coding: utf-8 -*-
from functools import reduce
import os,sys
import xml.etree.ElementTree as ET
sys.path.append(os.getcwd().split('projects')[0]+'projects/slps/shared/python')
import BGF3
import XBGF3
import CBGF3
import slpsns
import metrics3

# globals
bgfs = {}
cbgfs = {}
dicts = {}
master = BGF3.Grammar()
# current version dictionary
cvdict = {}

def bind(key,nt1,nt2):
	global dicts
	if nt1:
		if nt1 in dicts[key]:
			if nt2 in dicts[key][nt1].split('+'):
				print('~~~Confirmed binding',nt1,'to',nt2,'in',key)
			else:
				print('~~~Contradicting binding',nt1,'to',dicts[key][nt1],'or',nt2,'in',key)
				dicts[key][nt1] += '+'+nt2
				#print('■')
				#sys.exit(1)
		else:
Beispiel #8
0
 if len(sys.argv) != 5:
     print(
         'This mutation enforces the naming convention in a given BGF grammar.'
     )
     print('Usage:\n      ' + sys.argv[0] +
           ' <from> <to> <bgf-input> <xbgf-output>')
     print('      where <from> and <to> can be any of the following:')
     print('            U = upper case            - = dash-separated')
     print('            l = lower case            _ = underscore-separated')
     print('            m = mixed case            . = dot-separated')
     print('            C = camel case            s = space-separated')
     print('                                      ! = nonseparated')
     sys.exit(1)
 nc1 = sys.argv[1]
 nc2 = sys.argv[2]
 bgf = BGF3.Grammar()
 xbgf = XBGF3.Sequence()
 bgf.parse(sys.argv[3])
 for nt in metrics3.var(bgf):
     if not check(nc1[0], nt):
         print(nt, 'does not satisfy convention', sys.argv[1])
     else:
         print(nt, '-->', convert(nc1, nc2, nt))
         s = XBGF3.Step('rename')
         n = XBGF3.Wrapping('nonterminal')
         n.addChild(XBGF3.Leaf('from', nt))
         n.addChild(XBGF3.Leaf('to', convert(nc1, nc2, nt)))
         s.addParam(n)
         xbgf.addStep(s)
 ET.ElementTree(xbgf.getXml()).write(sys.argv[4])
 sys.exit(0)
Beispiel #9
0
    nts = []
    for p in g.prods:
        if p.expr.wrapped:
            for n in p.expr.wrapped.getXml().findall('.//nonterminal'):
                if (n.text not in nts) and (n.text != p.nt):
                    nts.append(n.text)
    return nts


if __name__ == "__main__":
    if len(sys.argv) != 2:
        print('This tool presents an overview of a BGF file.')
        print('Usage:')
        print('      checkbgf <bgf>')
        sys.exit(1)
    grammar = BGF3.Grammar()
    grammar.parse(sys.argv[1])
    print('<?xml version="1.0"?><xml>')
    wrap = lambda x, y: map(lambda z: '<' + x + '>' + z + '</' + x + '>', y)
    print((''.join(wrap('bottom', setminus(nrused(grammar), defd(grammar)))) +
           ''.join(
               wrap(
                   'top',
                   setminus(setminus(defd(grammar), nrused(grammar)),
                            grammar.roots)))).replace('&', '&amp;'))
    terms = term(grammar)
    htmlify = lambda s: map(
        lambda x: x.replace('&', '&amp;').replace('>', '&gt;').replace(
            '<', '&lt;'), s)
    print(''.join(wrap('keyword', htmlify(filter(isalpha, terms)))) +
          ''.join(wrap('terminal', htmlify(filter(isnotalpha, terms)))))
Beispiel #10
0
    if str(e1.wrapped.__class__) == "<class 'BGF3.Terminal'>":
        if str(e2.wrapped.__class__) != "<class 'BGF3.Terminal'>":
            #print("--isEqualE--> NO (type mismatch)")
            return False
        return e1.wrapped.data == e2.wrapped.data
    print(str(e1.wrapped.__class__))
    #print("--isEqualE--> NO")
    return False


def isEqualNT(n1, n2):
    # all NTs are equal
    #print('isEqualNT(%s,%s)' % (n1,n2))
    #print("--isEqualNT--> YES")
    return True


if __name__ == "__main__":
    if len(sys.argv) != 3:
        print('Usage:')
        print('	      name-independent-differ.py input1.bgf input2.bgf')
        sys.exit(-1)
    g1 = BGF3.Grammar()
    g1.parse(sys.argv[1])
    g2 = BGF3.Grammar()
    g2.parse(sys.argv[2])
    if isEqualG(g1, g2):
        sys.exit(0)
    else:
        sys.exit(-1)
Beispiel #11
0
import os, sys
import xml.etree.ElementTree as ET
sys.path.append(os.getcwd().split('slps')[0] + 'slps/shared/python')
import BGF3
from functools import reduce

if __name__ == "__main__":
    if len(sys.argv) < 4:
        print('Usage:')
        print('	merge.py input1.bgf [inputX.bgf ...] output.bgf')
        sys.exit(-1)
    bgfs = []
    names = []
    nts = []
    for fname in sys.argv[1:-1]:
        g = BGF3.Grammar()
        g.parse(fname)
        bgfs.append(g)
        names.append(fname)
    print(len(bgfs), 'grammars read.')
    for i in range(0, len(bgfs)):
        n = []
        for p in bgfs[i].prods:
            if p.nt not in n:
                n.append(p.nt)
        nts.append(n)
        print('\t', names[i], 'has', len(bgfs[i].prods), 'productions,',
              len(nts[i]), 'nonterminals and', len(bgfs[i].roots), 'roots')
    # FINAL STEP: compose BGF
    allbgf = BGF3.Grammar()
    # roots are combined