You can create a node using CreateParse
constructor to parse the node. Or you can initialize node
contents by parsing it using Parse method.
However, these both approaches require you to
first prepare appropriate TX3DLexer
instance and a list of read node names.
There are comfortable routines like ParseVRMLFile
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
TVRMLRootNode.ForceVersion. This will be used later when saving. Parser always returnsTVRMLRootNodeinstance, this keeps some per-file settings like version and X3D profile, components and meta values.When saving, you can save any
TVRMLNodeinstance to file. If it is notTVRMLRootNode, or ifTVRMLRootNode.HasForceVersionis 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
TVRMLRootNodeand 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).While parsing,
ForVRMLVersionmethod 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
DEFclause is parsed we add the node name and it's reference toNodeNameBindinglist that is passed through all parse routines. When aUSEclause is encountered, we just search this list for appropriate node name.Simple VRML rules of
DEF/USEbehavior 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 nextDEFoccurrence 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 byInlinenodes, 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
NodeNameBindingafter the node is fully parsed prevents creating loops in our graph, in case supplied VRML file is invalid.