PyVRML97 2.3.4b3__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- pyvrml97-2.3.4b3.dist-info/METADATA +65 -0
- pyvrml97-2.3.4b3.dist-info/RECORD +39 -0
- pyvrml97-2.3.4b3.dist-info/WHEEL +5 -0
- pyvrml97-2.3.4b3.dist-info/top_level.txt +1 -0
- vrml/__init__.py +22 -0
- vrml/_bytes.py +85 -0
- vrml/arrays.py +86 -0
- vrml/cache.py +250 -0
- vrml/copier.py +27 -0
- vrml/csscolors.py +177 -0
- vrml/event.py +24 -0
- vrml/field.py +476 -0
- vrml/fieldtypes.py +1491 -0
- vrml/node.py +569 -0
- vrml/nodepath.py +70 -0
- vrml/olist.py +126 -0
- vrml/protofunctions.py +233 -0
- vrml/protonamespace.py +13 -0
- vrml/route.py +167 -0
- vrml/vrml200x/__init__.py +0 -0
- vrml/vrml200x/parser.py +87 -0
- vrml/vrml97/__init__.py +6 -0
- vrml/vrml97/_transformmatrix.py +133 -0
- vrml/vrml97/_transformmatrix_accel.py +63 -0
- vrml/vrml97/basenamespaces.py +28 -0
- vrml/vrml97/basenodes.py +648 -0
- vrml/vrml97/linearise.py +579 -0
- vrml/vrml97/nodepath.py +135 -0
- vrml/vrml97/nodetypes.py +95 -0
- vrml/vrml97/nurbs.py +79 -0
- vrml/vrml97/parseprocessor.py +452 -0
- vrml/vrml97/parser.py +72 -0
- vrml/vrml97/scenegraph.py +181 -0
- vrml/vrml97/script.py +25 -0
- vrml/vrml97/shaders.py +123 -0
- vrml/vrml97/transformmatrix.py +193 -0
- vrml/weakkeydictfix.py +36 -0
- vrml/weaklist.py +163 -0
- vrml/weaktuple.py +138 -0
|
@@ -0,0 +1,452 @@
|
|
|
1
|
+
"""SimpleParse post-processor builds node-graph from parse-tree
|
|
2
|
+
"""
|
|
3
|
+
|
|
4
|
+
from simpleparse.dispatchprocessor import *
|
|
5
|
+
from vrml import node, field
|
|
6
|
+
from vrml.protofunctions import *
|
|
7
|
+
from vrml.arrays import array
|
|
8
|
+
from .._bytes import as_str
|
|
9
|
+
|
|
10
|
+
try:
|
|
11
|
+
long
|
|
12
|
+
except NameError:
|
|
13
|
+
long = int
|
|
14
|
+
_getString = getString
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
def getString(*args, **named):
|
|
18
|
+
base = _getString(*args, **named)
|
|
19
|
+
return as_str(base)
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class ParseProcessor(DispatchProcessor):
|
|
23
|
+
"""Builds in-memory node-graph from VRML97 parse-tree"""
|
|
24
|
+
|
|
25
|
+
def __init__(self, basePrototypes=None, baseURI=""):
|
|
26
|
+
"""Initialise the ParseProcessor
|
|
27
|
+
|
|
28
|
+
basePrototypes -- name: constructor mapping for all
|
|
29
|
+
prototypes to be built by the processor. Should
|
|
30
|
+
include at least:
|
|
31
|
+
|
|
32
|
+
* Script
|
|
33
|
+
* PROTO
|
|
34
|
+
* NULL
|
|
35
|
+
* sceneGraph
|
|
36
|
+
* ROUTE
|
|
37
|
+
|
|
38
|
+
as those "node" types are used during the
|
|
39
|
+
building process. You must also include any
|
|
40
|
+
built-in node types which you want recognised
|
|
41
|
+
without needing a prototype declaration.
|
|
42
|
+
|
|
43
|
+
If None, will use:
|
|
44
|
+
vrml.vrml97.basenamespaces.basePrototypes
|
|
45
|
+
|
|
46
|
+
"""
|
|
47
|
+
self.position = 0
|
|
48
|
+
if basePrototypes is None:
|
|
49
|
+
from vrml.vrml97 import basenamespaces
|
|
50
|
+
|
|
51
|
+
basePrototypes = basenamespaces.basePrototypes.copy()
|
|
52
|
+
self.basePrototypes = basePrototypes
|
|
53
|
+
self.baseURI = baseURI
|
|
54
|
+
self.sceneGraphStack = []
|
|
55
|
+
self.prototypeStack = []
|
|
56
|
+
self.nodeStack = []
|
|
57
|
+
self.fieldTypeStack = []
|
|
58
|
+
|
|
59
|
+
### High-level constructs in the grammar
|
|
60
|
+
def header(self, table, buffer):
|
|
61
|
+
"""We ignore the header for now"""
|
|
62
|
+
|
|
63
|
+
EOF = header
|
|
64
|
+
|
|
65
|
+
def rootItem(self, table, buffer):
|
|
66
|
+
"""A scenegraph root-item"""
|
|
67
|
+
(tag, left, right, children) = table
|
|
68
|
+
# ROUTE and proto are already taken care of, as would be is
|
|
69
|
+
# so we only need to worry about USE, Script and Node types
|
|
70
|
+
items = dispatchList(self, children, buffer)
|
|
71
|
+
result = [item for item in items if isinstance(item, node.Node)]
|
|
72
|
+
self.sceneGraphStack[-1].children.extend(result)
|
|
73
|
+
|
|
74
|
+
def vrmlScene(self, table, buffer):
|
|
75
|
+
"""Instantiate a VRML scene object"""
|
|
76
|
+
(tag, left, right, children) = table
|
|
77
|
+
if self.sceneGraphStack:
|
|
78
|
+
root = self.sceneGraphStack[-1]
|
|
79
|
+
protoTypes = None
|
|
80
|
+
else:
|
|
81
|
+
root = None
|
|
82
|
+
protoTypes = self.basePrototypes
|
|
83
|
+
self.sceneGraphStack.append(
|
|
84
|
+
self.basePrototypes.get('sceneGraph')(
|
|
85
|
+
root=root,
|
|
86
|
+
protoTypes=protoTypes,
|
|
87
|
+
baseURI=self.baseURI,
|
|
88
|
+
)
|
|
89
|
+
)
|
|
90
|
+
dispatchList(self, children, buffer)
|
|
91
|
+
node = self.sceneGraphStack.pop()
|
|
92
|
+
return node
|
|
93
|
+
|
|
94
|
+
### The two prototype sub-types
|
|
95
|
+
def Proto(self, table, buffer):
|
|
96
|
+
"""Process a regular Prototype declaration"""
|
|
97
|
+
(tag, left, right, children) = table
|
|
98
|
+
proto = node.prototype(getString(children[0], buffer))
|
|
99
|
+
self.prototypeStack.append(proto)
|
|
100
|
+
try:
|
|
101
|
+
dispatchList(self, children[1:-1], buffer)
|
|
102
|
+
setSceneGraph(proto, dispatch(self, children[-1], buffer))
|
|
103
|
+
self.sceneGraphStack[-1].addProto(proto)
|
|
104
|
+
finally:
|
|
105
|
+
self.prototypeStack.pop()
|
|
106
|
+
|
|
107
|
+
def ExternProto(self, table, buffer):
|
|
108
|
+
"""Process an external Prototype declaration"""
|
|
109
|
+
(tag, left, right, children) = table
|
|
110
|
+
proto = node.prototype(getString(children[0], buffer))
|
|
111
|
+
self.prototypeStack.append(proto)
|
|
112
|
+
try:
|
|
113
|
+
dispatchList(self, children[1:-1], buffer)
|
|
114
|
+
setExternalURL(proto, dispatch(self, children[-1], buffer))
|
|
115
|
+
self.sceneGraphStack[-1].addProto(proto)
|
|
116
|
+
finally:
|
|
117
|
+
self.prototypeStack.pop()
|
|
118
|
+
|
|
119
|
+
### Node instances of the various types
|
|
120
|
+
def Node(self, table, buffer):
|
|
121
|
+
'''Create new node, returning the value to the caller'''
|
|
122
|
+
(tag, start, stop, sublist) = table
|
|
123
|
+
if sublist[0][0] == 'name':
|
|
124
|
+
name = getString(sublist[0], buffer)
|
|
125
|
+
GI = getString(sublist[1], buffer)
|
|
126
|
+
rest = sublist[2:]
|
|
127
|
+
else:
|
|
128
|
+
name = ""
|
|
129
|
+
GI = getString(sublist[0], buffer)
|
|
130
|
+
rest = sublist[1:]
|
|
131
|
+
prototype = self.sceneGraphStack[-1].getProto(GI)
|
|
132
|
+
if prototype is None:
|
|
133
|
+
raise NameError(
|
|
134
|
+
"""Prototype %s used without declaration on line %s"""
|
|
135
|
+
% (
|
|
136
|
+
GI,
|
|
137
|
+
lines(end=start, buffer=buffer),
|
|
138
|
+
)
|
|
139
|
+
)
|
|
140
|
+
newNode = prototype()
|
|
141
|
+
root(newNode, self.sceneGraphStack[0])
|
|
142
|
+
if name:
|
|
143
|
+
self.sceneGraphStack[-1].regDefName(name, newNode)
|
|
144
|
+
self.nodeStack.append(newNode)
|
|
145
|
+
dispatchList(self, rest, buffer)
|
|
146
|
+
self.nodeStack.pop()
|
|
147
|
+
return newNode
|
|
148
|
+
|
|
149
|
+
def Script(self, table, buffer):
|
|
150
|
+
'''A script node (can be a root node)'''
|
|
151
|
+
(tag, start, stop, sublist) = table
|
|
152
|
+
# what's the DEF name...
|
|
153
|
+
if sublist and sublist[0][0] == 'name':
|
|
154
|
+
name = getString(sublist[0], buffer)
|
|
155
|
+
rest = sublist[1:]
|
|
156
|
+
else:
|
|
157
|
+
name = ""
|
|
158
|
+
rest = sublist
|
|
159
|
+
# build the node, with dummy fields
|
|
160
|
+
newNode = self.basePrototypes.get('Script')(
|
|
161
|
+
(),
|
|
162
|
+
)
|
|
163
|
+
vProto = newNode.__class__
|
|
164
|
+
# register it
|
|
165
|
+
root(newNode, self.sceneGraphStack[0])
|
|
166
|
+
if name:
|
|
167
|
+
self.sceneGraphStack[-1].regDefName(name, newNode)
|
|
168
|
+
self.nodeStack.append(newNode)
|
|
169
|
+
# now get the field-declarations...
|
|
170
|
+
fields, attributes, isMaps = [], [], []
|
|
171
|
+
for item in rest:
|
|
172
|
+
if item[0] in ("ScriptEventDecl", "ScriptFieldDecl"):
|
|
173
|
+
f, mapName = dispatch(self, item, buffer)
|
|
174
|
+
setattr(vProto, f.name, f)
|
|
175
|
+
if mapName is not None:
|
|
176
|
+
isMaps.append((mapName, f.name))
|
|
177
|
+
elif item[0] == 'Attr':
|
|
178
|
+
attributes.append(item)
|
|
179
|
+
else:
|
|
180
|
+
dispatch(self, item, buffer)
|
|
181
|
+
if isMaps:
|
|
182
|
+
set = node.ismaps(self.prototypeStack[-1])
|
|
183
|
+
for name, field in isMaps:
|
|
184
|
+
set.setdefault(name, []).append((newNode, field))
|
|
185
|
+
dispatchList(self, attributes, buffer)
|
|
186
|
+
self.nodeStack.pop()
|
|
187
|
+
return newNode
|
|
188
|
+
|
|
189
|
+
def SFNull(self, tup, buffer):
|
|
190
|
+
'''Create a reference to the SFNull node'''
|
|
191
|
+
return self.sceneGraphStack[-1].getProto("NULL")
|
|
192
|
+
|
|
193
|
+
def USE(self, tup, buffer):
|
|
194
|
+
"""Create a reference to an existing named node"""
|
|
195
|
+
name = getString(tup, buffer)
|
|
196
|
+
node = self.sceneGraphStack[-1].getDEF(name)
|
|
197
|
+
if node is None:
|
|
198
|
+
raise NameError(
|
|
199
|
+
"""Use of un-DEF'd name %s on line %s"""
|
|
200
|
+
% (
|
|
201
|
+
name,
|
|
202
|
+
lines(end=tup[1], buffer=buffer),
|
|
203
|
+
)
|
|
204
|
+
)
|
|
205
|
+
return node
|
|
206
|
+
|
|
207
|
+
def ROUTE(self, table, buffer):
|
|
208
|
+
'''Create a new route object/node, add the current sceneGraph'''
|
|
209
|
+
(tag, start, stop, sublist) = table
|
|
210
|
+
(s, sf, d, df) = [getString(item, buffer) for item in sublist]
|
|
211
|
+
(sn, dn) = [self.sceneGraphStack[-1].getDEF(name) for name in (s, d)]
|
|
212
|
+
for node, name in ((sn, s), (dn, d)):
|
|
213
|
+
if node is None:
|
|
214
|
+
raise NameError(
|
|
215
|
+
"""ROUTE of un-DEF'd name %s on line %s"""
|
|
216
|
+
% (
|
|
217
|
+
name,
|
|
218
|
+
lines(end=start, buffer=buffer),
|
|
219
|
+
)
|
|
220
|
+
)
|
|
221
|
+
self.sceneGraphStack[-1].addRoute(
|
|
222
|
+
self.basePrototypes.get('ROUTE')(
|
|
223
|
+
source=sn,
|
|
224
|
+
sourceField=sf,
|
|
225
|
+
destination=dn,
|
|
226
|
+
destinationField=df,
|
|
227
|
+
)
|
|
228
|
+
)
|
|
229
|
+
|
|
230
|
+
### Field and event declarations
|
|
231
|
+
def fieldDecl(self, table, buffer):
|
|
232
|
+
(tag, left, right, (exposure, datatype, name, value)) = table
|
|
233
|
+
datatype = getString(datatype, buffer)
|
|
234
|
+
self.fieldTypeStack.append(datatype)
|
|
235
|
+
try:
|
|
236
|
+
value = dispatch(self, value, buffer)
|
|
237
|
+
addField(
|
|
238
|
+
self.prototypeStack[-1],
|
|
239
|
+
field.newField(
|
|
240
|
+
getString(name, buffer),
|
|
241
|
+
datatype,
|
|
242
|
+
getString(exposure, buffer) == 'exposedField',
|
|
243
|
+
value,
|
|
244
|
+
),
|
|
245
|
+
)
|
|
246
|
+
finally:
|
|
247
|
+
self.fieldTypeStack.pop()
|
|
248
|
+
|
|
249
|
+
def extFieldDecl(self, table, buffer):
|
|
250
|
+
'''An external field declaration, no default value'''
|
|
251
|
+
(tag, start, stop, (exposure, datatype, name)) = table
|
|
252
|
+
datatype = getString(datatype, buffer)
|
|
253
|
+
addField(
|
|
254
|
+
self.prototypeStack[-1],
|
|
255
|
+
field.newField(
|
|
256
|
+
getString(name, buffer),
|
|
257
|
+
datatype,
|
|
258
|
+
getString(exposure, buffer) == 'exposedField',
|
|
259
|
+
),
|
|
260
|
+
)
|
|
261
|
+
|
|
262
|
+
def eventDecl(self, table, buffer):
|
|
263
|
+
(tag, left, right, (direction, datatype, name)) = table
|
|
264
|
+
datatype = getString(datatype, buffer)
|
|
265
|
+
addField(
|
|
266
|
+
self.prototypeStack[-1],
|
|
267
|
+
field.newEvent(
|
|
268
|
+
getString(name, buffer),
|
|
269
|
+
datatype,
|
|
270
|
+
getString(direction, buffer) == 'eventOut',
|
|
271
|
+
),
|
|
272
|
+
)
|
|
273
|
+
|
|
274
|
+
def ScriptEventDecl(self, table, buffer):
|
|
275
|
+
(tag, left, right, sublist) = table
|
|
276
|
+
direction, datatype, name = [getString(item, buffer) for item in sublist[:3]]
|
|
277
|
+
if len(sublist) > 3:
|
|
278
|
+
mapName = dispatch(self, sublist[3], buffer)
|
|
279
|
+
else:
|
|
280
|
+
mapName = None
|
|
281
|
+
return (
|
|
282
|
+
field.newEvent(name, datatype, direction == 'eventOut'),
|
|
283
|
+
mapName,
|
|
284
|
+
)
|
|
285
|
+
|
|
286
|
+
def ScriptFieldDecl(self, table, buffer):
|
|
287
|
+
"""Field declaration for a script node"""
|
|
288
|
+
(tag, left, right, (exposure, datatype, name, value)) = table
|
|
289
|
+
datatype = getString(datatype, buffer)
|
|
290
|
+
self.fieldTypeStack.append(datatype)
|
|
291
|
+
try:
|
|
292
|
+
if value[0] == 'IS':
|
|
293
|
+
mapName = self.IS(value, buffer)
|
|
294
|
+
value = None
|
|
295
|
+
fieldObject = field.newField(
|
|
296
|
+
getString(name, buffer),
|
|
297
|
+
datatype,
|
|
298
|
+
getString(exposure, buffer) == 'exposedField',
|
|
299
|
+
)
|
|
300
|
+
else:
|
|
301
|
+
mapName = None
|
|
302
|
+
value = dispatch(self, value, buffer)
|
|
303
|
+
fieldObject = field.newField(
|
|
304
|
+
getString(name, buffer),
|
|
305
|
+
datatype,
|
|
306
|
+
getString(exposure, buffer) == 'exposedField',
|
|
307
|
+
value,
|
|
308
|
+
)
|
|
309
|
+
return (fieldObject, mapName)
|
|
310
|
+
finally:
|
|
311
|
+
self.fieldTypeStack.pop()
|
|
312
|
+
|
|
313
|
+
### Node attributes and field values
|
|
314
|
+
def Attr(self, table, buffer):
|
|
315
|
+
'''An attribute of a node or script'''
|
|
316
|
+
(tag, start, stop, (name, value)) = table
|
|
317
|
+
name = getString(name, buffer)
|
|
318
|
+
clientNode = self.nodeStack[-1]
|
|
319
|
+
try:
|
|
320
|
+
field = getField(clientNode, name)
|
|
321
|
+
except AttributeError:
|
|
322
|
+
raise AttributeError(
|
|
323
|
+
"""Unknown field name %s for node type %s on line %s"""
|
|
324
|
+
% (
|
|
325
|
+
name,
|
|
326
|
+
protoName(clientNode),
|
|
327
|
+
lines(end=start, buffer=buffer),
|
|
328
|
+
)
|
|
329
|
+
)
|
|
330
|
+
if value[0] == 'IS':
|
|
331
|
+
mapName = dispatch(self, value, buffer)
|
|
332
|
+
set = node.ismaps(self.prototypeStack[-1])
|
|
333
|
+
set.setdefault(mapName, []).append((clientNode, name))
|
|
334
|
+
else:
|
|
335
|
+
self.fieldTypeStack.append(field.typeName())
|
|
336
|
+
try:
|
|
337
|
+
value = dispatch(self, value, buffer)
|
|
338
|
+
if isinstance(clientNode, node.PrototypedNode):
|
|
339
|
+
# prototyped nodes get IS-value updates
|
|
340
|
+
field.fset(clientNode, value, notify=1)
|
|
341
|
+
else:
|
|
342
|
+
field.fset(clientNode, value, notify=0)
|
|
343
|
+
finally:
|
|
344
|
+
self.fieldTypeStack.pop()
|
|
345
|
+
|
|
346
|
+
def Field(self, table, buffer):
|
|
347
|
+
'''A field value (of any type)'''
|
|
348
|
+
(tag, start, stop, sublist) = table
|
|
349
|
+
if sublist and sublist[0][0] in ('USE', 'Script', 'Node', 'SFNull'):
|
|
350
|
+
if self.fieldTypeStack[-1] == 'SFNode':
|
|
351
|
+
return dispatch(self, sublist[0], buffer)
|
|
352
|
+
else:
|
|
353
|
+
return dispatchList(self, sublist, buffer)
|
|
354
|
+
elif self.fieldTypeStack[-1] == 'MFNode':
|
|
355
|
+
return []
|
|
356
|
+
else:
|
|
357
|
+
# is a simple data type...
|
|
358
|
+
function = getattr(self, self.fieldTypeStack[-1])
|
|
359
|
+
return function(sublist, buffer)
|
|
360
|
+
|
|
361
|
+
def SFBool(self, table, buffer):
|
|
362
|
+
'''Boolean, in Python tradition is either 0 or 1'''
|
|
363
|
+
(tup,) = table
|
|
364
|
+
return getString(tup, buffer) == 'TRUE'
|
|
365
|
+
|
|
366
|
+
def SFFloat(self, table, buffer):
|
|
367
|
+
(tup,) = table
|
|
368
|
+
return float(getString(tup, buffer))
|
|
369
|
+
|
|
370
|
+
SFTime = SFFloat
|
|
371
|
+
|
|
372
|
+
def SFInt32(self, table, buffer):
|
|
373
|
+
(tup,) = table
|
|
374
|
+
return int(getString(tup, buffer), 0)
|
|
375
|
+
|
|
376
|
+
def SFVec3f(self, table, buffer):
|
|
377
|
+
return [float(getString(item, buffer)) for item in table]
|
|
378
|
+
|
|
379
|
+
def SFVec2f(self, table, buffer):
|
|
380
|
+
return [float(getString(item, buffer)) for item in table]
|
|
381
|
+
|
|
382
|
+
SFColor = SFVec3f
|
|
383
|
+
|
|
384
|
+
def SFRotation(self, table, buffer):
|
|
385
|
+
return [float(getString(item, buffer)) for item in table]
|
|
386
|
+
|
|
387
|
+
def SFArray(self, values, buffer, final=True):
|
|
388
|
+
"""Process a vector-of-values data-set"""
|
|
389
|
+
result = []
|
|
390
|
+
for tag, start, stop, children in values:
|
|
391
|
+
if tag == 'vector':
|
|
392
|
+
result.append(self.SFArray(children, buffer, final=False))
|
|
393
|
+
else:
|
|
394
|
+
result.append(float(buffer[start:stop]))
|
|
395
|
+
if final:
|
|
396
|
+
result = array(result, 'f')
|
|
397
|
+
return result
|
|
398
|
+
|
|
399
|
+
def MFInt32(self, tuples, buffer):
|
|
400
|
+
# localisation
|
|
401
|
+
if not tuples:
|
|
402
|
+
return []
|
|
403
|
+
return [int(buffer[start:stop], 0) for (tag, start, stop, children) in tuples]
|
|
404
|
+
|
|
405
|
+
SFImage = MFInt32
|
|
406
|
+
|
|
407
|
+
def MFUInt32(self, tuples, buffer):
|
|
408
|
+
# localisation
|
|
409
|
+
return [long(buffer[start:stop], 0) for (tag, start, stop, children) in tuples]
|
|
410
|
+
|
|
411
|
+
def MFFloat(self, tuples, buffer):
|
|
412
|
+
return [float(buffer[start:stop]) for (tag, start, stop, children) in tuples]
|
|
413
|
+
|
|
414
|
+
MFColor = MFRotation = MFVec2f = MFVec3f = MFTime = MFFloat32 = MFFloat
|
|
415
|
+
|
|
416
|
+
def MFString(self, tuples, buffer):
|
|
417
|
+
bigresult = []
|
|
418
|
+
for tag, start, stop, sublist in tuples:
|
|
419
|
+
result = []
|
|
420
|
+
for element in sublist:
|
|
421
|
+
if element[0] == 'CHARNODBLQUOTE':
|
|
422
|
+
result.append(as_str(buffer[element[1] : element[2]]))
|
|
423
|
+
elif element[0] == 'ESCAPEDCHAR':
|
|
424
|
+
result.append(as_str(buffer[element[1] + 1 : element[2]]))
|
|
425
|
+
elif element[0] == 'SIMPLEBACKSLASH':
|
|
426
|
+
result.append('\\')
|
|
427
|
+
bigresult.append("".join(result))
|
|
428
|
+
return bigresult
|
|
429
|
+
|
|
430
|
+
def SFString(self, table, buffer):
|
|
431
|
+
'''Return the (escaped) string as a simple Python string'''
|
|
432
|
+
((tag, start, stop, sublist),) = table
|
|
433
|
+
result = []
|
|
434
|
+
for element in sublist:
|
|
435
|
+
if element[0] == 'CHARNODBLQUOTE':
|
|
436
|
+
result.append(as_str(buffer[element[1] : element[2]]))
|
|
437
|
+
elif element[0] == 'ESCAPEDCHAR':
|
|
438
|
+
result.append(as_str(buffer[element[1] + 1 : element[2]]))
|
|
439
|
+
elif element[0] == 'SIMPLEBACKSLASH':
|
|
440
|
+
result.append(as_str('\\'))
|
|
441
|
+
return "".join(result)
|
|
442
|
+
|
|
443
|
+
### Low-level/trivial constructs which have their own processing functions
|
|
444
|
+
def IS(self, table, buffer):
|
|
445
|
+
'''Create a field reference'''
|
|
446
|
+
(tag, start, stop, (nametuple,)) = table
|
|
447
|
+
return getString(nametuple, buffer)
|
|
448
|
+
|
|
449
|
+
def ExtProtoURL(self, table, buffer):
|
|
450
|
+
'''add the url to the external prototype'''
|
|
451
|
+
(tag, start, stop, sublist) = table
|
|
452
|
+
return self.MFString(sublist, buffer)
|
vrml/vrml97/parser.py
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
"""VRML97-compliant SimpleParse 2.0 Parser
|
|
2
|
+
|
|
3
|
+
This example is a full VRML97 parser, originally created
|
|
4
|
+
for the mcf.vrml VRML-processing system. It supports all
|
|
5
|
+
VRML97 constructs, and should be correct for any VRML97
|
|
6
|
+
content you can produce. The parser is fairly fast
|
|
7
|
+
(parsing around 280,000 cps on a 1GHz Athlon machine).
|
|
8
|
+
|
|
9
|
+
This is the errorOnFail version of the grammar, otherwise
|
|
10
|
+
identical to the vrml.py module. Note: there is basically
|
|
11
|
+
no speed penalty for the errorOnFail version compared to
|
|
12
|
+
the original version, as the errorOnFail code is not touched
|
|
13
|
+
unless a syntax error is actually found in the input text.
|
|
14
|
+
"""
|
|
15
|
+
from simpleparse.parser import Parser
|
|
16
|
+
from simpleparse.common import chartypes
|
|
17
|
+
|
|
18
|
+
#print file
|
|
19
|
+
grammar = r'''
|
|
20
|
+
header := -[\n]*
|
|
21
|
+
vrmlFile := header, vrmlScene, !, EOF
|
|
22
|
+
rootItem := ts,(Proto/ExternProto/ROUTE/('USE',ts,USE,ts)/Script/Node),ts
|
|
23
|
+
vrmlScene := rootItem*
|
|
24
|
+
|
|
25
|
+
Proto := 'PROTO',ts,!, nodegi,ts,'[',ts,(fieldDecl/eventDecl)*,']', ts, '{', ts, vrmlScene,ts, '}', ts
|
|
26
|
+
fieldDecl := fieldExposure,ts,!,dataType,ts,name,ts,Field,ts
|
|
27
|
+
fieldExposure := 'field'/'exposedField'
|
|
28
|
+
dataType := ('SF'/'MF')?,name
|
|
29
|
+
eventDecl := eventDirection, ts, !,dataType, ts, name, ts
|
|
30
|
+
eventDirection := 'eventIn'/'eventOut'
|
|
31
|
+
ExternProto := 'EXTERNPROTO',ts,!,nodegi,ts,'[',ts,(extFieldDecl/eventDecl)*,']', ts, ExtProtoURL
|
|
32
|
+
extFieldDecl := fieldExposure,ts,!,dataType,ts,name,ts
|
|
33
|
+
ExtProtoURL := '['?,(ts,SFString)*, ts, ']'?, ts # just an MFString by another name :)
|
|
34
|
+
|
|
35
|
+
ROUTE := 'ROUTE',ts, !,name,'.',name, ts, 'TO', ts, name,'.',name, ts
|
|
36
|
+
|
|
37
|
+
Node := ('DEF',ts,!,name,ts)?,nodegi,ts,'{',ts,(Proto/ExternProto/ROUTE/Attr)*,ts,!,'}', ts
|
|
38
|
+
|
|
39
|
+
Script := ('DEF',ts,!,name,ts)?,'Script',ts,!,'{',ts,(ScriptFieldDecl/ScriptEventDecl/Proto/ExternProto/ROUTE/Attr)*,ts,'}', ts
|
|
40
|
+
ScriptEventDecl := eventDirection, ts, !,dataType, ts, name, ts, ('IS', ts,!, IS,ts)?
|
|
41
|
+
ScriptFieldDecl := fieldExposure,ts,!,dataType,ts,name,ts,(('IS', ts,!,IS,ts)/Field),ts
|
|
42
|
+
|
|
43
|
+
SFNull := 'NULL', ts
|
|
44
|
+
|
|
45
|
+
# should really have an optimised way of declaring a different reporting name for the same production...
|
|
46
|
+
USE := name
|
|
47
|
+
IS := name
|
|
48
|
+
nodegi := name
|
|
49
|
+
Attr := name, ts, (('IS', ts,IS,ts)/Field), ts
|
|
50
|
+
Field := ( '[',ts,((vector/SFNumber/SFBool/SFString/('USE',ts,USE,ts)/Script/Node),ts)*, ']'!, ts )/((SFNumber/SFBool/SFNull/SFString/('USE',ts,USE,ts)/Script/Node),ts)+
|
|
51
|
+
|
|
52
|
+
vector := '[',ts,((vector/SFNumber),ts)*,']'
|
|
53
|
+
name := -[][0-9{}\000-\020"'#,.\\ ], -[][{}\000-\020"'#,.\\ ]*
|
|
54
|
+
SFNumber := [-+]*, ( ('0',[xX],[0-9A-Fa-f]+) / ([0-9.]+,([eE],[-+0-9.]+)?))
|
|
55
|
+
SFBool := 'TRUE'/'FALSE'
|
|
56
|
+
SFString := '"',(CHARNODBLQUOTE/ESCAPEDCHAR/SIMPLEBACKSLASH)*,'"'!
|
|
57
|
+
CHARNODBLQUOTE := -[\134"]+
|
|
58
|
+
SIMPLEBACKSLASH := '\134'
|
|
59
|
+
ESCAPEDCHAR := '\\"'/'\134\134'
|
|
60
|
+
<ts> := ( [ \011-\015,]+ / ('#',-'\012'*,'\n')+ )*
|
|
61
|
+
'''
|
|
62
|
+
|
|
63
|
+
class VRMLParser( Parser ):
|
|
64
|
+
"""Simple subclassing of Parser to create proper ParseProcessor"""
|
|
65
|
+
def buildProcessor( self ):
|
|
66
|
+
"""Build and return a vrml.vrml97.parseprocessor.ParseProcessor"""
|
|
67
|
+
from vrml.vrml97 import parseprocessor
|
|
68
|
+
return parseprocessor.ParseProcessor()
|
|
69
|
+
|
|
70
|
+
def buildParser( declaration = grammar ):
|
|
71
|
+
"""Build a new VRMLParser object"""
|
|
72
|
+
return VRMLParser( declaration, "vrmlFile" )
|