# Test suite for the dRel parser # import unittest import drel_lex import drel_yacc import CifFile import StarFile # Test simple statements class SimpleStatementTestCase(unittest.TestCase): def setUp(self): #create our lexer and parser self.lexer = drel_lex.lexer self.parser = drel_yacc.parser # as we disallow simple expressions on a separate line to avoid a # reduce/reduce conflict for identifiers, we need at least an # assignment statement def testrealnum(self): """test parsing of real numbers""" res = self.parser.parse('a=5.45\n',debug=True,lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self)==5.45) res = self.parser.parse('a=.45e-24\n',debug=True,lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) ==.45e-24) def testinteger(self): """test parsing an integer""" resm = [0,0,0,0] checkm = [1230,77,5,473] resm[0] = self.parser.parse('a = 1230\n',lexer=self.lexer) resm[1] = self.parser.parse('a = 0x4D\n',lexer=self.lexer) resm[2] = self.parser.parse('a = 0B0101\n',lexer=self.lexer) resm[3] = self.parser.parse('a = 0o731\n',lexer=self.lexer) for res,check in zip(resm,checkm): realfunc = drel_yacc.make_func(res,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) == check) def testcomplex(self): """test parsing a complex number""" resc = self.parser.parse('a = 13.45j\n',lexer=self.lexer) realfunc = drel_yacc.make_func(resc,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) == 13.45j) def testshortstring(self): """test parsing a one-line string""" jk = "a = \"my pink pony's mane\"" jl = "a = 'my pink pony\"s mane'" ress = self.parser.parse(jk+"\n",lexer=self.lexer) resr = self.parser.parse(jl+"\n",lexer=self.lexer) realfunc = drel_yacc.make_func(ress,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) == jk[5:-1]) realfunc = drel_yacc.make_func(resr,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) == jl[5:-1]) # # This fails due to extra indentation introduced when constructing the # enclosing function # def testlongstring(self): """test parsing multi-line strings""" jk = '''a = """ a long string la la la '"' some more end"""''' jl = """a = ''' a long string la la la '"' some more end'''""" ress = self.parser.parse(jk+"\n",lexer=self.lexer) resr = self.parser.parse(jl+"\n",lexer=self.lexer) realfunc = drel_yacc.make_func(ress,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) == jk[7:-3]) realfunc = drel_yacc.make_func(resr,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) == jl[7:-3]) def testmathexpr(self): """test simple maths expressions """ testexpr = (("a = 5.45 + 23.6e05",5.45+23.6e05), ("a = 11 - 45",11-45), ("a = 45.6 / 22.2",45.6/22.2)) for test,check in testexpr: res = self.parser.parse(test+"\n",lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) == check) def testexprlist(self): """test comma-separated expressions""" test = "a = 5,6,7+8.5e2" res = self.parser.parse(test+"\n",lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) ==(5,6,7+8.5e2)) def testparen(self): """test parentheses""" test = "a = ('once', 'upon', 6,7j +.5e2)" res = self.parser.parse(test+"\n",lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) ==('once' , 'upon' , 6 , 7j + .5e2 )) def testlists(self): """test list parsing""" test = "a = ['once', 'upon', 6,7j +.5e2]" res = self.parser.parse(test+"\n",lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","a",have_sn=False) exec realfunc self.failUnless(myfunc(self,self) ==['once' , 'upon' , 6 , 7j + .5e2 ]) class MoreComplexTestCase(unittest.TestCase): def setUp(self): #create our lexer and parser self.lexer = drel_lex.lexer self.parser = drel_yacc.parser self.parser.withtable = {} self.parser.special_id = [] self.parser.target_id = None self.parser.indent = "" def testassignment(self): """Test that an assignment works""" teststrg = "n = 11" res = self.parser.parse(teststrg,lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","n",have_sn=False) exec realfunc self.failUnless(myfunc(self,self)==11) def test_do_stmt(self): """Test how a do statement comes out""" teststrg = """ total = 0 do jkl = 0,20,2 { total = total + jkl } do emm = 1,5 { total = total + emm } """ res = self.parser.parse(teststrg + "\n",lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","total",have_sn=False) exec realfunc realres = myfunc(self,self) # Do statements are inclusive print "Do statement returns %d" % realres self.failUnless(realres==125) print res def test_do_stmt_2(self): """Test how another do statement comes out""" teststrg = """ pp = 0 geom_hbond = [(1,2),(2,3),(3,4)] do i= 0,1 { l,s = geom_hbond [i] pp += s } """ self.parser.special_id = [{'axy':1}] res = self.parser.parse(teststrg + "\n",debug=True,lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","pp",have_sn=False) exec realfunc realres = myfunc(self,self) # Do statements are inclusive print "Do statement returns %d" % realres self.failUnless(realres==5) print res def test_nested_stmt(self): """Test how a nested do statement prints""" teststrg = """ total = 0 othertotal = 0 do jkl = 0,20,2 { total = total + jkl do emm = 1,5 { othertotal = othertotal + 1 } } end_of_loop = -25.6 """ res = self.parser.parse(teststrg + "\n",lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","othertotal,total",have_sn=False) print "Nested do:\n" + realfunc exec realfunc othertotal,total = myfunc(self,self) print "nested do returns %d, %d" % (othertotal,total) self.failUnless(othertotal==55) self.failUnless(total==110) def test_if_stmt(self): """test parsing of if statement""" teststrg = """ dmin = 5.0 d1 = 4.0 rad1 = 2.2 radius_bond = 2.0 If (d1(rad1+radius_bond)) b = 5 """ res = self.parser.parse(teststrg + "\n",lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","b",have_sn=False) exec realfunc b = myfunc(self,self) print "if returns %d" % b self.failUnless(b==5) # We don't test the return value until we have a way to actually access it! def test_fancy_assign(self): """Test fancy assignment""" teststrg = """ a = [2,3,4] b = 3 c= 4 do jkl = 1,5,1 { geom_angle( .id = Tuple(a,b,c), .distances = Tuple(b,c), .value = jkl) } """ self.parser.target_id = "geom_angle" res = self.parser.parse(teststrg + "\n",debug=True,lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc",None,cat_meth = True,have_sn=False) print "Fancy assign: %s" % res[0] exec realfunc b = myfunc(self,self) print "Geom_angle.angle = %s" % b['geom_angle.value'] self.failUnless(b['geom_angle.value']==[1,2,3,4]) def test_tables(self): """Test that tables are parsed correctly""" teststrg = """ jk = Table() jk['bx'] = 25 """ print "Table test:" res = self.parser.parse(teststrg+"\n",debug=True,lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","jk",have_sn=False) print "Table: %s" % `res[0]` exec realfunc b = myfunc(self,self) self.failUnless(b['bx']==25) class WithDictTestCase(unittest.TestCase): """Now test flow control which requires a dictionary present""" def setUp(self): #create our lexer and parser self.lexer = drel_lex.lexer self.parser = drel_yacc.parser #use a simple dictionary self.testdic = CifFile.CifDic("testdic") self.testblock = CifFile.CifFile("testdic")["DDL_DIC"] #create the global namespace self.namespace = self.testblock.keys() self.namespace = dict(map(None,self.namespace,self.namespace)) self.parser.special_id = [self.namespace] self.parser.withtable = {} self.parser.target_id = None self.parser.indent = "" def test_with_stmt(self): """Test what comes out of a simple flow statement, including multiple with statements""" teststrg = """ with p as description with q as dictionary { x = 22 j = 25 jj = q.date px = p.text _dictionary.date = "2007-04-01" }""" self.parser.loopable_cats = [] #category dictionary is not looped self.parser.target_id = '_dictionary.date' res = self.parser.parse(teststrg+"\n",lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc",None) print "With statement -> \n" + realfunc exec realfunc newdate = myfunc(self.testdic,self.testblock) print 'date now %s' % newdate self.failUnless(newdate == "2007-04-01") def test_loop_statement(self): """Test proper processing of loop statements""" teststrg = """ n = 0 loop p as dictionary_audit n += 1 _symmetry.ops = n """ self.parser.loopable_cats = ['dictionary_audit'] #category dictionary is not looped self.parser.target_id = '_symmetry.ops' res = self.parser.parse(teststrg+"\n",lexer=self.lexer,debug=1) realfunc = drel_yacc.make_func(res,"myfunc",None) print "Loop statement -> \n" + realfunc exec realfunc symops = myfunc(self.testdic,self.testblock) print 'symops now %d' % symops self.failUnless(symops == 81) def test_functions(self): """Test that functions are converted correctly""" struct_testdic = CifFile.CifFile("cif_core.dic", grammar="DDLm") struct_testblock = struct_testdic["CIF_CORE"] self.parser.loopable_cats = ["import"] #category import is looped self.parser.target_id = "_import_list.id" self.parser.withtable = {} teststrg = """ with i as import _import_list.id = List([i.scope, i.block, i.file, i.if_dupl, i.if_miss]) """ res = self.parser.parse(teststrg+"\n",lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc",None) print "With statement -> \n" + realfunc exec realfunc retval = myfunc(self.testdic,struct_testblock,3) self.failUnless(retval == StarFile.StarList(["dic","CORE_MODEL","core_model.dic","exit","exit"])) def test_attributes(self): """Test that attributes of complex expressions come out OK""" # We need to do a scary funky attribute of a key lookup ourdic = CifFile.CifDic("testdic2") testblock = CifFile.CifFile("test_data.cif")["testdata"] self.parser.loopable_cats = ['geom','position'] # teststrg = """ LineList = [] PointList = [] With p as position Loop g as geom { If (g.type == "point") { PointList += Tuple(g.vertex1_id,p[g.vertex1_id].vector_xyz) } #Else if (g.type == "line") { # LineList ++= Tuple(Tuple(g.vertex1_id, g.vertex2_id), # Tuple(p[g.vertex1_id].vector_xyz, # p[g.vertex2_id].vector_xyz)) #} } """ self.parser.target_id = 'PointList' res = self.parser.parse(teststrg+"\n",lexer=self.lexer) realfunc = drel_yacc.make_func(res,"myfunc","PointList") print "Function -> \n" + realfunc exec realfunc retval = myfunc(ourdic,testblock,"LineList") print "testdic2 return value" + `retval` print "Value for comparison with docs: %s" % `retval[0]` def test_funcdef(self): """Test function conversion""" teststrg = """ function Closest( v :[Array, Real], # coord vector to be cell translated w :[Array, Real]) { # target vector d = v - w t = Int( Mod( 99.5 + d, 1.0 ) - d ) Closest = Tuple ( v+t, t ) } """ self.parser.target_id = 'Closest' res,ww = self.parser.parse(teststrg+"\n",lexer=self.lexer) print "Function -> \n" + res exec res retval = Closest(0.2,0.8) print 'Closest 0.2,0.8 returns ' + ",".join([`retval[0]`,`retval[1]`]) self.failUnless(retval == StarFile.StarTuple(1.2,1)) if __name__=='__main__': unittest.main()