#!/usr/bin/env python3
# -*- Coding: UTF-8 -*-

# ---------------------------------------------------------------------------
# Open Asset Import Library (ASSIMP)
# ---------------------------------------------------------------------------
#
# Copyright (c) 2006-2020, ASSIMP Development Team
#
# All rights reserved.
#
# Redistribution and use of this software in source and binary forms, 
# with or without modification, are permitted provided that the following 
# conditions are met:
# 
# * Redistributions of source code must retain the above
#   copyright notice, this list of conditions and the
#   following disclaimer.
# 
# * Redistributions in binary form must reproduce the above
#   copyright notice, this list of conditions and the
#   following disclaimer in the documentation and/or other
#   materials provided with the distribution.
# 
# * Neither the name of the ASSIMP team, nor the names of its
#   contributors may be used to endorse or promote products
#   derived from this software without specific prior
#   written permission of the ASSIMP Development Team.
# 
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# ---------------------------------------------------------------------------

"""Parse an EXPRESS file and extract basic information on all
entities and data types contained"""

import sys
import re
from collections import OrderedDict

re_match_entity = re.compile(r"""
ENTITY\s+(\w+)\s*                                    # 'ENTITY foo'
.*?                                                  #  skip SUPERTYPE-of
(?:SUBTYPE\s+OF\s+\((\w+)\))?;                       # 'SUBTYPE OF (bar);' or simply ';'
(.*?)                                                # 'a : atype;' (0 or more lines like this)
(?:(?:INVERSE|UNIQUE|WHERE)\s*$.*?)?                 #  skip the INVERSE, UNIQUE, WHERE clauses and everything behind 
END_ENTITY;                                          
""",re.VERBOSE|re.DOTALL|re.MULTILINE) 

re_match_type = re.compile(r"""
TYPE\s+(\w+?)\s*=\s*((?:LIST|SET)\s*\[\d+:[\d?]+\]\s*OF)?(?:\s*UNIQUE)?\s*(\w+)   # TYPE foo = LIST[1:2] of blub
(?:(?<=ENUMERATION)\s*OF\s*\((.*?)\))?
.*?                                                                 #  skip the WHERE clause
END_TYPE;
""",re.VERBOSE|re.DOTALL)

re_match_field = re.compile(r"""
\s+(\w+?)\s*:\s*(OPTIONAL)?\s*((?:LIST|SET)\s*\[\d+:[\d?]+\]\s*OF)?(?:\s*UNIQUE)?\s*(\w+?);
""",re.VERBOSE|re.DOTALL)


class Schema:
    def __init__(self):
        self.entities = OrderedDict()
        self.types = OrderedDict()

class Entity:
    def __init__(self,name,parent,members):
        self.name = name
        self.parent = parent
        self.members = members

class Field:
    def __init__(self,name,type,optional,collection):
        self.name = name
        self.type = type
        self.optional = optional
        self.collection = collection
        self.fullspec = (self.collection+' ' if self.collection else '') + self.type 

class Type:
    def __init__(self,name,aggregate,equals,enums):
        self.name = name
        self.aggregate = aggregate
        self.equals = equals
        self.enums = enums
        

def read(filename, silent=False):
    schema = Schema()
    print( "Try to read EXPRESS schema file" + filename)
    with open(filename,'rt') as inp: 
        contents = inp.read()
        types = re.findall(re_match_type,contents)
        for name,aggregate,equals,enums in types:
            schema.types[name] = Type(name,aggregate,equals,enums)
            
        entities = re.findall(re_match_entity,contents)
        for name,parent,fields_raw in entities:
            print('process entity {0}, parent is {1}'.format(name,parent)) if not silent else None
            fields = re.findall(re_match_field,fields_raw)
            members = [Field(name,type,opt,coll) for name, opt, coll, type in fields]
            print('  got {0} fields'.format(len(members))) if not silent else None
            
            schema.entities[name] = Entity(name,parent,members)
    return schema

if __name__ == "__main__":
    sys.exit(read(sys.argv[1] if len(sys.argv)>1 else 'schema.exp'))




    
