2
0

ExpressReader.py 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. #!/usr/bin/env python3
  2. # -*- Coding: UTF-8 -*-
  3. # ---------------------------------------------------------------------------
  4. # Open Asset Import Library (ASSIMP)
  5. # ---------------------------------------------------------------------------
  6. #
  7. # Copyright (c) 2006-2010, ASSIMP Development Team
  8. #
  9. # All rights reserved.
  10. #
  11. # Redistribution and use of this software in source and binary forms,
  12. # with or without modification, are permitted provided that the following
  13. # conditions are met:
  14. #
  15. # * Redistributions of source code must retain the above
  16. # copyright notice, this list of conditions and the
  17. # following disclaimer.
  18. #
  19. # * Redistributions in binary form must reproduce the above
  20. # copyright notice, this list of conditions and the
  21. # following disclaimer in the documentation and/or other
  22. # materials provided with the distribution.
  23. #
  24. # * Neither the name of the ASSIMP team, nor the names of its
  25. # contributors may be used to endorse or promote products
  26. # derived from this software without specific prior
  27. # written permission of the ASSIMP Development Team.
  28. #
  29. # THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  30. # "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  31. # LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  32. # A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  33. # OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  34. # SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  35. # LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  36. # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  37. # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  38. # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  39. # OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  40. # ---------------------------------------------------------------------------
  41. """Parse an EXPRESS file and extract basic information on all
  42. entities and data types contained"""
  43. import sys, os, re
  44. from collections import OrderedDict
  45. re_match_entity = re.compile(r"""
  46. ENTITY\s+(\w+)\s* # 'ENTITY foo'
  47. .*? # skip SUPERTYPE-of
  48. (?:SUBTYPE\s+OF\s+\((\w+)\))?; # 'SUBTYPE OF (bar);' or simply ';'
  49. (.*?) # 'a : atype;' (0 or more lines like this)
  50. (?:(?:INVERSE|UNIQUE|WHERE)\s*$.*?)? # skip the INVERSE, UNIQUE, WHERE clauses and everything behind
  51. END_ENTITY;
  52. """,re.VERBOSE|re.DOTALL|re.MULTILINE)
  53. re_match_type = re.compile(r"""
  54. TYPE\s+(\w+?)\s*=\s*((?:LIST|SET)\s*\[\d+:[\d?]+\]\s*OF)?(?:\s*UNIQUE)?\s*(\w+) # TYPE foo = LIST[1:2] of blub
  55. (?:(?<=ENUMERATION)\s*OF\s*\((.*?)\))?
  56. .*? # skip the WHERE clause
  57. END_TYPE;
  58. """,re.VERBOSE|re.DOTALL)
  59. re_match_field = re.compile(r"""
  60. \s+(\w+?)\s*:\s*(OPTIONAL)?\s*((?:LIST|SET)\s*\[\d+:[\d?]+\]\s*OF)?(?:\s*UNIQUE)?\s*(\w+?);
  61. """,re.VERBOSE|re.DOTALL)
  62. class Schema:
  63. def __init__(self):
  64. self.entities = OrderedDict()
  65. self.types = OrderedDict()
  66. class Entity:
  67. def __init__(self,name,parent,members):
  68. self.name = name
  69. self.parent = parent
  70. self.members = members
  71. class Field:
  72. def __init__(self,name,type,optional,collection):
  73. self.name = name
  74. self.type = type
  75. self.optional = optional
  76. self.collection = collection
  77. self.fullspec = (self.collection+' ' if self.collection else '') + self.type
  78. class Type:
  79. def __init__(self,name,aggregate,equals,enums):
  80. self.name = name
  81. self.aggregate = aggregate
  82. self.equals = equals
  83. self.enums = enums
  84. def read(filename, silent=False):
  85. schema = Schema()
  86. print( "Try to read EXPRESS schema file" + filename)
  87. with open(filename,'rt') as inp:
  88. contents = inp.read()
  89. types = re.findall(re_match_type,contents)
  90. for name,aggregate,equals,enums in types:
  91. schema.types[name] = Type(name,aggregate,equals,enums)
  92. entities = re.findall(re_match_entity,contents)
  93. for name,parent,fields_raw in entities:
  94. print('process entity {0}, parent is {1}'.format(name,parent)) if not silent else None
  95. fields = re.findall(re_match_field,fields_raw)
  96. members = [Field(name,type,opt,coll) for name, opt, coll, type in fields]
  97. print(' got {0} fields'.format(len(members))) if not silent else None
  98. schema.entities[name] = Entity(name,parent,members)
  99. return schema
  100. if __name__ == "__main__":
  101. sys.exit(read(sys.argv[1] if len(sys.argv)>1 else 'schema.exp'))