Skip to content

Commit c31bc16

Browse files
committed
Try to better my life as a programmer, starting with more comments and documentation
1 parent cdbafac commit c31bc16

File tree

12 files changed

+81616
-1021
lines changed

12 files changed

+81616
-1021
lines changed

src/ifcexpressparser/DocAttribute.csv

Lines changed: 4891 additions & 0 deletions
Large diffs are not rendered by default.

src/ifcexpressparser/DocDefined.csv

Lines changed: 1860 additions & 0 deletions
Large diffs are not rendered by default.

src/ifcexpressparser/DocEntity.csv

Lines changed: 38069 additions & 0 deletions
Large diffs are not rendered by default.

src/ifcexpressparser/DocEntityAttributes.csv

Lines changed: 1655 additions & 0 deletions
Large diffs are not rendered by default.

src/ifcexpressparser/DocEnumeration.csv

Lines changed: 5951 additions & 0 deletions
Large diffs are not rendered by default.

src/ifcexpressparser/DocSelect.csv

Lines changed: 1015 additions & 0 deletions
Large diffs are not rendered by default.
Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
###############################################################################
2+
# #
3+
# This file is part of IfcOpenShell. #
4+
# #
5+
# IfcOpenShell is free software: you can redistribute it and/or modify #
6+
# it under the terms of the Lesser GNU General Public License as published by #
7+
# the Free Software Foundation, either version 3.0 of the License, or #
8+
# (at your option) any later version. #
9+
# #
10+
# IfcOpenShell is distributed in the hope that it will be useful, #
11+
# but WITHOUT ANY WARRANTY; without even the implied warranty of #
12+
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
13+
# Lesser GNU General Public License for more details. #
14+
# #
15+
# You should have received a copy of the Lesser GNU General Public License #
16+
# along with this program. If not, see <http://www.gnu.org/licenses/>. #
17+
# #
18+
###############################################################################
19+
20+
###############################################################################
21+
# #
22+
# This files uses the documentation files from buildingSMART to generate #
23+
# descriptions from EXPRESS names that are suitable for comments in the C++ #
24+
# code. The .csv files used by this file are generated from the MS Office #
25+
# Access database, which in turn has been generated from the IFC baseline #
26+
# documentation by the IFCDOC utility provided by buildingSMART. #
27+
# #
28+
###############################################################################
29+
30+
import re,csv
31+
import csv
32+
try: from html.entities import entitydefs
33+
except: from htmlentitydefs import entitydefs
34+
35+
name_to_oid = {}
36+
oid_to_desc = {}
37+
oid_to_name = {}
38+
oid_to_pid = {}
39+
regices = list(zip([re.compile(s,re.M) for s in [r'<[\w\n=" \-/\.;_\t:%#,\?\(\)]+>',r'(\n[\t ]*){2,}',r'^[\t ]+','^']],['','\n\n',' ','/// ']))
40+
41+
definition_files = ['DocEntity.csv', 'DocEnumeration.csv', 'DocDefined.csv', 'DocSelect.csv']
42+
for fn in definition_files:
43+
with open(fn) as f:
44+
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
45+
name_to_oid[name] = oid
46+
oid_to_name[oid] = name
47+
oid_to_desc[oid] = desc
48+
49+
with open('DocEntityAttributes.csv') as f:
50+
for pid, x, oid in csv.reader(f, delimiter=';', quotechar='"'):
51+
oid_to_pid[oid] = pid
52+
53+
with open('DocAttribute.csv') as f:
54+
for oid, name, desc in csv.reader(f, delimiter=';', quotechar='"'):
55+
pid = oid_to_pid[oid]
56+
pname = oid_to_name[pid]
57+
name_to_oid[(pname, name)] = oid
58+
oid_to_desc[oid] = desc
59+
60+
def description(item):
61+
global name_to_oid, oid_to_desc, oid_to_name, oid_to_pid
62+
oid = name_to_oid.get(item,0)
63+
desc = oid_to_desc.get(oid,None)
64+
if desc:
65+
for a,b in entitydefs.items(): desc = desc.replace("&%s;"%a,b)
66+
desc = desc.replace("\r","")
67+
for r,s in regices[:-1]: desc = r.sub(s,desc)
68+
desc = desc.strip()
69+
r,s = regices[-1]
70+
desc = r.sub(s,desc)
71+
return desc

src/ifcexpressparser/IfcExpressParser.py

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,8 @@
3434
###############################################################################
3535

3636
import os, sys
37+
import IfcDocumentation
38+
3739
filename = sys.argv[1]
3840

3941
#
@@ -160,12 +162,14 @@ def __init__(self,l):
160162
self.len = len(self.type)
161163
elif isinstance(self.type,SelectType): selections.add(self.name)
162164
simple_types.add(self.name)
165+
comment = IfcDocumentation.description(self.name)
166+
self.comment = comment+"\n" if comment else ''
163167
def __str__(self):
164168
global generator_mode
165169
if generator_mode == 'HEADER' and isinstance(self.type,EnumType):
166-
return ("namespace %(name)s {typedef %(type)s %(name)s;\nstd::string ToString(%(name)s v);\n%(name)s FromString(const std::string& s);}"%self.__dict__)%self.__dict__
170+
return ("namespace %(name)s {\n%(comment)stypedef %(type)s %(name)s;\nstd::string ToString(%(name)s v);\n%(name)s FromString(const std::string& s);\n}"%self.__dict__)%self.__dict__
167171
elif generator_mode == 'HEADER':
168-
return "typedef %s %s;"%(self.type,self.name)
172+
return "%stypedef %s %s;"%(self.comment,self.type,self.name)
169173
elif generator_mode == 'SOURCE' and isinstance(self.type,EnumType):
170174
generator_mode = 'SOURCE_TO'
171175
s = "std::string %(name)s::ToString(%(name)s v) {\n if ( v < 0 || v >= %(len)d ) throw IfcException(\"Unable to find find keyword in schema\");\n const char* names[] = %(type)s;\n return names[v];\n}\n"%self.__dict__
@@ -185,7 +189,7 @@ def __str__(self):
185189
s = ""
186190
argv = self.argstart
187191
for a in self.l:
188-
class_name = indent = ""
192+
class_name = indent = comment = optional_comment = ""
189193
return_type = str(a.type)
190194
if generator_mode == 'SOURCE':
191195
class_name = "%(class_name)s::"
@@ -204,13 +208,17 @@ def __str__(self):
204208
function_body2 = " { return !entity->getArgument(%d)->isNull(); }"%argv
205209
else:
206210
indent = " "
207-
function_body = function_body2 = ";"
208-
if a.optional: s += "\n%sbool %shas%s()%s"%(indent,class_name,a.name,function_body2)
211+
function_body = function_body2 = ";"
212+
comment = IfcDocumentation.description((self.class_name,a.name))
213+
comment = comment+"\n" if comment else ''
214+
comment = comment.replace("///","%s///"%indent)
215+
optional_comment = "%s/// Whether the optional attribute %s is defined for this %s\n"%(indent,a.name,self.class_name)
216+
if a.optional: s += "\n%s%sbool %shas%s()%s"%(optional_comment,indent,class_name,a.name,function_body2)
209217
if ( str(a.type) in enumerations ):
210218
return_type = "%(type)s::%(type)s"%a.__dict__
211219
elif ( str(a.type) in entity_names ):
212220
return_type = "%(type)s*"%a.__dict__
213-
s += "\n%s%s %s%s()%s"%(indent,return_type,class_name,a.name,function_body)
221+
s += "\n%s%s%s %s%s()%s"%(comment,indent,return_type,class_name,a.name,function_body)
214222
argv += 1
215223
return s
216224
class InverseList:
@@ -228,12 +236,15 @@ def __str__(self):
228236
class Classdef:
229237
def __init__(self,l):
230238
self.class_name, self.parent_class, self.arguments, self.inverse = l
239+
self.arguments.class_name = self.class_name
231240
entity_names.add(self.class_name)
232241
parent_relations[self.class_name] = self.parent_class
233242
argument_count[self.class_name] = len(self.arguments)
234243
def __str__(self):
235244
if generator_mode == 'HEADER':
236-
return "class %s : public %s {\npublic:%s%s%s\n};" % (self.class_name,
245+
comment = IfcDocumentation.description(self.class_name)
246+
comment = comment+"\n" if comment else ''
247+
return "%sclass %s : public %s {\npublic:%s%s%s\n};" % (comment,self.class_name,
237248
"IfcBaseClass" if self.parent_class is None else self.parent_class,
238249
self.arguments,
239250
self.inverse,
@@ -247,7 +258,7 @@ def __str__(self):
247258
)
248259
elif generator_mode == 'SOURCE':
249260
self.arguments.argstart = argument_start(self.class_name)
250-
return (("\n// %(class_name)s"+str(self.arguments)+str(self.inverse)+
261+
return (("\n// Function implementations for %(class_name)s"+str(self.arguments)+str(self.inverse)+
251262
("\nbool %(class_name)s::is(Type::Enum v) const { return v == Type::%(class_name)s; }" if self.parent_class is None else
252263
"\nbool %(class_name)s::is(Type::Enum v) const { return v == Type::%(class_name)s || %(parent_class)s::is(v); }")+
253264
"\nType::Enum %(class_name)s::type() const { return Type::%(class_name)s; }"+

0 commit comments

Comments
 (0)