Merge remote-tracking branch 'origin/master' into hdf5

Conflicts:
	src/ifcexpressparser/bootstrap.py
	src/ifcexpressparser/templates.py
	src/ifcgeom/IfcGeomFaces.cpp
	src/ifcgeom/IfcGeomFunctions.cpp
	src/ifcgeom/IfcGeomIterator.h
	src/ifcgeom/IfcGeomWires.cpp
	src/ifcparse/Ifc2x3.h
	src/ifcparse/Ifc4.h
	src/ifcparse/IfcLateBoundEntity.cpp
	src/ifcparse/IfcParse.cpp
	src/ifcparse/IfcUtil.h
This commit is contained in:
aothms
2016-02-19 14:19:57 +01:00
100 changed files with 3560 additions and 1002 deletions
+3 -1
View File
@@ -4,6 +4,8 @@ the IFC schema and will most likely fail on any other Express schema.
The code can be invoked in the following way and results in two header files
and a single implementation file named according to the schema name in the
Express file. A python 3 interpreter with the pyparsing library is required.
Express file. A python 3 interpreter with the pyparsing [1] library is required.
$ python bootstrap.py express.bnf > express_parser.py && python express_parser.py IFC2X3_TC1.exp
[1] http://pyparsing.wikispaces.com/Download+and+Installation
+2
View File
@@ -196,4 +196,6 @@ implementation.Implementation(mapping).emit()
latebound_header.LateBoundHeader(mapping).emit()
latebound_implementation.LateBoundImplementation(mapping).emit()
schema_class.SchemaClass(mapping).emit()
sys.stdout.write(mapping.schema.name)
"""%('\n '.join(statements)))
+34
View File
@@ -0,0 +1,34 @@
###############################################################################
# #
# This file is part of IfcOpenShell. #
# #
# IfcOpenShell is free software: you can redistribute it and/or modify #
# it under the terms of the Lesser GNU General Public License as published by #
# the Free Software Foundation, either version 3.0 of the License, or #
# (at your option) any later version. #
# #
# IfcOpenShell is distributed in the hope that it will be useful, #
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
# Lesser GNU General Public License for more details. #
# #
# You should have received a copy of the Lesser GNU General Public License #
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
# #
###############################################################################
class Base(object):
"""
A base class for all code generation classes. Currently only working around
some python 2/3 incompatibilities in terms of unicode file handling.
"""
def emit(self):
import platform
if tuple(map(int, platform.python_version_tuple())) < (2, 8):
from io import open as unicode_open
else:
unicode_open = open
unicode = lambda x, *args, **kwargs: x
f = unicode_open(self.file_name, 'w', encoding='utf-8')
f.write(unicode(repr(self), encoding='utf-8', errors='ignore'))
f.close()
+8 -3
View File
@@ -27,11 +27,15 @@
# #
###############################################################################
import re,csv
import re
import os
import csv
try: from html.entities import entitydefs
except: from htmlentitydefs import entitydefs
make_absolute = lambda fn: os.path.join(os.path.dirname(os.path.realpath(__file__)), fn)
name_to_oid = {}
oid_to_desc = {}
oid_to_name = {}
@@ -39,6 +43,7 @@ oid_to_pid = {}
regices = list(zip([re.compile(s,re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>',r'(\n[\t ]*){2,}',r'^[\t ]+']],['','\n\n',' ']))
definition_files = ['DocEntity.csv', 'DocEnumeration.csv', 'DocDefined.csv', 'DocSelect.csv']
definition_files = map(make_absolute, definition_files)
for fn in definition_files:
with open(fn) as f:
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
@@ -46,11 +51,11 @@ for fn in definition_files:
oid_to_name[oid] = name
oid_to_desc[oid] = desc
with open('DocEntityAttributes.csv') as f:
with open(make_absolute('DocEntityAttributes.csv')) as f:
for pid, x, oid in csv.reader(f, delimiter=';', quotechar='"'):
oid_to_pid[oid] = pid
with open('DocAttribute.csv') as f:
with open(make_absolute('DocAttribute.csv')) as f:
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
pid = oid_to_pid[oid]
pname = oid_to_name[pid]
+6 -5
View File
@@ -18,8 +18,9 @@
###############################################################################
import templates
import codegen
class EnumHeader:
class EnumHeader(codegen.Base):
def __init__(self, mapping):
enumerable_types = sorted(set([name for name, type in mapping.schema.types.items()] + [name for name, type in mapping.schema.entities.items()]))
@@ -30,9 +31,9 @@ class EnumHeader:
}
self.schema_name = mapping.schema.name.capitalize()
self.file_name = '%senum.h'%self.schema_name
def __repr__(self):
return self.str
def emit(self):
f = open('%senum.h'%self.schema_name, 'w', encoding='utf-8')
f.write(str(self))
f.close()
+6 -6
View File
@@ -17,10 +17,11 @@
# #
###############################################################################
import codegen
import templates
import documentation
class Header:
class Header(codegen.Base):
def __init__(self, mapping):
declarations = []
@@ -123,10 +124,9 @@ class Header:
}
self.schema_name = mapping.schema.name.capitalize()
self.file_name = '%s.h'%self.schema_name
def __repr__(self):
return self.str
def emit(self):
f = open('%s.h'%self.schema_name, 'w', encoding='utf-8')
f.write(str(self))
f.close()
+6 -6
View File
@@ -17,9 +17,10 @@
# #
###############################################################################
import codegen
import templates
class Implementation:
class Implementation(codegen.Base):
def __init__(self, mapping):
enumeration_functions = []
entity_implementations = []
@@ -235,10 +236,9 @@ class Implementation:
}
self.schema_name = mapping.schema.name.capitalize()
self.file_name = '%s.cpp'%self.schema_name
def __repr__(self):
return self.str
def emit(self):
f = open('%s.cpp'%self.schema_name, 'w', encoding='utf-8')
f.write(str(self))
f.close()
+6 -5
View File
@@ -17,9 +17,10 @@
# #
###############################################################################
import codegen
import templates
class LateBoundHeader:
class LateBoundHeader(codegen.Base):
def __init__(self, mapping):
self.str = templates.lb_header % {
'schema_name_upper' : mapping.schema.name.upper(),
@@ -27,9 +28,9 @@ class LateBoundHeader:
}
self.schema_name = mapping.schema.name.capitalize()
self.file_name = '%s-latebound.h'%self.schema_name
def __repr__(self):
return self.str
def emit(self):
f = open('%s-latebound.h'%self.schema_name, 'w', encoding='utf-8')
f.write(str(self))
f.close()
@@ -17,9 +17,10 @@
# #
###############################################################################
import codegen
import templates
class LateBoundImplementation:
class LateBoundImplementation(codegen.Base):
def __init__(self, mapping):
schema_name = mapping.schema.name.capitalize()
@@ -110,10 +111,9 @@ class LateBoundImplementation:
}
self.schema_name = mapping.schema.name.capitalize()
self.file_name = '%s-latebound.cpp'%self.schema_name
def __repr__(self):
return self.str
def emit(self):
f = open('%s-latebound.cpp'%self.schema_name, 'w', encoding='utf-8')
f.write(str(self))
f.close()
+15 -13
View File
@@ -17,6 +17,8 @@
# #
###############################################################################
from __future__ import print_function
import sys
import nodes
import templates
@@ -33,11 +35,11 @@ class Mapping:
'binary' : 'boost::dynamic_bitset<>'
}
supported_argument_types = {
supported_argument_types = set([
'INT', 'BOOL', 'DOUBLE', 'STRING', 'BINARY', 'ENUMERATION', 'ENTITY_INSTANCE',
'AGGREGATE_OF_INT', 'AGGREGATE_OF_DOUBLE', 'AGGREGATE_OF_STRING', 'AGGREGATE_OF_BINARY', 'AGGREGATE_OF_ENTITY_INSTANCE',
'AGGREGATE_OF_AGGREGATE_OF_INT', 'AGGREGATE_OF_AGGREGATE_OF_DOUBLE', 'AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE',
}
])
def __init__(self, schema):
self.schema = schema
@@ -52,11 +54,11 @@ class Mapping:
def simple_type_parent(self, type):
parent = self.schema.types[type].type.type
if isinstance(parent, nodes.AggregationType): parent = None
return None if parent in self.express_to_cpp_typemapping else parent
return None if str(parent) in self.express_to_cpp_typemapping else parent
def make_type_string(self, type):
if isinstance(type, str):
return self.express_to_cpp_typemapping.get(type, type)
if isinstance(type, (str, nodes.BinaryType)):
return self.express_to_cpp_typemapping.get(str(type), type)
else:
is_list = self.schema.is_entity(type.type)
is_nested_list = isinstance(type.type, nodes.AggregationType)
@@ -83,12 +85,8 @@ class Mapping:
def make_argument_type(self, attr):
def _make_argument_type(type):
if type in self.express_to_cpp_typemapping:
return self.express_to_cpp_typemapping.get(type, type).split('::')[-1].upper()
elif self.schema.is_entity(type) or isinstance(type, nodes.SelectType):
if self.schema.is_entity(type) or isinstance(type, nodes.SelectType):
return "ENTITY_INSTANCE"
elif self.schema.is_type(type):
return _make_argument_type(self.schema.types[type].type.type)
elif isinstance(type, nodes.BinaryType):
return "BINARY"
elif isinstance(type, nodes.EnumerationType):
@@ -97,17 +95,21 @@ class Mapping:
ty = _make_argument_type(type.type)
if ty == "UNKNOWN": return "UNKNOWN"
return "AGGREGATE_OF_" + ty
elif str(type) in self.express_to_cpp_typemapping:
return self.express_to_cpp_typemapping.get(str(type), type).split('::')[-1].upper()
elif self.schema.is_type(type):
return _make_argument_type(self.schema.types[type].type.type)
else:
raise ValueError("Unable to map type %r for attribute %r" % (type, attr))
ty = _make_argument_type(attr.type if hasattr(attr, 'type') else attr)
if ty not in self.supported_argument_types:
print("Attribute %r mapped as 'unknown'" % (type, attr), file=sys.stderr)
print("Attribute %r mapped as 'unknown'" % (attr), file=sys.stderr)
ty = 'UNKNOWN'
return "IfcUtil::Argument_%s" % ty
def get_type_dep(self, type):
if isinstance(type, str):
return self.express_to_cpp_typemapping.get(type, type)
return self.express_to_cpp_typemapping.get(str(type), type)
else:
return self.get_type_dep(type.type)
@@ -124,7 +126,7 @@ class Mapping:
ty = self.get_parameter_type(attr_type.type if is_nested_list else attr_type, False, allow_entities, False)
if self.schema.is_select(attr_type.type):
type_str = templates.untyped_list
elif self.schema.is_simpletype(ty) or ty in self.express_to_cpp_typemapping.values():
elif self.schema.is_simpletype(ty) or str(ty) in self.express_to_cpp_typemapping.values():
tmpl = templates.nested_array_type if is_nested_list else templates.array_type
type_str = tmpl % {
'instance_type' : ty,
+15 -10
View File
@@ -18,29 +18,34 @@
###############################################################################
import nodes
import platform
import collections
if tuple(map(int, platform.python_version_tuple())) < (2, 7):
import ordereddict
collections.OrderedDict = ordereddict.OrderedDict
class Schema:
def is_enumeration(self, v):
return v in self.enumerations
return str(v) in self.enumerations
def is_select(self, v):
return v in self.selects
return str(v) in self.selects
def is_simpletype(self, v):
return v in self.simpletypes
return str(v) in self.simpletypes
def is_type(self, v):
return v in self.types
return str(v) in self.types
def is_entity(self, v):
return v in self.entities
return str(v) in self.entities
def __init__(self, parsetree):
self.name = parsetree[1]
sort = lambda d: collections.OrderedDict(sorted(d.items()))
sort = lambda d: collections.OrderedDict(sorted(d))
self.types = sort({t.name:t for t in parsetree if isinstance(t, nodes.TypeDeclaration)})
self.entities = sort({t.name:t for t in parsetree if isinstance(t, nodes.EntityDeclaration)})
self.types = sort([(t.name,t) for t in parsetree if isinstance(t, nodes.TypeDeclaration)])
self.entities = sort([(t.name,t) for t in parsetree if isinstance(t, nodes.EntityDeclaration)])
of_type = lambda *types: sort({a: b.type.type for a,b in self.types.items() if any(isinstance(b.type.type, ty) for ty in types)})
of_type = lambda *types: sort([(a, b.type.type) for a,b in self.types.items() if any(isinstance(b.type.type, ty) for ty in types)])
self.enumerations = of_type(nodes.EnumerationType)
self.selects = of_type(nodes.SelectType)
self.simpletypes = of_type(str, nodes.AggregationType)
self.simpletypes = of_type(str, nodes.AggregationType, nodes.BinaryType)
+36 -26
View File
@@ -23,7 +23,6 @@ header = """
#include <string>
#include <vector>
#include <map>
#include <boost/optional.hpp>
@@ -34,6 +33,11 @@ header = """
const IfcParse::schema_definition& get_schema();
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4100)
#endif
#define IfcSchema %(schema_name)s
namespace %(schema_name)s {
@@ -50,6 +54,10 @@ void InitStringMap();
IfcUtil::IfcBaseClass* SchemaEntity(IfcAbstractEntity* e = 0);
}
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#endif
"""
@@ -111,6 +119,8 @@ implementation= """
#include "../ifcparse/IfcWrite.h"
#include "../ifcparse/IfcWritableEntity.h"
#include <map>
using namespace %(schema_name)s;
using namespace IfcParse;
using namespace IfcWrite;
@@ -268,49 +278,49 @@ std::pair<const char*, int> Type::GetEnumerationIndex(Enum t, const std::string&
}
std::pair<Type::Enum, unsigned> Type::GetInverseAttribute(Enum t, const std::string& a) {
if (inverse_map.empty()) ::InitInverseMap();
inverse_map_t::const_iterator it;
inverse_map_t::mapped_type::const_iterator jt;
while (true) {
if (inverse_map.empty()) ::InitInverseMap();
inverse_map_t::const_iterator it;
inverse_map_t::mapped_type::const_iterator jt;
for(;;) {
it = inverse_map.find(t);
if (it != inverse_map.end()) {
jt = it->second.find(a);
if (jt != it->second.end()) {
return jt->second;
}
}
jt = it->second.find(a);
if (jt != it->second.end()) {
return jt->second;
}
}
if ((t = Parent(t)) == -1) break;
}
throw IfcException("Attribute not found");
}
std::set<std::string> Type::GetInverseAttributeNames(Enum t) {
if (inverse_map.empty()) ::InitInverseMap();
inverse_map_t::const_iterator it;
inverse_map_t::mapped_type::const_iterator jt;
if (inverse_map.empty()) ::InitInverseMap();
inverse_map_t::const_iterator it;
inverse_map_t::mapped_type::const_iterator jt;
std::set<std::string> return_value;
std::set<std::string> return_value;
while (true) {
for (;;) {
it = inverse_map.find(t);
if (it != inverse_map.end()) {
for (jt = it->second.begin(); jt != it->second.end(); ++jt) {
return_value.insert(jt->first);
}
}
for (jt = it->second.begin(); jt != it->second.end(); ++jt) {
return_value.insert(jt->first);
}
}
if ((t = Parent(t)) == -1) break;
}
return return_value;
return return_value;
}
void Type::PopulateDerivedFields(IfcWrite::IfcWritableEntity* e) {
std::map<Type::Enum, std::set<int> >::const_iterator i = derived_map.find(e->type());
if (i != derived_map.end()) {
for (std::set<int>::const_iterator it = i->second.begin(); it != i->second.end(); ++it) {
e->setArgumentDerived(*it);
}
}
if (i != derived_map.end()) {
for (std::set<int>::const_iterator it = i->second.begin(); it != i->second.end(); ++it) {
e->setArgumentDerived(*it);
}
}
}
"""