Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: com/trapezium/vrml/grammar/VRML97parser.java


1   /*
2    * @(#)VRML97parser.java
3    *
4    * Copyright (c) 1998 by Trapezium Development LLC.  All Rights Reserved.
5    *
6    * The information in this file is the property of Trapezium Development LLC
7    * and may be used only in accordance with the terms of the license granted
8    * by Trapezium.
9    *
10   */
11  package com.trapezium.vrml.grammar;
12  
13  import com.trapezium.vrml.VrmlElement;
14  import com.trapezium.vrml.Scene;
15  import com.trapezium.vrml.ErrorElement;
16  import com.trapezium.vrml.visitor.ParentSetter;
17  import com.trapezium.parse.TokenEnumerator;
18  
19  /**
20   *  Main class for parsing a VRML 2.0 file.
21   *
22   *  A Scene is the root of a VRML element hierarchy.  This is a simple hierarchy where each
23   *  VrmlElement may or may not have children.  Much of the additional functionality required
24   *  is implemented by using the "Visitor Pattern" on this hierarchy.  This pattern encapsulates
25   *  features in the visitor objects.
26   *
27   *  Within the SceneRule factory, the above parameters eventually turn into a Token enumerator,
28   *  and the Scene is constructed as follows:
29   *
30   *            TokenEnumerator tokenEnumerator = ...
31   *            Scene scene = new Scene( fileUrl, tokenEnumerator );
32   *            VRML97parser parser = new VRML97parser();
33   *            parser.Build( tokenEnumerator, scene );
34   *
35   *  The convention followed by this and all other grammar rules is that a static public
36   *  "Build" method is used to add children to an object.
37   *
38   *  The SceneRule handles the following portion of the grammar from the VRML 2.0 spec:
39   *
40   *   vrmlScene ::=
41   *        statements ;
42   *   statements ::=
43   *        statement |
44   *        statement statements |
45   *        empty ;
46   *           
47   *  @author          Johannes N. Johannsen
48   *  @version         1.12, 2 April 1998, allow inclusion of first token in parsing
49   *  @version         1.1, 21 Jan 1998
50   *
51   *  @since           1.0
52   */
53  public class VRML97parser {
54      NodeRule nodeRule;
55      StatementRule statementRule;
56      
57      // PROTOs use same parser as base
58      static public VRML97parser singleton = null;
59  
60      /** Parser with no DEFNameFactory and no error reporting limits */
61      public VRML97parser() {
62          this( null );
63      }
64      
65      /** Parser with an optional DEFNameFactory for generating DEF names.
66       *
67       *  If the "Build" method gets called with a Scene that also has
68       *  a DEFNameFactory, that DEFNameFactory will replace the VRML97parser
69       *  DEFNameFactory.
70       */
71      public VRML97parser( DEFNameFactory defNameFactory ) {
72          nodeRule = new NodeRule( defNameFactory );
73          statementRule = new StatementRule( nodeRule );
74          singleton = this;
75      }
76      
77    /**
78     *  Apply the SceneRule to update the Scene.
79     */
80    public void Build( TokenEnumerator v, Scene scene ) {
81        String line = v.getLineAt( 0 );
82        if ( line.indexOf( "#VRML V2.0 utf8" ) != 0 ) {
83            scene.addChild( new ErrorElement( 0, "Bad header, expected 'VRML V2.0 utf8'" ));
84        } else {
85            Build( v, scene, 0 );
86        }
87    }
88    
89    /**
90     *  Build Scene, startToken needed for dynamic generation.  Normally
91     *  this is 0, which is the header, which is not ignored by the parsing.
92     *  For dynamically generated Nodes, with no header, this is set to
93     *  -1 so that first token is not ignored in parsing.
94     */
95    public void Build( TokenEnumerator v, Scene scene, int startToken )  {
96        v.setState( startToken );
97        
98        // use the scene's DEFNameFactory, if any
99        if ( scene.getDEFNameFactory() != null ) {
100           nodeRule.setDEFNameFactory( scene.getDEFNameFactory() );
101       }
102     Build( v, scene, scene, "" );
103     
104     // necessary to prevent infinite loop on visitors if
105     // scene graph has Script field self references
106     ParentSetter ps = new ParentSetter( v );
107     scene.traverse( ps );
108   }
109 
110   /**
111    *  Build either an embedded Scene (for PROTOs), or a Scene from a file.  If the
112    *  "terminator" is a "}", we are building an embedded Scene.
113    */
114   void Build( TokenEnumerator v, Scene scene, VrmlElement parent, String terminator ) {
115     GrammarRule.Enter( "SceneRule.Build" );
116     scene.setFirstTokenOffset( v.getCurrentTokenOffset() );
117     int tokenOffset = -1;
118     while ( true ) {
119       tokenOffset = v.getNextToken();
120       if ( tokenOffset == -1 ) {
121         break;
122       }
123       if ( v.sameAs( tokenOffset, terminator )) {
124         break;
125       }
126       statementRule.Build( tokenOffset, v, scene, parent );
127     }
128     if ( tokenOffset == -1 ) {
129         scene.setLastTokenOffset( v.getCurrentTokenOffset() - 1 );
130       } else {
131           scene.setLastTokenOffset( v.getCurrentTokenOffset() );
132       }
133     GrammarRule.Exit( "SceneRule.Build" );
134   }
135 }
136