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

Quick Search    Search Deep

Source code: com/hexidec/ekit/component/parser/ContentModel.java


1   /*
2    * @(#)ContentModel.java  1.8 01/12/03
3    *
4    * Copyright 2002 Sun Microsystems, Inc. All rights reserved.
5    * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6    */
7   
8   package com.hexidec.ekit.component.parser;
9   
10  import java.util.Vector;
11  import java.util.Enumeration;
12  import java.io.*;
13  
14  
15  /**
16   * A representation of a content model. A content model is
17   * basically a restricted BNF expression. It is restricted in
18   * the sense that it must be deterministic. This means that you
19   * don't have to represent it as a finite state automata.<p>
20   * See Annex H on page 556 of the SGML handbook for more information.
21   *
22   * @author   Arthur van Hoff
23   * @version  1.8,12/03/01
24   *
25   */
26  public final class ContentModel implements Serializable {
27      /**
28       * Type. Either '*', '?', '+', ',', '|', '&'.
29       */
30      public int type;
31  
32      /**
33       * The content. Either an Element or a ContentModel.
34       */
35      public Object content;
36  
37      /**
38       * The next content model (in a ',', '|' or '&' expression).
39       */
40      public ContentModel next;
41  
42      public ContentModel() {
43      }
44  
45      /**
46       * Create a content model for an element.
47       */
48      public ContentModel(Element content) {
49    this(0, content, null);
50      }
51  
52      /**
53       * Create a content model of a particular type.
54       */
55      public ContentModel(int type, ContentModel content) {
56    this(type, content, null);
57      }
58  
59      /**
60       * Create a content model of a particular type.
61       */
62      public ContentModel(int type, Object content, ContentModel next) {
63    this.type = type;
64    this.content = content;
65    this.next = next;
66      }
67  
68      /**
69       * Return true if the content model could
70       * match an empty input stream.
71       */
72      public boolean empty() {
73    switch (type) {
74      case '*':
75      case '?':
76        return true;
77  
78      case '+':
79      case '|':
80        for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
81      if (m.empty()) {
82          return true;
83      }
84        }
85        return false;
86  
87      case ',':
88      case '&':
89        for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
90      if (!m.empty()) {
91          return false;
92      }
93        }
94        return true;
95  
96      default:
97        return false;
98    }
99      }
100 
101     /**
102      * Update elemVec with the list of elements that are
103      * part of the this contentModel.
104      */
105      public void getElements(Vector elemVec) {
106    switch (type) {
107    case '*':
108    case '?':
109    case '+':
110        ((ContentModel)content).getElements(elemVec);
111        break;
112    case ',':
113    case '|':
114    case '&':
115        for (ContentModel m=(ContentModel)content; m != null; m=m.next){
116      m.getElements(elemVec);
117        }
118        break;
119    default:
120        elemVec.addElement(content);
121    }
122      }
123 
124      private boolean valSet[];
125      private boolean val[];
126      // A cache used by first().  This cache was found to speed parsing
127      // by about 10% (based on measurements of the 4-12 code base after
128      // buffering was fixed).
129 
130     /**
131      * Return true if the token could potentially be the
132      * first token in the input stream.
133      */
134     public boolean first(Object token) {
135   switch (type) {
136     case '*':
137     case '?':
138     case '+':
139       return ((ContentModel)content).first(token);
140 
141     case ',':
142       for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
143     if (m.first(token)) {
144         return true;
145     }
146     if (!m.empty()) {
147         return false;
148     }
149       }
150       return false;
151 
152     case '|':
153     case '&': {
154       Element e = (Element) token;
155       if (valSet == null) {
156     valSet = new boolean[Element.maxIndex + 1];
157     val = new boolean[Element.maxIndex + 1];
158     // All Element instances are created before this ever executes
159       }
160       if (valSet[e.index]) {
161     return val[e.index];
162       }
163       for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
164     if (m.first(token)) {
165         val[e.index] = true;
166         break;
167     }
168       }
169       valSet[e.index] = true;
170       return val[e.index];
171     }
172 
173     default:
174       return (content == token);
175             // PENDING: refer to comment in ContentModelState
176 /*
177               if (content == token) {
178                   return true;
179               }
180               Element e = (Element)content;
181               if (e.omitStart() && e.content != null) {
182                   return e.content.first(token);
183               }
184               return false;
185 */
186   }
187     }
188 
189     /**
190      * Return the element that must be next.
191      */
192     public Element first() {
193   switch (type) {
194     case '&':
195     case '|':
196     case '*':
197     case '?':
198       return null;
199 
200     case '+':
201     case ',':
202       return ((ContentModel)content).first();
203 
204     default:
205       return (Element)content;
206   }
207     }
208 
209     /**
210      * Convert to a string.
211      */
212     public String toString() {
213   switch (type) {
214     case '*':
215       return content + "*";
216     case '?':
217       return content + "?";
218     case '+':
219       return content + "+";
220 
221     case ',':
222     case '|':
223     case '&':
224       char data[] = {' ', (char)type, ' '};
225       String str = "";
226       for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
227     str = str + m;
228     if (m.next != null) {
229         str += new String(data);
230     }
231       }
232       return "(" + str + ")";
233 
234     default:
235       return content.toString();
236   }
237     }
238 }