1
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
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
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
66 return key in self.content
67
69 return self.content[key]
70
72 self.content[key]=value
73
76
78 return len(self.content)
79
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
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
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
158
159
160 self.header,self.data=self.parse(content)
161
163 return key in self.data
164
166 return self.data[key]
167
170
173
174
175
176
177
178
179
181 """ Get the data structure"""
182 return self.data
183
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
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
228 r'\('
229 t.lexer.level+=1
230
231
233 r'\)'
234 t.lexer.level-=1
235
236 if t.lexer.level < 0 :
237 t.value = t.lexer.lexdata[t.lexer.code_start:t.lexer.lexpos-1]
238
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
248 print "Error",t.lexer.lexdata[t.lexer.lexpos]
249 t.lexer.skip(1)
250
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
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
295
296
298 print "Illegal character '%s'" % t.value[0]
299 t.lexer.skip(1)
300
302 'global : header dictbody'
303 p[0] = ( p[1] , p[2] )
304
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
314 'noHeader : dictbody'
315 p[0] = ( None , p[1] )
316
318 'pureList : list'
319 p[0] = ( None , p[1] )
320
322 '''boundaryDict : header list
323 | header prelist '''
324
325 p[0] = ( p[1] , p[2] )
326
328 'header : FOAMFILE dictionary'
329 p[0] = p[2]
330
332 '''integer : ICONST'''
333 p[0] = int(p[1])
334
336 '''integer : FCONST'''
337 p[0] = float(p[1])
338
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
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
381 '''unparsed : UNPARSEDCHUNK'''
382 p[0] = Unparsed(p[1])
383
385 '''prelist_seen : '''
386 if self.listLengthUnparsed!=None:
387
388 if int(p[-1])>=self.listLengthUnparsed:
389
390 p.lexer.begin('unparsed')
391 p.lexer.level=0
392 p.lexer.code_start = p.lexer.lexpos
393
394
395
396
397
398
399
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
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
421 '''word : NAME
422 | UNIFORM
423 | NONUNIFORM'''
424 p[0]=p[1]
425
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
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
450 '''number : integer
451 | FCONST'''
452 p[0] = p[1]
453
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
464 '''vector : '(' number number number ')' '''
465 p[0]=apply(Vector,p[2:5])
466
468 '''tensor : '(' number number number number number number number number number ')' '''
469 p[0]=apply(Tensor,p[2:11])
470
472 '''symmtensor : '(' number number number number number number ')' '''
473 p[0]=apply(SymmTensor,p[2:8])
474
481
486
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
496 '''longitem : pitemlist pitem'''
497 p[0] = p[1]+(p[2],)
498
500 '''pitemlist : pitemlist pitem
501 | pitem '''
502 if len(p)==2:
503 p[0]=(p[1],)
504 else:
505
506
507
508 p[0]=p[1]+(p[2],)
509
511 '''pitem : word
512 | SCONST
513 | number
514 | dictionary
515 | list
516 | dimension
517 | empty'''
518 p[0] = p[1]
519
521 '''item : pitem
522 | REACTION
523 | list
524 | dictionary'''
525 p[0] = p[1]
526
530
533
534
535
538 self.descr=descr
539 self.data=data
540
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
557
559 """Convenience class that parses only a headerless OpenFOAM dictionary"""
560
561 - def __init__(self,content,debug=False):
566
569
571 """Convenience class that parses only a OpenFOAM polyMesh-boundaries file"""
572
573 - def __init__(self,name,backup=False,debug=False):
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
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
607 """Only parse the header of a file"""
608
611
613 return self.header[name]
614
616 return name in self.header
617
619 return len(self.header)
620