1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
|
#!/usr/local/bin/python
# Ralph Gauges <ralph.gauges@eml.villa-bosch.de>
## YOU NEED AT LEAST python version 1.5 TO RUN THIS SCRIPT !!
## Todo List: - complete the predefined classes (what about ?Bat etc. ?) (hopefully already done)
## - store comments from model files to write them back out with the model
## - add methods to use the model class to represent a java swing jtree
## - add COORD modifier and @ ????
import string ## imports a module for string operations
import sys ## imports a module to get command line arguments
class Model: ## This class represents the model as a tree
## Systemmodels is a long string that hold the textual representation of the classes and datatypes defined in sysclasses.c
## This might be necessary for the validation.
## At least ?Colour and ?View are used in some models
Systemmodels=["?Model","?Text","?Comment","?Keyword","?Class","?Tag","SourceCode","?Include","?Session","?Display","?Table","#Table_definition","?Colour","?UserSession","?Jade","?View"]
CharacterArrays=["?LongText","?DNA","?Peptide","?BasePosition","?BaseQuality","?URL","?BaseCall","?KeySet","?MatchTable"] ## some character arrays of ACEDB.
## they are needed for the validation process
BasicDataTypes=["Int","Text","Float","DateType"]
## those are needed to find out if an entry is a label or a datatype
def __init__(self,FileContent): ## Constructor
self.Classes=[] ## A List that holds all the classes
self.DefinedDataTypes=[] ## A list that holds the user defined datatypes
Blocks=self.MakeBlocks(FileContent) ## Divides the content of the file into blocks which correspond to the individual classes
for Block in Blocks:
if (Block[0][0]== "?"): ## if it starts with a '?', it is a class
self.Classes.append(ClassType(self,Block,self.BasicDataTypes)) ## add a new class instance to Classes
else:
if (Block[0][0]=="#"): ## if it starts with a '#' it is a datatype
self.DefinedDataTypes.append(UserDefinedType(self,Block,self.BasicDataTypes)) ## add a new datatype to the user defined datatypes
else: ## if it doesn't start with '?' or '#' than it is an error
print "This Datatype is unknown: "+string.split(Block[0])[0]
print "Please check your model."
sys.exit(0) ## exit the program
def MakeBlocks(self,ModelText):
ClassBlocks=[]
ClassBlock=[]
Text=string.join(ModelText,"")
while (string.find(Text,"/*") != -1): ## removes multi line comments
x=string.find(Text,"/*")
y=string.find(Text,"*/")
if (x > y): ## since it doesn't work for all cases print error message and exit
print "There is some problem with the comments."
print "Please remove all nestet comments."
sys.exit(0)
else:
Text=Text[:x]+Text[y+2:]
ModelText=string.split(Text,"\n")
NumOfClasses=0
for Line in ModelText:
x=string.find(Line,"//")
if (x != -1):
Line=Line[:x] ## removes one line comment
Comment=Line[x:]
if (len(string.split(Line)) > 0):
Line=string.expandtabs(Line)
if (Line[0] not in [" ","\t"]): ## if the line starts with anything else than ' ' or '\t' a new class starts
NumOfClasses=NumOfClasses+1
if (NumOfClasses !=1): ## if it is not the first class
ClassBlocks.append(ClassBlock) ## add the class
ClassBlock=[Line] ## this Line belongs to the next class
else:
ClassBlock.append(Line) ## it is the first time a `?' or `#' is encountered, so there is nothing to add yet
ClassBlocks.append(ClassBlock) ## We have to add the last class block before we return to the main program
return ClassBlocks ## this return a list of Textblocks that correspond to classes
def __str__(self): ## this represents the model if you say 'print 'instance of Model'
String=""
for Class in self.Classes:
String=String+str(Class)
for UDataType in self.DefinedDataTypes:
String=String+str(UDataType)
return String
def __repr__(self): ## similar to __str__
return self.__str__()
def toString(self): ## actualy not used, but might come handy when interfacing to java
return self
def Validate(self): ## this routine checks the model
ERROR=""
ValidIdentifiers=[]
CLASSDICT=self.MakeClassDict() ## this makes a dictionary of all the defined classnames and pointers to the corresponding class in the model
for CLASS in self.Classes: ## let every class validate itself
ERROR=ERROR+CLASS.Validate(self.BasicDataTypes,CLASSDICT,self.CharacterArrays+self.Systemmodels)
for DATATYPE in self.DefinedDataTypes: ## let every datatype validate itself
ERROR=ERROR+DATATYPE.Validate(self.BasicDataTypes,CLASSDICT,self.CharacterArrays+self.Systemmodels)
return ERROR
def MakeClassDict(self): ## this makes a dictionary of all classnames and pointers to the corresponding classes
## with this it is possible to get a classinstance with the name of the class
## {classname:pointer_to_class}
CLASSDICT={}
for CLASS in self.Classes+self.DefinedDataTypes:
CLASSDICT[CLASS.GetName()]=CLASS
return CLASSDICT
def GetPath(self):
return ""
class ClassType: ## this class represents a model class
def __init__(self,Parent,ClassBlock,BasicDataTypes): ## Constructor
self.Parts=[] ## Parts is a list that stores the branches (labels) and leafes (datatypes)
self.SetParent(Parent) ## stores the parent node
self.SetName(string.split(ClassBlock[0])[0]) ## sets the name of the class
NextLevel=self.GetNextLevelBlocks(ClassBlock) ## makes the next level of hirearchy
## this just makes textblocks of all the entries that belong to the next level in the tree
for Object in NextLevel: ## for each textblock try to make an object and add it to the list
## the entries are created as lists of lists
## each line in the modelfile corresponds to a list
## lists that correspond to datatypes will have more entries in one list
## list corresponding to labels have only one entry
## [
## [label1],
## [label2],
## [datatype1, datatype2, datatype3...],
## [label4]
## ]
O=self.MakeObject(Object,BasicDataTypes)
if (O):
self.AddObject(O)
else: ## if no object could be made, print an error and exit
print "This block does not represent a valid entry:"
print Object
sys.exit(0)
def GetNextLevelBlocks(self,Block): ## makes textblocks corresponding to the next level in the tree
BLOCKS=[]
TEMP=string.split(string.strip(Block[0])) ## split first line into parts
if (len(TEMP) > 1): ## if object has parts
INDENT=string.find(Block[0]," "+TEMP[1])+1
TEMP2=[]
for LINE in Block:
if (LINE[INDENT-1] not in [" ","\t"]): ## if the character before the current indentation level is a non whitespace, then we have a problem with the indentation
print self.GetPath()+": There seems to be a problem with the indentation.\n\n"
sys.exit(0)
else:
LINE=LINE[INDENT:] ## shorten each line according to the indentation level
if (LINE[0] != " "): ## if the line doesn't start with a space, we have the start of a new object
if (TEMP2 != []): ## is it the first one ?, if not
BLOCKS.append(TEMP2) ## add the current object to the list
TEMP2=[LINE]
else:
TEMP2.append(LINE) ## starts with a space? So it is part of the current object
BLOCKS.append(TEMP2) ## don't forget to add the last one to the list
else: ## if object doesn't have parts, it can only one line long
## otherwise there is a problem with the indentation
if (len(Block)>1):
print self.GetPath()+": There seems to be a problem with the indentation.\n\n"
sys.exit(0)
return BLOCKS
def __repr__(self): ## similar to __str__
return self
def __str__(self): ## returns a string representation of the class
STRING=""
if (len(self.Parts) > 0):
for PART in self.Parts: ## let every entry represent itself
for P in PART:
STRING=STRING+str(P)+" "
STRING=STRING[:-1]
LINES=string.split(STRING,"\n")
LINES=LINES[:-1]
LINES[0]=self.GetName()+"\t"+LINES[0] ## add the name of this instance to the beginning of the first line
INDENT=(len(self.GetName())/8)+1 ## Indentation of the other lines
for X in range(1,len(LINES)):
LINES[X]=INDENT*"\t"+LINES[X] ## indent all the other lines
STRING=string.join(LINES,"\n")
STRING=STRING+"\n"
else:
STRING=self.GetName()+"\n" ## if the instance doesn't have entries, return just the name
return STRING
def SetParent(self,Parent): ## sets the parent node
self.Parent=Parent
def GetParent(self): ## return the parent node
return self.Parent
def SetParts(self,Parts): ## not used, but sets Parts
self.Parts=Parts
def GetParts(self):
return self.Parts ## returns all entries
def HasLabel(self,LabelName): ## checks wether the class has a specified label
LABEL=""
for PART in self.Parts:
if (string.upper(PART[0].GetName()) == string.upper(LabelName)): ## if the class has the label
LABEL=PART[0].GetPath() ## return the Path to the label
break
if (LABEL == ""): ## if the class doesn't contain the label directly, check further down
for PART in self.Parts:
LABEL=PART[0].HasLabel(LabelName)
if (LABEL != ""):
break
return LABEL ## returns an empty string if the label wasn't found
def Validate(self,BasicDataTypes,ClassDict,CharacterArrays): ## checks the class
ERROR=""
for PART in self.Parts: ## let every entry check itself
for P in PART:
ERROR=ERROR+P.Validate(BasicDataTypes,ClassDict,CharacterArrays)
if (self.GetName()[0] != "?"): ## if the name doesn't start with an `?`, it's not a class
ERROR=ERROR+"ERROR in "+self.GetPath()+": Classes have to start with an '?'.\n"
if (string.upper(self.GetName()) in BasicDataTypes+["UNIQUE","XREF","REPEAT"]):
## if the name corrsponds to a reserved keyword, than print an error message
ERROR=ERROR+"ERROR in "+self.GetPath()+": The name "+self.GetName()+" is not allowed for a class.\n"
if (("#"+string.upper(self.GetName()[1:])) in map(string.upper,ClassDict.keys()+CharacterArrays)): ## checks wether there already exists a defined datatype with the same name
ERROR=ERROR+"ERROR in "+self.GetPath()+": There already exists a defined datatype with this name.\n"
if (len(self.Parts) < 1): ## if the class is empty
ERROR=ERROR+"ERROR in "+self.GetPath()+": Classes must have labels. They can not be empty.\n"
return ERROR
def SetName(self,Name):
self.Name=Name
def GetName(self):
return self.Name
def GetPath(self): ## returns the path of the instance ?Classname -> Label1 -> Label11 -> Datatype111
PATH=""
if (hasattr(self,"Parent")):
PATH=self.Parent.GetPath()
if (PATH==""):
PATH=self.Name
else:
PATH=PATH+" -> "+self.Name
return PATH
def AddObject(self,Object): ## just adds an entry
self.Parts.append(Object)
def RemoveObject(self,Object): ## removes an entry
self.Parts.remove(Object)
def MakeDataPackages(self,Object,BasicDataTypes): ## if the object is a line with several datatypes, it has to be divided into the individual datypes
## this makes lists of the datatypes and their modifiers
BITS=string.split(Object[0])
PACKAGES=[]
LAST=-1
for X in range(0,len(BITS)):
if ((string.upper(BITS[X]) in map(string.upper,BasicDataTypes)) or (BITS[X][0] in ["#","?"])):
if (LAST != -1):
if (string.upper(BITS[X-1]) == "UNIQUE"):
PACKAGE=BITS[LAST:X-1]
PACKAGES.append(PACKAGE)
else:
PACKAGE=BITS[LAST:X]
PACKAGES.append(PACKAGE)
LAST=X
else:
LAST=0
if (string.upper(BITS[LAST-1]) =="UNIQUE"):
PACKAGES.append(BITS[LAST-1:])
else:
PACKAGES.append(BITS[LAST:])
return PACKAGES
def MakeObject(self,Object,BasicDataTypes): ## this routine checks wether an object is a label or a datatype or a 'UNIQUE list'
IDENTIFIER = string.split(Object[0])[0]
OBJECT=[]
if ((string.upper(IDENTIFIER) in map(string.upper,BasicDataTypes)) or (IDENTIFIER[0] in ["#","?"])):
PACKAGES=self.MakeDataPackages(Object,BasicDataTypes)
for PACKAGE in PACKAGES:
OBJECT.append(DataType(self,PACKAGE,BasicDataTypes))
else:
if (string.upper(IDENTIFIER) == "UNIQUE"):
if ((len(Object) == 1) and ((string.upper(string.split(Object[0])[1]) in map(string.upper,BasicDataTypes)) or (string.split(Object[0])[1][0] in ["#","?"]))):
PACKAGES=self.MakeDataPackages(Object,BasicDataTypes)
OBJECT=[]
for PACKAGE in PACKAGES:
OBJECT.append(DataType(self,PACKAGE,BasicDataTypes))
else:
OBJECT.append(ExclusiveListType(self,Object,BasicDataTypes))
else:
if (string.upper(IDENTIFIER) in ["XREF","REPEAT"]):
print self.GetPath()
print "Fatal error. This entry can not have a modifier "+IDENTIFIER
sys.exit(0)
else:
OBJECT.append(LabelType(self,Object,BasicDataTypes))
return OBJECT
def GetNumParts(self): ## returns the number of entries
return len(self.Parts)
def GetLenPart(self,INDEX): ## returns the length of an entry
## for labels this is 1
## for lines with datatypes, this corresponds to the number of datatypes on the line
if (self.GetNumParts() >= INDEX):
RESULT=len(self.Parts[INDEX])
else:
RESULT=-1
return RESULT
def FindElement(self,Element): ## this searches for an instance of a label or datatype in Parts and returns its index
RESULT=(-1,-1)
for PART in self.Parts:
if (Element in PART):
RESULT=(self.Parts.index(PART),PART.index(Element))
return RESULT
class LabelType(ClassType): ## this class represents a label
## it inherits everything from the ClassType class
## only the validation method is overwritten
def Validate(self,BasicDataTypes,ClassDict,CharacterArrays): ## validates the label
ERROR=""
for PART in self.Parts: ## let all entries check themselves
for P in PART:
ERROR=ERROR+P.Validate(BasicDataTypes,ClassDict,CharacterArrays)
if ((self.GetName()[0] in ["#","?"]) or (string.upper(self.GetName()) in map(string.upper,BasicDataTypes)+["UNIQUE","XREF","REPEAT"])):
## if the name starts with `#` or `?` or corresponds to a reserved keyword, than print an error message
ERROR=ERROR+"ERROR "+self.GetPath()+": This name is not allowed for a label.\n\n"
return ERROR
class ExclusiveListType(ClassType): ## this class represents a UNIQUE list of labels
## UNIQUE datatypes are just datatypes with the modifier UNIQUE
## this class also inherits everything from ClassType and overwrites the validation method
def Validate(self,BasicDataTypes,ClassDict,CharacterArrays):
ERROR=""
for PART in self.Parts:
if (len(PART) > 1): ## if the entry has more than one entry, it can not be a label
ERROR=ERROR+"ERROR in "+self.GetPath()+": UNIQUE lists can only have labels not datatypes.\n"
for P in PART:
ERROR=ERROR+P.Validate(BasicDataTypes,ClassDict,CharacterArrays)
if (string.upper(self.GetName()) != "UNIQUE"): ## actualy the UNIQUE list is just a label that has the name UNIQUE
## if it doesn't have that name, it's an error
ERROR=ERROR+"ERROR in "+self.GetPath()+": UNIQUE lists must have name 'UNIQUE'.\n"
if (len(self.Parts) < 1): ## UNIQUE lists can not be empty
ERROR=ERROR+"ERROR in "+self.GetPath()+": UNIQUE lists must have labels. They can not be empty.\n"
return ERROR
class UserDefinedType(ClassType): ## this class represents the user defined datatypes
## it inherits everything from ClassType and overwrites the validation method
def Validate(self,BasicDataTypes,ClassDict,CharacterArrays):
ERROR=""
for PART in self.Parts: ## let every entry check itself
for P in PART:
ERROR=ERROR+P.Validate(BasicDataTypes,ClassDict,CharacterArrays)
if (self.GetName()[0] != "#"): ## per definition user defined datatypes have to start with an '#'
ERROR=ERROR+"ERROR in "+self.GetPath()+": User defined datatypes have to start with an '#'.\n"
if (len(self.Parts) < 1): ## an empty user defined datatype doesn't make sense
ERROR=ERROR+"ERROR in "+self.GetPath()+": User defined datatypes not be empty.\n"
if ((string.upper(self.GetName()[1:]) in map(string.upper,BasicDataTypes)+["UNIQUE","XREF","REPEAT"])):
## if the name corrsponds to a reserved keyword, than print an error message
ERROR=ERROR+"ERROR "+self.GetPath()+": This name is not allowed for a user defined datatype.\n\n"
if ("?"+string.upper(self.GetName()[1:]) in map(string.upper,ClassDict.keys()+CharacterArrays)): ## checks wether there already exists a class with the same name
ERROR=ERROR+"ERROR in "+self.GetPath()+": There already exists a class with this name.\n"
return ERROR
class DataType: ## this class represents a datatype
def __init__(self,Parent,Object,BasicDataTypes): ## Constructor
self.Modifiers=[] ## this lists hold the modifiers
self.SetParent(Parent) ## sets the parent node
for P in Object: ## an initialisation a datatype object gets a list of string that represents the individual parts of the datatype, like modifiers, name etc.
## this list is not ordered
if (string.upper(P) == "UNIQUE"):
self.AddModifier(UNIQUE_Modifier(self,P))
if ((string.upper(P) in map(string.upper,BasicDataTypes)) or (P[0] in ["#","?"])):
self.SetName(P)
if (string.upper(P) == "XREF"):
self.AddModifier(XREF_Modifier(self,P,Object[Object.index(P)+1]))
if (string.upper(P) == "REPEAT"):
self.AddModifier(REPEAT_Modifier(self,P))
def SetParent(self,Parent): ## sets the parent node
self.Parent=Parent
def GetParent(self): ## returns the parent node
return self.Parent
def Validate(self,BasicDataTypes,ClassDict,CharacterArrays): ## checks the datatype
ERROR=""
if ((string.upper(self.GetName()) not in map(string.upper,BasicDataTypes)) and (self.GetName()[0] not in ["?","#"])):
## the name has to start with `?' or `#` or be a basic data type
ERROR=ERROR+"ERROR in "+self.GetPath()+": This datatype is not valid.\n"
else:
if (self.GetName()[0] in ["#","?"]): ## if it is a class, it must be defined in the model
if ((string.upper(self.GetName()) not in map(string.upper,ClassDict.keys()+CharacterArrays)) and ("?"+string.upper(self.GetName()[1:]) not in map(string.upper,ClassDict.keys()+CharacterArrays))):
ERROR=ERROR+"ERROR in "+self.GetPath()+": This class or datatype was never defined.\n"
else: ## check if the classname has consistens spelling concerning upper and lower case letters
if ((self.GetName() not in ClassDict.keys()+CharacterArrays) and ("?"+self.GetName()[1:] not in ClassDict.keys()+CharacterArrays)):
ERROR=ERROR+"WARNING! "+self.GetPath()+": There is an inconsistency in the spelling of a class or datatype concerning upper and lower case usage.\n"
else: ## check if the basic datatype has consistent usage of upper and lower case letters
if (self.GetName() not in BasicDataTypes):
ERROR=ERROR+"WARNING! "+self.GetPath()+": There is an inconsistency in the spelling of a datatype concerning upper and lower case usage.\n"
if (len(self.Modifiers) > 3): ## a datatype can at most have 3 modifiers
ERROR=ERROR+"ERROR in "+self.GetPath()+": A datatype can at most have 3 modifieres (UNIQUE xxx XREF yyy REPEAT).\n"
else:
XREF_count=0
UNIQUE_count=0
REPEAT_count=0
for Modif in self.Modifiers:
if (isinstance(Modif,UNIQUE_Modifier)):
UNIQUE_count=UNIQUE_count+1
else:
if (isinstance(Modif,XREF_Modifier)):
ERR=Modif.Validate(BasicDataTypes)
if (ERR != ""):
ERROR=ERROR+"ERROR in "+self.GetPath()+" "+Modif.__str__()+": "+ERR
if (self.GetName()[0] != "?"): ## only labels in classinstance can be referenced
ERROR=ERROR+"ERROR in "+self.GetPath()+": Only classinstances can have references.\n"
if (ClassDict.has_key(self.GetName())):
CLASS=ClassDict[self.GetName()]
if (CLASS.HasLabel(Modif.GetRef()) == ""): ## checks wether the reference exists
ERROR=ERROR+"ERROR in "+self.GetPath()+": The label '"+Modif.GetRef()+"' is not defined in class " +self.GetName()+".\n"
else:
LABELNAME=string.split(CLASS.HasLabel(Modif.GetRef()))[-1]
if (LABELNAME != Modif.GetRef()):
ERROR=ERROR+"WARNING! There is an inconsistency in the spelling of the label '"+CLASS.HasLabel(Modif.GetRef())+"'. In the reference that belongs to '"+self.GetPath()+"' it is spelled '"+Modif.GetRef()+"'.\n"
XREF_count=XREF_count+1
else:
if (isinstance(Modif,REPEAT_Modifier)):
REPEAT_count=REPEAT_count+1
if (self.IsLast() !=1): ## only the last datatype can have modifier REPEAT
ERROR=ERROR+"ERROR in "+self.GetPath()+": Only the last datatype in a line can have a REPEAT modifier.\n"
if ((REPEAT_count > 1) or (XREF_count > 1) or (UNIQUE_count > 1)): ## each modifier can only appear once
ERROR=ERROR+"ERROR in "+self.GetPath()+": Each modifier can only be used once for a datatype.\n"
return ERROR
def AddModifier(self,Modif): ## adds a modifier
self.Modifiers.append(Modif)
def RemoveModifier(self,ModName): ## removes a modifier
for Modif in self.Modifiers:
if (Modif.GetName() == ModName):
self.Modifiers.remove(Modif)
def SetName(self,Name): ## sets the name
self.Name=Name
def GetName(self): ## returns the name
return self.Name
def GetPath(self): ## returns the path to the object
PATH=""
if (hasattr(self,"Parent")):
PATH=self.Parent.GetPath()
if (PATH==""):
PATH=self.Name
else:
PATH=PATH+" -> "+self.Name
return PATH
def __str__(self): ## returns a string representation of the object
STRING=self.GetName()
for Modif in self.Modifiers:
if (isinstance(Modif,UNIQUE_Modifier)):
STRING=Modif.__str__()+" "+STRING
else:
STRING=STRING+" "+Modif.__str__()
if (self.IsLast()==1):
STRING=STRING+"\n"
return STRING
def __repr__(self): ## similar to __str__
return self
def IsLast(self): ## checks wether the datatype is the last one in a line
RESULT=0
POSITION=self.Parent.FindElement(self)
if ((POSITION[1]+1) == self.Parent.GetLenPart(POSITION[0])):
RESULT=1
return RESULT
def HasLabel(self,LabelName): ## this is needed to ensure that the recursive method for class and labels works
return ""
class Modifier: ## abstract modifier class
def __init__(self,Parent,Name):
self.SetParent(Parent)
self.SetName(Name)
def __str__(self):
return self.GetName()
def __repr__(self):
return self
def SetName(self,Name):
self.Name=Name
def SetParent(self,Parent):
self.Parent=Parent
def GetName(self):
return self.Name
def GetParent(self):
return self.Parent
def Validate(self,BasicDataTypes):
return ""
class XREF_Modifier(Modifier): ## inherits from Modifier and adds some extra functinality
def __init__(self,Parent,Name,Reference):
Modifier.__init__(self,Parent,Name)
self.SetRef(Reference)
def __str__(self):
return Modifier.__str__(self)+" "+self.GetRef()
def SetRef(self,Ref):
self.Reference=Ref
def GetRef(self):
return self.Reference
def Validate(self,BasicDataTypes):
Error = ""
if ((self.GetRef()[0] in ["#","?"]) or (string.upper(self.GetRef()) in map(string.upper,BasicDataTypes))):
Error="A reference can not be a class or datatype, it must be a label.\n"
return Error
class REPEAT_Modifier(Modifier): ## same as Modifier just needed for convienence
pass
class UNIQUE_Modifier(Modifier): ## same as Modifier
pass
if __name__=="__main__": ## this method is the main method
## it is executed when the file is called from the command line
## it is not executed when the file is imported as a module
if (len(sys.argv) > 2):
print "usage ParseModel.py 'modelfile'"
else:
File=sys.argv[1] ## first command line argument is the filename
Text=open(File,'r').readlines() ## read all the text from the file
M=Model(Text) ## creates an instance M of the Model
print M.Validate() ## prints the reulst of the validation process for the whole model
|