ExpressReader.py 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120
  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. re_match_entity = re.compile(r"""
  45. ENTITY\s+(\w+)\s* # 'ENTITY foo'
  46. .*? # skip SUPERTYPE-of
  47. (?:SUBTYPE\s+OF\s+\((\w+)\))?; # 'SUBTYPE OF (bar);' or simply ';'
  48. (.*?) # 'a : atype;' (0 or more lines like this)
  49. (?:(?:INVERSE|UNIQUE|WHERE)\s*$.*?)? # skip the INVERSE, UNIQUE, WHERE clauses and everything behind
  50. END_ENTITY;
  51. """,re.VERBOSE|re.DOTALL|re.MULTILINE)
  52. re_match_type = re.compile(r"""
  53. TYPE\s+(\w+?)\s*=\s*((?:LIST|SET)\s*\[\d+:[\d?]+\]\s*OF)?(?:\s*UNIQUE)?\s*(\w+) # TYPE foo = LIST[1:2] of blub
  54. (?:(?<=ENUMERATION)\s*OF\s*\((.*?)\))?
  55. .*? # skip the WHERE clause
  56. END_TYPE;
  57. """,re.VERBOSE|re.DOTALL)
  58. re_match_field = re.compile(r"""
  59. \s+(\w+?)\s*:\s*(OPTIONAL)?\s*((?:LIST|SET)\s*\[\d+:[\d?]+\]\s*OF)?(?:\s*UNIQUE)?\s*(\w+?);
  60. """,re.VERBOSE|re.DOTALL)
  61. class Schema:
  62. def __init__(self):
  63. self.entities = {}
  64. self.types = {}
  65. class Entity:
  66. def __init__(self,name,parent,members):
  67. self.name = name
  68. self.parent = parent
  69. self.members = members
  70. class Field:
  71. def __init__(self,name,type,optional,collection):
  72. self.name = name
  73. self.type = type
  74. self.optional = optional
  75. self.collection = collection
  76. self.fullspec = (self.collection+' ' if self.collection else '') + self.type
  77. class Type:
  78. def __init__(self,name,aggregate,equals,enums):
  79. self.name = name
  80. self.aggregate = aggregate
  81. self.equals = equals
  82. self.enums = enums
  83. def read(filename,silent=False):
  84. schema = Schema()
  85. with open(filename,'rt') as inp:
  86. contents = inp.read()
  87. types = re.findall(re_match_type,contents)
  88. for name,aggregate,equals,enums in types:
  89. schema.types[name] = Type(name,aggregate,equals,enums)
  90. entities = re.findall(re_match_entity,contents)
  91. for name,parent,fields_raw in entities:
  92. print('process entity {0}, parent is {1}'.format(name,parent)) if not silent else None
  93. fields = re.findall(re_match_field,fields_raw)
  94. members = [Field(name,type,opt,coll) for name, opt, coll, type in fields]
  95. print(' got {0} fields'.format(len(members))) if not silent else None
  96. schema.entities[name] = Entity(name,parent,members)
  97. return schema
  98. if __name__ == "__main__":
  99. sys.exit(read(sys.argv[1] if len(sys.argv)>1 else 'schema.exp'))