Permalink
Browse files

differential testing of XSLT and Python BGF pretty-printers

git-svn-id: https://slps.svn.sourceforge.net/svnroot/slps@895 ab42f6e0-554d-0410-b580-99e487e6eeb2
  • Loading branch information...
grammarware committed Dec 9, 2010
1 parent 8919992 commit c394592c5b3a98b1577eac2ac76f14b1ab7714e0
Showing with 151 additions and 13 deletions.
  1. +115 −13 shared/python/BGF.py
  2. +5 −0 topics/export/ebnf/Makefile
  3. +19 −0 topics/export/ebnf/export.py
  4. +12 −0 topics/export/ebnf/testperform
View
@@ -1,7 +1,6 @@
#!/usr/local/bin/python
import os
import sys
sys.path.append('../../../shared/python')
import slpsns
import elementtree.ElementTree as ET
@@ -10,6 +9,16 @@ class Grammar:
def __init__(self):
self.roots = []
self.prods = []
def parse(self,fname):
self.roots = []
self.prods = []
self.xml = ET.parse(sys.argv[1])
for e in self.xml.findall('root'):
self.roots.append(e.text)
for e in self.xml.findall(slpsns.bgf_('production')):
prod = Production()
prod.parse(e)
self.prods.append(prod)
def addRoot(self,r):
self.roots.append(r)
def addProd(self,p):
@@ -24,8 +33,8 @@ def getXml(self):
return self.ex
def __str__(self):
s = ''
for e in self.roots:
s = '[ROOT] '+e+'\n'
#for e in self.roots:
# s = '[ROOT] '+e+'\n'
for e in self.prods:
s += str(e)+'\n'
return s
@@ -36,6 +45,14 @@ def __init__(self):
self.label = ''
self.nt = ''
self.expr = None
def parse(self,prodelem):
if prodelem.findall('label'):
self.label = prodelem.findtext('label')
else:
self.label = ''
self.nt = prodelem.findtext('nonterminal')
self.expr = Expression(None)
self.expr.parse(prodelem.findall(slpsns.bgf_('expression'))[0])
def setLabel(self,l):
self.label = l
def setNT(self,nt):
@@ -54,13 +71,58 @@ def __str__(self):
s = ''
if self.label != '':
s = '['+self.label+'] '
s += str(self.nt)+':\n '
s += str(self.expr)
s += str(self.nt)+':\n '
if self.expr.__class__.__name__ == 'Expression':
e = self.expr.wrapped
else:
e = self.expr
if e.__class__.__name__ == 'Sequence':
s += e.unbracketed()
elif e.__class__.__name__ == 'Choice':
a = e.asArray()
for i in range(0,len(a)):
if a[i][0] == '(' and a[i][-1] == ')':
a[i] = a[i][1:-1]
s += '\n '.join(a)
else:
s += str(self.expr)
return s
class Expression:
def __init__(self,insides):
self.wrapped = insides
def parse(self,exprelem):
expr = exprelem.findall('*')[0]
if expr.tag == 'terminal':
self.wrapped = Terminal()
elif expr.tag == 'nonterminal':
self.wrapped = Nonterminal()
elif expr.tag == 'selectable':
self.wrapped = Selectable()
elif expr.tag == 'epsilon':
self.wrapped = Epsilon()
elif expr.tag == 'any':
self.wrapped = Any()
elif expr.tag == 'empty':
self.wrapped = Empty()
elif expr.tag == 'value':
self.wrapped = Value()
elif expr.tag == 'sequence':
self.wrapped = Sequence()
elif expr.tag == 'choice':
self.wrapped = Choice()
elif expr.tag == 'marked':
self.wrapped = Marked()
elif expr.tag == 'optional':
self.wrapped = Optional()
elif expr.tag == 'plus':
self.wrapped = Plus()
elif expr.tag == 'star':
self.wrapped = Star()
else:
print "Don't know how to parse",expr.tag
return
self.wrapped.parse(expr)
def getXml(self):
#print 'Getting the XML of expression...'
return self.wrapped.getXml()
@@ -71,6 +133,8 @@ def __str__(self):
class Terminal:
def __init__(self):
self.data = None
def parse(self,termelem):
self.data = termelem.text
def setName(self,name):
self.data = name
def getXml(self):
@@ -85,6 +149,8 @@ def __str__(self):
class Nonterminal:
def __init__(self):
self.data = None
def parse(self,nontermelem):
self.data = nontermelem.text
def setName(self,name):
self.data = name
def getXml(self):
@@ -100,6 +166,10 @@ class Selectable:
def __init__(self):
self.sel = None
self.expr = None
def parse(self,selelem):
self.sel = selelem.findtext('selector')
self.expr = Expression(None)
self.expr.parse(selelem.findall(slpsns.bgf_('expression'))[0])
def setName(self,name):
self.sel = name
def setExpr(self,expr):
@@ -118,6 +188,8 @@ def __str__(self):
class Epsilon:
def __init__(self):
pass
def parse(self,e):
pass
def getXml(self):
#print 'Getting the XML of epsilon...'
self.ex = ET.Element(slpsns.bgf_('expression'))
@@ -130,6 +202,8 @@ def __str__(self):
class Any:
def __init__(self):
pass
def parse(self,e):
pass
def getXml(self):
#print 'Getting the XML of any...'
self.ex = ET.Element(slpsns.bgf_('expression'))
@@ -142,6 +216,8 @@ def __str__(self):
class Empty:
def __init__(self):
pass
def parse(self,e):
pass
def getXml(self):
#print 'Getting the XML of empty...'
self.ex = ET.Element(slpsns.bgf_('expression'))
@@ -154,6 +230,8 @@ def __str__(self):
class Value:
def __init__(self):
self.data = None
def parse(self,valelem):
self.data = valelem.text
def setInt(self):
self.data = 'int'
def setStr(self):
@@ -164,12 +242,17 @@ def getXml(self):
ET.SubElement(self.ex,'value').text = self.data
return self.ex
def __str__(self):
return self.data.upper()
return self.data.upper()[:3]
# sequence::(expression+)
class Sequence:
def __init__(self):
self.data = []
def parse(self,seqelem):
self.data = []
for e in seqelem.findall('*'):
self.data.append(Expression(None))
self.data[-1].parse(e)
def add(self,expr):
self.data.append(expr)
def getXml(self):
@@ -185,16 +268,22 @@ def getXml(self):
self.xml.append(el.getXml())
return self.ex
def __str__(self):
s = '('
return '(' + self.unbracketed() + ')'
def unbracketed(self):
s = ''
for el in self.data:
s += str(el)+' '
s += ')'
return s
return s.strip()
# choice::(expression+)
class Choice:
def __init__(self):
self.data = []
def parse(self,chelem):
self.data = []
for e in chelem.findall('*'):
self.data.append(Expression(None))
self.data[-1].parse(e)
def add(self,expr):
self.data.append(expr)
def getXml(self):
@@ -210,16 +299,20 @@ def getXml(self):
self.xml.append(el.getXml())
return self.ex
def __str__(self):
s = '('
return '('+' | '.join(self.asArray())+')'
def asArray(self):
a = []
for el in self.data:
s += str(el)+' | '
s += ')'
return s
a.append(str(el))
return a
# marked::expression
class Marked:
def __init__(self):
self.data = None
def parse(self,melem):
self.data = Expression(None)
self.data.parse(melem.findall('*')[0])
def setExpr(self,expr):
self.data = expr
def getXml(self):
@@ -234,6 +327,9 @@ def __str__(self):
class Optional:
def __init__(self):
self.data = None
def parse(self,optelem):
self.data = Expression(None)
self.data.parse(optelem.findall('*')[0])
def setExpr(self,expr):
self.data = expr
def getXml(self):
@@ -248,6 +344,9 @@ def __str__(self):
class Star:
def __init__(self):
self.data = None
def parse(self,starelem):
self.data = Expression(None)
self.data.parse(starelem.findall('*')[0])
def setExpr(self,expr):
self.data = expr
def getXml(self):
@@ -262,6 +361,9 @@ def __str__(self):
class Plus:
def __init__(self):
self.data = None
def parse(self,pluselem):
self.data = Expression(None)
self.data.parse(pluselem.findall('*')[0])
def setExpr(self,expr):
self.data = expr
def getXml(self):
@@ -0,0 +1,5 @@
test:
ls -1 ../../storage/bgf/tests.small/*.bgf | xargs -n1 ./testperform
clean:
rm -f *.bnf
@@ -0,0 +1,19 @@
#!/usr/local/bin/python
import os
import sys
sys.path.append('../../../shared/python')
import slpsns
import BGF
import elementtree.ElementTree as ET
if __name__ == "__main__":
if len(sys.argv) != 3:
print 'This tool extracts a Rascal grammar.'
print 'Usage:'
print ' bgf2bnf <bgf-input> <bnf-output>'
sys.exit(1)
bgf = BGF.Grammar()
bgf.parse(sys.argv[1])
bnf = open(sys.argv[2],'w')
bnf.write(str(bgf))
bnf.close()
@@ -0,0 +1,12 @@
#!/bin/sh
echo '[Test Case]' `basename $1`
./export.py $1 py.bnf
../../../shared/tools/bgf2bnf $1 xsl.bnf
diff py.bnf xsl.bnf
if [ $? -ne 0 ]; then
echo 'ERROR. Python vs XSLT output follows:'
cat py.bnf
cat xsl.bnf
exit -1
fi

0 comments on commit c394592

Please sign in to comment.