You can create a node using
constructor to parse the node. Or you can initialize node
contents by parsing it using
However, these both approaches require you to
first prepare appropriate
instance and a list of read node names.
There are comfortable routines like
that take care of this for you. They create appropriate lexer,
and may create also suitable
TStream instance to read
given file content.
Some details about parsing:
Our VRML/X3D lexer is a unified lexer for both VRML 1.0, 2.0 and (classic) X3D. Most of the syntax is identical, minor differences can be handled correctly by a lexer because it always knows VRML/X3D header line of the given file. So it knows what syntax to expect.
VRML/X3D version of the original file
is saved in
This will be used later when saving.
Parser always returns
instance, this keeps some per-file settings like version
and X3D profile, components and meta values.
When saving, you can save any
to file. If it is not
TVRMLRootNode.HasForceVersion is false,
we simply assume it uses the latest X3D version.
In engine versions <= 2.5.0 we experimented
with auto-detecting the suitable VRML/X3D version for nodes inside,
but this mechanism was dropped. It was complicated, and was failing
anyway for complicated cases (nodes from mixed versions,
things with routes, imports, exports etc.). If you want to save a specific
VRML/X3D version, it's best to simply wrap it inside
and force desired version explicitly.
Modern programs should target only X3D anyway,
as VRML 1.0 is ancient, and VRML 2.0 is old too (from 1997).
method mentioned earlier may be used to decide which node classes
to create based on VRML/X3D version indicated in the file's header line.
To properly handle
DEF / USE mechanism
we keep a list of known node names while parsing.
After a node with
is parsed we add the node name and it's reference to
list that is passed through all parse routines.
USE clause is encountered,
we just search this list for appropriate node name.
Simple VRML rules of
behavior make this approach correct. Remember that VRML name
scope is not modeled after normal programming languages,
where name scope of an identifier is usually limited
to the structure (function, class, etc.) where this identifier
is declared. In VRML, name scope always spans to the end
of whole VRML file (or to the next
occurrence with the same name, that overrides previous
name). Also, the name scope is always limited to the current file
— for example, you cannot use names defined in other VRML
files (that you included by
or that include you).
(Prototypes and external prototypes in VRML 2.0 are designed
to allow reusing VRML code between different VRML files.)
The simple trick with adding our name to
after the node is fully parsed prevents
creating loops in our graph, in case supplied VRML file is invalid.