Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
BGF python interface extended with labels (as tangible entities, for …
…scoping); CBGF3 python interface added (pending change); SLPS namespace python hack includes MBGF now; some more minor pending uncommitted tools
- Loading branch information
1 parent
d2ce648
commit 96cf3ab
Showing
6 changed files
with
902 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,132 @@ | ||
#!/Library/Frameworks/Python.framework/Versions/3.1/bin/python3 | ||
import os | ||
import sys | ||
sys.path.append(os.getcwd().split('slps')[0]+'slps/shared/python') | ||
import slpsns | ||
import BGF3 | ||
import xml.etree.ElementTree as ET | ||
|
||
class Sequence: | ||
def __init__(self): | ||
self.steps = [] | ||
def parse(self,fname): | ||
self.steps = [] | ||
self.xml = ET.parse(fname) | ||
for e in self.xml.findall(slpsns.cbgf_('*')): | ||
s = Step() | ||
s.parse(e) | ||
self.steps.append(s) | ||
def addStep(self,s): | ||
self.steps.append(s) | ||
def addFirstStep(self,s): | ||
ns = [s] | ||
ns.extend(self.steps) | ||
self.steps = ns | ||
def getXml(self): | ||
self.ex = ET.Element(slpsns.cbgf_('relationship')) | ||
for e in self.steps: | ||
self.ex.append(e.getXml()) | ||
return self.ex | ||
|
||
class Step: | ||
def __init__(self,op): | ||
self.name = op | ||
self.params = [] | ||
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) | ||
def setName(self,n): | ||
self.name = n | ||
def addParam(self,p): | ||
self.params.append(p) | ||
def getXml(self): | ||
#print 'Getting the XML of production...' | ||
self.ex = ET.Element(slpsns.cbgf_(self.name)) | ||
for p in self.params: | ||
self.ex.append(p.getXml()) | ||
return self.ex | ||
|
||
class Label: | ||
def __init__(self,n): | ||
self.name = n | ||
def getXml(self): | ||
e = ET.Element('label') | ||
e.text = self.name | ||
return e | ||
def __str__(self): | ||
return self.name | ||
|
||
class Root: | ||
def __init__(self,n): | ||
self.name = n | ||
def getXml(self): | ||
e = ET.Element('root') | ||
e.text = self.name | ||
return e | ||
def __str__(self): | ||
return self.name | ||
|
||
# the main difference from BGF3.Nonterminal is the absence of wrapping expression | ||
class Nonterminal: | ||
def __init__(self,name): | ||
self.data = name | ||
def parse(self,nontermelem): | ||
self.data = nontermelem.text | ||
def setName(self,name): | ||
self.data = name | ||
def getXml(self): | ||
#print 'Getting the XML of nonterminal',self.data,'...' | ||
self.ex = ET.Element('nonterminal') | ||
self.ex.text = self.data | ||
return self.ex | ||
def __str__(self): | ||
return self.data | ||
|
||
# the nonterminal for rename-renameN | ||
class NonterminalFT: | ||
def __init__(self,n1,n2): | ||
self.ntfr = n1 | ||
self.ntto = n2 | ||
def parse(self,nontermelem): | ||
self.ntfr = nontermelem.findtext('from') | ||
self.ntto = nontermelem.findtext('to') | ||
def setFrom(self,name): | ||
self.ntfr = name | ||
def setTo(self,name): | ||
self.ntto = name | ||
def getXml(self): | ||
#print 'Getting the XML of nonterminal',self.data,'...' | ||
self.ex = ET.Element('nonterminal') | ||
ET.SubElement(self.ex,'from').text = self.ntfr | ||
ET.SubElement(self.ex,'to' ).text = self.ntto | ||
return self.ex | ||
def __str__(self): | ||
return self.ntfr+'→'+self.ntto | ||
|
||
# the roots for reroot-reroot | ||
class Roots: | ||
def __init__(self,name,ns): | ||
self.name = name | ||
self.ns = ns[:] | ||
def parse(self,el): | ||
self.name = el.tag | ||
self.ns = [] | ||
for nt in el.findall('root'): | ||
self.ns.append(nt.text) | ||
def getXml(self): | ||
#print 'Getting the XML of nonterminal',self.data,'...' | ||
self.ex = ET.Element(self.name) | ||
for nt in self.ns: | ||
ET.SubElement(self.ex,'root').text = nt | ||
return self.ex | ||
def __str__(self): | ||
return ', '.join(self.ns) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,209 @@ | ||
#!/usr/bin/python | ||
|
||
import sys | ||
|
||
maxdepth = 2 | ||
|
||
def generate_epsilon(): | ||
return ['<bgf:expression><epsilon/></bgf:expression>'] | ||
|
||
def generate_nonterminal(): | ||
return ['<bgf:expression><nonterminal>foo</nonterminal></bgf:expression>','<bgf:expression><nonterminal>bar</nonterminal></bgf:expression>'] | ||
|
||
def generate_terminal(): | ||
return ['<bgf:expression><terminal>begin</terminal></bgf:expression>','<bgf:expression><terminal>end</terminal></bgf:expression>'] | ||
|
||
def generate_unary(name,depth): | ||
global maxdepth | ||
r = [] | ||
for x in generate_nonterminal(): | ||
r.append(x) | ||
for x in generate_terminal(): | ||
r.append(x) | ||
if depth < maxdepth: | ||
for x in generate_expression(depth+1): | ||
r.append(x) | ||
return map(lambda x:'<bgf:expression><'+name+'>'+x+'</'+name+'></bgf:expression>',r) | ||
|
||
def generate_binary(name,depth): | ||
global maxdepth | ||
p = [] | ||
for x in generate_nonterminal(): | ||
p.append(x) | ||
for x in generate_terminal(): | ||
p.append(x) | ||
if depth < maxdepth: | ||
for x in generate_expression(depth+1): | ||
p.append(x) | ||
r = [] | ||
for x in p: | ||
for y in p: | ||
r.append('<bgf:expression><'+name+'>'+x+y+'</'+name+'></bgf:expression>') | ||
return r | ||
|
||
def generate_sequence(depth): | ||
return generate_binary('sequence',depth) | ||
|
||
def generate_choice(depth): | ||
return generate_binary('choice',depth) | ||
|
||
def generate_optional(depth): | ||
return generate_unary('optional',depth) | ||
|
||
def generate_plus(depth): | ||
return generate_unary('plus',depth) | ||
|
||
def generate_star(depth): | ||
return generate_unary('star',depth) | ||
|
||
def generate_expression(depth): | ||
global maxdepth | ||
r = [] | ||
#for x in generate_epsilon(): | ||
# r.append(x) | ||
for x in generate_nonterminal(): | ||
r.append(x) | ||
for x in generate_terminal(): | ||
r.append(x) | ||
if depth < maxdepth: | ||
for x in generate_expression(depth+1): | ||
r.append(x) | ||
return map(lambda x:'<bgf:expression><'+name+'>'+x+'</'+name+'></bgf:expression>',r) | ||
|
||
#basic_elements = ['e','o','i','s','a','t','n'] | ||
#unary_modifiers = ['z','m','q','p','k'] | ||
binary_modifiers = ['f','c'] | ||
names_subsets = ([],['foo'],['foo','bar']) | ||
counter = 0 | ||
label = True | ||
|
||
def main(dir,basic_elements='eoisatn',unary_modifiers='zmqpk',options=''): | ||
global counter, label | ||
if options == '--nolabel': | ||
print 'No labels will be generated.' | ||
label = False | ||
# solitary basic elements | ||
for x in basic_elements: | ||
dump_file(generate_expression(x),dir+'/'+x+'.bgf') | ||
print counter,'test cases with basic elements generated successfully' | ||
counter = 0 | ||
# once wrapped basic elements | ||
for x in unary_modifiers: | ||
for y in basic_elements: | ||
dump_file(wrap_expression(x,generate_expression(y)),dir+'/'+x+y+'.bgf') | ||
print counter,'test cases with wrapped basic elements generated successfully' | ||
counter = 0 | ||
# twice wrapped basic elements | ||
for x in unary_modifiers: | ||
for y in unary_modifiers: | ||
for z in basic_elements: | ||
dump_file(wrap_expression(x,wrap_expression(y,generate_expression(z))),dir+'/'+x+y+z+'.bgf') | ||
print counter,'test cases with twice wrapped basic elements generated successfully' | ||
counter = 0 | ||
# sequences and choices | ||
for x in binary_modifiers: | ||
for y in basic_elements: | ||
for z in basic_elements: | ||
dump_file(wrap_expression(x,generate_expression(y)+generate_expression(z)),dir+'/'+x+y+z+'.bgf') | ||
print counter,'test cases with sequences and choices of length 2 generated successfully' | ||
counter = 0 | ||
# longer sequences and choices | ||
for x in binary_modifiers: | ||
for a in basic_elements: | ||
for b in basic_elements: | ||
for c in basic_elements: | ||
dump_file(wrap_expression(x,generate_expression(a)+generate_expression(b)+generate_expression(c)),dir+'/'+x+a+b+c+'.bgf') | ||
print counter,'test cases with sequences and choices of length 3 generated successfully' | ||
counter = 0 | ||
# nested sequences and choices | ||
for x in binary_modifiers: | ||
for y in binary_modifiers: | ||
for a in basic_elements: | ||
for b in basic_elements: | ||
for c in basic_elements: | ||
dump_file(wrap_expression(x,wrap_expression(y,generate_expression(a)+generate_expression(b))+generate_expression(c)),dir+'/'+x+y+a+b+c+'.bgf') | ||
dump_file(wrap_expression(x,generate_expression(a)+wrap_expression(y,generate_expression(b)+generate_expression(c))),dir+'/'+x+a+y+b+c+'.bgf') | ||
print counter,'test cases with sequences and choices of nested depth 2 generated successfully' | ||
counter = 0 | ||
# specific cases | ||
for x in names_subsets: | ||
for y in names_subsets: | ||
dump_specific_file(x,y,dir+'/r'+str(len(x))+'l'+str(len(y))+'.bgf') | ||
if label: | ||
print counter,'test cases with multiple labelled productions generated successfully' | ||
else: | ||
print counter,'test cases with multiple productions generated successfully' | ||
return | ||
|
||
def dump_file(expr,fname): | ||
global counter, label | ||
f = open(fname,'w') | ||
f.write('<?xml version="1.0"?><bgf:grammar xmlns:bgf="http://planet-sl.org/bgf"><bgf:production>') | ||
if label: | ||
f.write('<label>foo</label>') | ||
f.write('<nonterminal>bar</nonterminal>') | ||
f.write(expr) | ||
f.write('</bgf:production></bgf:grammar>') | ||
f.close() | ||
counter += 1 | ||
|
||
def dump_specific_file(roots,labels,fname): | ||
global counter, label | ||
f = open(fname,'w') | ||
f.write('<?xml version="1.0"?><bgf:grammar xmlns:bgf="http://planet-sl.org/bgf">') | ||
for r in roots: | ||
f.write('<root>'+r+'</root>') | ||
for l in labels: | ||
f.write('<bgf:production>') | ||
if label: | ||
f.write('<label>l'+l+'</label> ') | ||
f.write('<nonterminal>'+l+'</nonterminal>'+generate_expression('e')+'</bgf:production>') | ||
f.write('</bgf:grammar>') | ||
f.close() | ||
counter += 1 | ||
|
||
def generate_expression(code): | ||
# basic_elements = ['e','o','i','s','a','t','n'] | ||
if code == 'e': | ||
expr = '<epsilon/>' | ||
elif code == 'o': | ||
expr = '<empty/>' | ||
elif code == 'i': | ||
expr = '<value>int</value>' | ||
elif code == 's': | ||
expr = '<value>string</value>' | ||
elif code == 'a': | ||
expr = '<any/>' | ||
elif code == 't': | ||
expr = '<terminal>x</terminal>' | ||
elif code == 'n': | ||
expr = '<nonterminal>x</nonterminal>' | ||
return '<bgf:expression>'+expr+'</bgf:expression>' | ||
|
||
def wrap_expression(code,expr): | ||
# unary_modifiers = ['z','m','q','p','k'] | ||
if code == 'z': | ||
expr = '<selectable><selector>x</selector>'+expr+'</selectable>' | ||
elif code == 'm': | ||
expr = '<marked>'+expr+'</marked>' | ||
elif code == 'q': | ||
expr = '<optional>'+expr+'</optional>' | ||
elif code == 'p': | ||
expr = '<plus>'+expr+'</plus>' | ||
elif code == 'k': | ||
expr = '<star>'+expr+'</star>' | ||
elif code == 'f': | ||
expr = '<sequence>'+expr+'</sequence>' | ||
elif code == 'c': | ||
expr = '<choice>'+expr+'</choice>' | ||
return '<bgf:expression>'+expr+'</bgf:expression>' | ||
|
||
if __name__ == "__main__": | ||
if len(sys.argv) >= 2: | ||
apply(main,sys.argv[1:]) | ||
else: | ||
print '''BGF Test Set Generator | ||
Usage:''' | ||
print ' ',sys.argv[0],'<output directory>','[<basic elements>]','[<unary modifiers>]','[--nolabel]' | ||
sys.exit(1) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,31 @@ | ||
#!/usr/local/bin/python | ||
# -*- coding: utf-8 -*- | ||
import os, sys, math | ||
import slpsns | ||
import elementtree.ElementTree as ET | ||
import metrics | ||
|
||
def bgf2dot(g): | ||
cg = metrics.getCallGraph(g) | ||
s = 'digraph generated{\n' | ||
for a in cg.keys(): | ||
for b in cg[a]: | ||
s += a+' -> '+b+';\n' | ||
#s += '}\n' | ||
print metrics.calculateLevels(cg) | ||
cg = metrics.makeOneStep(cg) | ||
#s = 'digraph generated{\n' | ||
for a in cg.keys(): | ||
s += a.replace('-','_')+'_[label="'+a+'"];\n' | ||
for b in cg[a]: | ||
s += a.replace('-','_')+'_ -> '+b+'_;\n' | ||
print metrics.calculateLevels(cg) | ||
cg = metrics.makeOneStep(cg) | ||
for a in cg.keys(): | ||
s += a.replace('-','_')+'__[label="'+a+'"];\n' | ||
for b in cg[a]: | ||
s += a.replace('-','_')+'__ -> '+b+'__;\n' | ||
print metrics.calculateLevels(cg) | ||
s += '}' | ||
print metrics.calculateLevels(metrics.getClosure(cg)) | ||
return s |
Oops, something went wrong.