Package PyFoam :: Package RunDictionary :: Module ParsedParameterFile
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.RunDictionary.ParsedParameterFile

  1  #  ICE Revision: $Id: ParsedParameterFile.py 9337 2008-09-08 13:33:29Z bgschaid $  
  2  """Parameter file is read into memory and modified there""" 
  3   
  4  from FileBasis import FileBasisBackup 
  5  from PyFoam.Basics.PlyParser import PlyParser 
  6  from PyFoam.Basics.FoamFileGenerator import FoamFileGenerator 
  7   
  8  from PyFoam.Basics.DataStructures import Vector,Field,Dimension,DictProxy,TupleProxy,Tensor,SymmTensor,Unparsed,UnparsedList 
  9   
 10  from PyFoam.Error import error 
 11   
 12  from os import path 
 13   
14 -class ParsedParameterFile(FileBasisBackup):
15 """ Parameterfile whose complete representation is read into 16 memory, can be manipulated and afterwards written to disk""" 17
18 - def __init__(self, 19 name, 20 backup=False, 21 debug=False, 22 boundaryDict=False, 23 listDict=False, 24 listLengthUnparsed=None, 25 noHeader=False, 26 noBody=False, 27 dontRead=False):
28 """@param name: The name of the parameter file 29 @param backup: create a backup-copy of the file 30 @param boundaryDict: the file to parse is a boundary file 31 @param listDict: the file only contains a list 32 @param listLengthUnparsed: Lists longer than that length are not parsed 33 @param noHeader: don't expect a header 34 @param noBody: don't read the body of the file (only the header) 35 @param dontRead: Do not read the file during construction 36 """ 37 38 self.noHeader=noHeader 39 self.noBody=noBody 40 FileBasisBackup.__init__(self,name,backup=backup) 41 self.debug=debug 42 self.boundaryDict=boundaryDict 43 self.listDict=listDict 44 self.listLengthUnparsed=listLengthUnparsed 45 46 self.header=None 47 self.content=None 48 49 if not dontRead: 50 self.readFile()
51
52 - def parse(self,content):
53 """Constructs a representation of the file""" 54 parser=FoamFileParser(content,debug=self.debug, 55 boundaryDict=self.boundaryDict, 56 listDict=self.listDict, 57 listLengthUnparsed=self.listLengthUnparsed, 58 noHeader=self.noHeader, 59 noBody=self.noBody) 60 61 self.content=parser.getData() 62 self.header=parser.getHeader() 63 return self.content
64
65 - def __contains__(self,key):
66 return key in self.content
67
68 - def __getitem__(self,key):
69 return self.content[key]
70
71 - def __setitem__(self,key,value):
72 self.content[key]=value
73
74 - def __delitem__(self,key):
75 del self.content[key]
76
77 - def __len__(self):
78 return len(self.content)
79
80 - def __str__(self):
81 """Generates a string from the contents in memory 82 Used to be called makeString""" 83 84 string="// -*- C++ -*-\n// File generated by PyFoam - sorry for the ugliness\n\n" 85 86 generator=FoamFileGenerator(self.content,header=self.header) 87 string+=str(generator) 88 89 return string
90
91 -class WriteParameterFile(ParsedParameterFile):
92 """A specialization that is used to only write to the file"""
93 - def __init__(self, 94 name, 95 backup=False, 96 className="dictionary", 97 objectName=None):
98 ParsedParameterFile.__init__(self, 99 name, 100 backup=backup, 101 dontRead=True) 102 103 if objectName==None: 104 objectName=path.basename(name) 105 106 self.content={} 107 self.header={"version":"2.0", 108 "format":"ascii", 109 "class":className, 110 "object":objectName}
111
112 -class FoamFileParser(PlyParser):
113 """Class that parses a string that contains the contents of an 114 OpenFOAM-file and builds a nested structure of directories and 115 lists from it""" 116
117 - def __init__(self, 118 content, 119 debug=False, 120 noHeader=False, 121 noBody=False, 122 boundaryDict=False, 123 listDict=False, 124 listLengthUnparsed=None):
125 """@param content: the string to be parsed 126 @param debug: output debug information during parsing 127 @param noHeader: switch that turns off the parsing of the header""" 128 129 self.data=None 130 self.header=None 131 self.debug=debug 132 self.listLengthUnparsed=listLengthUnparsed 133 134 startCnt=0 135 136 if noBody: 137 self.start='noBody' 138 startCnt+=1 139 140 if noHeader: 141 self.start='noHeader' 142 startCnt+=1 143 144 if listDict: 145 self.start='pureList' 146 startCnt+=1 147 148 if boundaryDict: 149 self.start='boundaryDict' 150 startCnt+=1 151 152 if startCnt>1: 153 error("Only one start symbol can be specified.",startCnt,"are specified") 154 155 PlyParser.__init__(self,debug=debug) 156 157 #sys.setrecursionlimit(50000) 158 #print sys.getrecursionlimit() 159 160 self.header,self.data=self.parse(content)
161
162 - def __contains__(self,key):
163 return key in self.data
164
165 - def __getitem__(self,key):
166 return self.data[key]
167
168 - def __setitem__(self,key,value):
169 self.data[key]=value
170
171 - def __delitem__(self,key):
172 del self.data[key]
173 174 ## def __len__(self): 175 ## if self.data==None: 176 ## return 0 177 ## else: 178 ## return len(self.data) 179
180 - def getData(self):
181 """ Get the data structure""" 182 return self.data
183
184 - def getHeader(self):
185 """ Get the OpenFOAM-header""" 186 return self.header
187
188 - def printContext(self,c,ind):
189 """Prints the context of the current index""" 190 print "------" 191 print c[max(0,ind-100):max(0,ind-1)] 192 print "------" 193 print ">",c[ind-1],"<" 194 print "------" 195 print c[min(len(c),ind):min(len(c),ind+100)] 196 print "------"
197
198 - def parserError(self,text,c,ind):
199 """Prints the error message of the parser and exit""" 200 print "PARSER ERROR:",text 201 print "On index",ind 202 self.printContext(c,ind) 203 raise PyFoamParserError("Unspecified")
204 205 tokens = ( 206 'NAME', 207 'ICONST', 208 'FCONST', 209 'SCONST', 210 'FOAMFILE', 211 'UNIFORM', 212 'NONUNIFORM', 213 'UNPARSEDCHUNK', 214 'REACTION', 215 ) 216 217 reserved = { 218 'FoamFile' : 'FOAMFILE', 219 'uniform' : 'UNIFORM', 220 'nonuniform' : 'NONUNIFORM', 221 } 222 223 states = ( 224 ('unparsed', 'exclusive'), 225 ) 226
227 - def t_unparsed_left(self,t):
228 r'\(' 229 t.lexer.level+=1
230 # print "left",t.lexer.level, 231
232 - def t_unparsed_right(self,t):
233 r'\)' 234 t.lexer.level-=1 235 # print "right",t.lexer.level, 236 if t.lexer.level < 0 : 237 t.value = t.lexer.lexdata[t.lexer.code_start:t.lexer.lexpos-1] 238 # print t.value 239 t.lexer.lexpos-=1 240 t.type = "UNPARSEDCHUNK" 241 t.lexer.lineno += t.value.count('\n') 242 t.lexer.begin('INITIAL') 243 return t
244 245 t_unparsed_ignore = ' \t\n0123456789.-+e' 246
247 - def t_unparsed_error(self,t):
248 print "Error",t.lexer.lexdata[t.lexer.lexpos] 249 t.lexer.skip(1)
250
251 - def t_NAME(self,t):
252 r'[a-zA-Z_][+\-<>(),.\*|a-zA-Z_0-9+&]*' 253 t.type=self.reserved.get(t.value,'NAME') 254 if t.value[-1]==")": 255 if t.value.count(")")>t.value.count("("): 256 # Give back the last ) because it propably belongs to a list 257 t.value=t.value[:-1] 258 t.lexer.lexpos-=1 259 260 return t
261 262 t_ICONST = r'(-|)\d+([uU]|[lL]|[uU][lL]|[lL][uU])?' 263 264 t_FCONST = r'(-|)((\d+)(\.\d*)(e(\+|-)?(\d+))? | (\d+)e(\+|-)?(\d+))([lL]|[fF])?' 265 266 t_SCONST = r'\"([^\\\n]|(\\.))*?\"' 267 268 literals = "(){};[]" 269 270 t_ignore=" \t\r" 271 272 # Define a rule so we can track line numbers
273 - def t_newline(self,t):
274 r'\n+' 275 t.lexer.lineno += len(t.value) 276 now=t.lexer.lexpos 277 next=t.lexer.lexdata.find('\n',now) 278 if next>=0: 279 line=t.lexer.lexdata[now:next] 280 pos=line.find("=") 281 if pos>=0: 282 if (line.find("//")>=0 and line.find("//")<pos) or (line.find("/*")>=0 and line.find("/*")<pos): 283 return 284 t.value = line 285 t.type = "REACTION" 286 t.lexer.lineno += 1 287 t.lexer.lexpos = next 288 return t
289 290 # C or C++ comment (ignore)
291 - def t_ccode_comment(self,t):
292 r'(/\*(.|\n)*?\*/)|(//.*)' 293 t.lexer.lineno += t.value.count('\n') 294 pass
295 296 # Error handling rule
297 - def t_error(self,t):
298 print "Illegal character '%s'" % t.value[0] 299 t.lexer.skip(1)
300
301 - def p_global(self,p):
302 'global : header dictbody' 303 p[0] = ( p[1] , p[2] )
304
305 - def p_gotHeader(self,p):
306 'gotHeader :' 307 p.lexer.lexpos=len(p.lexer.lexdata)
308
309 - def p_noBody(self,p):
310 ''' noBody : FOAMFILE '{' dictbody gotHeader '}' ''' 311 p[0] = ( p[3] , {} )
312
313 - def p_noHeader(self,p):
314 'noHeader : dictbody' 315 p[0] = ( None , p[1] )
316
317 - def p_pureList(self,p):
318 'pureList : list' 319 p[0] = ( None , p[1] )
320
321 - def p_boundaryDict(self,p):
322 '''boundaryDict : header list 323 | header prelist ''' 324 # p[0] = ( p[1] , dict(zip(p[2][::2],p[2][1::2])) ) 325 p[0] = ( p[1] , p[2] )
326
327 - def p_header(self,p):
328 'header : FOAMFILE dictionary' 329 p[0] = p[2]
330
331 - def p_integer(self,p):
332 '''integer : ICONST''' 333 p[0] = int(p[1])
334
335 - def p_float(self,p):
336 '''integer : FCONST''' 337 p[0] = float(p[1])
338
339 - def p_dictionary(self,p):
340 '''dictionary : '{' dictbody '}' 341 | '{' '}' ''' 342 if len(p)==4: 343 p[0] = p[2] 344 else: 345 p[0] = DictProxy()
346
347 - def p_dictbody(self,p):
348 '''dictbody : dictbody dictline 349 | dictline 350 | empty''' 351 352 if len(p)==3: 353 p[0]=p[1] 354 p[0][p[2][0]]=p[2][1] 355 else: 356 if p[1]: 357 p[0]=DictProxy() 358 p[0][p[1][0]]=p[1][1] 359 else: 360 p[0]=DictProxy()
361
362 - def p_list(self,p):
363 '''list : '(' itemlist ')' ''' 364 p[0] = p[2] 365 if len(p[2])==3 or len(p[2])==9 or len(p[2])==6: 366 isVector=True 367 for i in p[2]: 368 try: 369 float(i) 370 except: 371 isVector=False 372 if isVector: 373 if len(p[2])==3: 374 p[0]=apply(Vector,p[2]) 375 elif len(p[2])==9: 376 p[0]=apply(Tensor,p[2]) 377 else: 378 p[0]=apply(SymmTensor,p[2])
379
380 - def p_unparsed(self,p):
381 '''unparsed : UNPARSEDCHUNK''' 382 p[0] = Unparsed(p[1])
383
384 - def p_prelist_seen(self,p):
385 '''prelist_seen : ''' 386 if self.listLengthUnparsed!=None: 387 # print "Hepp" 388 if int(p[-1])>=self.listLengthUnparsed: 389 # print "Ho",p.lexer.lexpos,p.lexer.lexdata[p.lexer.lexpos-1:p.lexer.lexpos+2],p[1],len(p[1]) 390 p.lexer.begin('unparsed') 391 p.lexer.level=0 392 p.lexer.code_start = p.lexer.lexpos
393 394 # t=p.lexer.token() 395 396 ## print t.type 397 ## return t 398 # p[0] = None 399
400 - def p_prelist(self,p):
401 '''prelist : integer prelist_seen '(' itemlist ')' 402 | integer prelist_seen '(' unparsed ')' ''' 403 if type(p[4])==Unparsed: 404 p[0] = UnparsedList(int(p[1]),p[4].data) 405 else: 406 p[0] = p[4]
407
408 - def p_itemlist(self,p):
409 '''itemlist : itemlist item 410 | item ''' 411 if len(p)==2: 412 if p[1]==None: 413 p[0]=[] 414 else: 415 p[0]=[ p[1] ] 416 else: 417 p[0]=p[1] 418 p[0].append(p[2])
419
420 - def p_wort(self,p):
421 '''word : NAME 422 | UNIFORM 423 | NONUNIFORM''' 424 p[0]=p[1]
425
426 - def p_dictline(self,p):
427 '''dictline : word dictitem ';' 428 | word list ';' 429 | word prelist ';' 430 | word fieldvalue ';' 431 | word dictionary''' 432 if len(p)==4 and type(p[2])==list: 433 # remove the prefix from long lists (if present) 434 doAgain=True 435 tmp=p[2] 436 while doAgain: 437 doAgain=False 438 for i in range(len(tmp)-1): 439 if type(tmp[i])==int and type(tmp[i+1]) in [list]: 440 if tmp[i]==len(tmp[i+1]): 441 nix=tmp[:i]+tmp[i+1:] 442 for i in range(len(tmp)): 443 tmp.pop() 444 tmp.extend(nix) 445 doAgain=True 446 break 447 p[0]= ( p[1] , p[2] )
448
449 - def p_number(self,p):
450 '''number : integer 451 | FCONST''' 452 p[0] = p[1]
453
454 - def p_dimension(self,p):
455 '''dimension : '[' number number number number number number number ']' 456 | '[' number number number number number ']' ''' 457 result=p[2:-1] 458 if len(result)==5: 459 result+=[0,0] 460 461 p[0]=apply(Dimension,result)
462
463 - def p_vector(self,p):
464 '''vector : '(' number number number ')' ''' 465 p[0]=apply(Vector,p[2:5])
466
467 - def p_tensor(self,p):
468 '''tensor : '(' number number number number number number number number number ')' ''' 469 p[0]=apply(Tensor,p[2:11])
470
471 - def p_symmtensor(self,p):
472 '''symmtensor : '(' number number number number number number ')' ''' 473 p[0]=apply(SymmTensor,p[2:8])
474
475 - def p_fieldvalue_uniform(self,p):
476 '''fieldvalue : UNIFORM number 477 | UNIFORM vector 478 | UNIFORM tensor 479 | UNIFORM symmtensor''' 480 p[0] = Field(p[2])
481
482 - def p_fieldvalue_nonuniform(self,p):
483 '''fieldvalue : NONUNIFORM NAME list 484 | NONUNIFORM NAME prelist''' 485 p[0] = Field(p[3],name=p[2])
486
487 - def p_dictitem(self,p):
488 '''dictitem : longitem 489 | pitem''' 490 if type(p[1])==tuple: 491 p[0]=TupleProxy(p[1]) 492 else: 493 p[0] = p[1]
494
495 - def p_longitem(self,p):
496 '''longitem : pitemlist pitem''' 497 p[0] = p[1]+(p[2],)
498
499 - def p_pitemlist(self,p):
500 '''pitemlist : pitemlist pitem 501 | pitem ''' 502 if len(p)==2: 503 p[0]=(p[1],) 504 else: 505 ## print type(p[1][-1]) 506 ## if type(p[1][-1])==int and type(p[2])==tuple: 507 ## print "Hepp",p[2] 508 p[0]=p[1]+(p[2],)
509
510 - def p_pitem(self,p):
511 '''pitem : word 512 | SCONST 513 | number 514 | dictionary 515 | list 516 | dimension 517 | empty''' 518 p[0] = p[1]
519
520 - def p_item(self,p):
521 '''item : pitem 522 | REACTION 523 | list 524 | dictionary''' 525 p[0] = p[1]
526
527 - def p_empty(self,p):
528 'empty :' 529 pass
530
531 - def p_error(self,p):
532 raise PyFoamParserError("Syntax error at token", p) # .type, p.lineno
533 # Just discard the token and tell the parser it's okay. 534 # self.yacc.errok() 535
536 -class PyFoamParserError:
537 - def __init__(self,descr,data=None):
538 self.descr=descr 539 self.data=data
540
541 - def __str__(self):
542 result="Error in PyFoamParser: '"+self.descr+"'" 543 if self.data!=None: 544 val=self.data.value 545 if len(val)>100: 546 val=val[:40]+" .... "+val[-40:] 547 548 result+=" @ %r (Type: %s ) in line %d at position %d" % (val, 549 self.data.type, 550 self.data.lineno, 551 self.data.lexpos) 552 553 return result
554
555 - def __repr__(self):
556 return str(self)
557
558 -class FoamStringParser(FoamFileParser):
559 """Convenience class that parses only a headerless OpenFOAM dictionary""" 560
561 - def __init__(self,content,debug=False):
562 """@param content: the string to be parsed 563 @param debug: output debug information during parsing""" 564 565 FoamFileParser.__init__(self,content,debug=debug,noHeader=True,boundaryDict=False)
566
567 - def __str__(self):
568 return str(FoamFileGenerator(self.data))
569
570 -class ParsedBoundaryDict(ParsedParameterFile):
571 """Convenience class that parses only a OpenFOAM polyMesh-boundaries file""" 572
573 - def __init__(self,name,backup=False,debug=False):
574 """@param name: The name of the parameter file 575 @param backup: create a backup-copy of the file""" 576 577 ParsedParameterFile.__init__(self,name,backup=backup,debug=debug,boundaryDict=True)
578
579 - def parse(self,content):
580 """Constructs a representation of the file""" 581 temp=ParsedParameterFile.parse(self,content) 582 self.content={} 583 for i in range(0,len(temp),2): 584 self.content[temp[i]]=temp[i+1] 585 return self.content
586
587 - def __str__(self):
588 string="// File generated by PyFoam - sorry for the ugliness\n\n" 589 temp=[] 590 for k,v in self.content.iteritems(): 591 temp.append((k,v)) 592 593 temp.sort(lambda x,y:cmp(int(x[1]["startFace"]),int(y[1]["startFace"]))) 594 595 temp2=[] 596 597 for b in temp: 598 temp2.append(b[0]) 599 temp2.append(b[1]) 600 601 generator=FoamFileGenerator(temp2,header=self.header) 602 string+=str(generator) 603 604 return string
605
606 -class ParsedFileHeader(ParsedParameterFile):
607 """Only parse the header of a file""" 608
609 - def __init__(self,name):
610 ParsedParameterFile.__init__(self,name,backup=False,noBody=True)
611
612 - def __getitem__(self,name):
613 return self.header[name]
614
615 - def __contains__(self,name):
616 return name in self.header
617
618 - def __len__(self):
619 return len(self.header)
620