History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/javax/swing/text/html/parser/ContentModelState.java (1 of 18352 files). Show all

Unified · Split

java/pkg/javax/swing/text/html/parser/ContentModelState.java+295−0
@@ -0,0 +1,295 @@
1+/*
2+ * Copyright (c) 1998, 2000, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package javax.swing.text.html.parser;
27+
28+/**
29+ * A content model state. This is basically a list of pointers to
30+ * the BNF expression representing the model (the ContentModel).
31+ * Each element in a DTD has a content model which describes the
32+ * elements that may occur inside, and the order in which they can
33+ * occur.
34+ * <p>
35+ * Each time a token is reduced a new state is created.
36+ * <p>
37+ * See Annex H on page 556 of the SGML handbook for more information.
38+ *
39+ * @see Parser
40+ * @see DTD
41+ * @see Element
42+ * @see ContentModel
43+ * @author Arthur van Hoff
44+ */
45+class ContentModelState {
46+ ContentModel model;
47+ long value;
48+ ContentModelState next;
49+
50+ /**
51+ * Create a content model state for a content model.
52+ */
53+ public ContentModelState(ContentModel model) {
54+ this(model, null, 0);
55+ }
56+
57+ /**
58+ * Create a content model state for a content model given the
59+ * remaining state that needs to be reduce.
60+ */
61+ ContentModelState(Object content, ContentModelState next) {
62+ this(content, next, 0);
63+ }
64+
65+ /**
66+ * Create a content model state for a content model given the
67+ * remaining state that needs to be reduce.
68+ */
69+ ContentModelState(Object content, ContentModelState next, long value) {
70+ this.model = (ContentModel)content;
71+ this.next = next;
72+ this.value = value;
73+ }
74+
75+ /**
76+ * Return the content model that is relevant to the current state.
77+ */
78+ public ContentModel getModel() {
79+ ContentModel m = model;
80+ for (int i = 0; i < value; i++) {
81+ if (m.next != null) {
82+ m = m.next;
83+ } else {
84+ return null;
85+ }
86+ }
87+ return m;
88+ }
89+
90+ /**
91+ * Check if the state can be terminated. That is there are no more
92+ * tokens required in the input stream.
93+ * @return true if the model can terminate without further input
94+ */
95+ public boolean terminate() {
96+ switch (model.type) {
97+ case '+':
98+ if ((value == 0) && !(model).empty()) {
99+ return false;
100+ }
101+ case '*':
102+ case '?':
103+ return (next == null) || next.terminate();
104+
105+ case '|':
106+ for (ContentModel m = (ContentModel)model.content ; m != null ; m = m.next) {
107+ if (m.empty()) {
108+ return (next == null) || next.terminate();
109+ }
110+ }
111+ return false;
112+
113+ case '&': {
114+ ContentModel m = (ContentModel)model.content;
115+
116+ for (int i = 0 ; m != null ; i++, m = m.next) {
117+ if ((value & (1L << i)) == 0) {
118+ if (!m.empty()) {
119+ return false;
120+ }
121+ }
122+ }
123+ return (next == null) || next.terminate();
124+ }
125+
126+ case ',': {
127+ ContentModel m = (ContentModel)model.content;
128+ for (int i = 0 ; i < value ; i++, m = m.next);
129+
130+ for (; (m != null) && m.empty() ; m = m.next);
131+ if (m != null) {
132+ return false;
133+ }
134+ return (next == null) || next.terminate();
135+ }
136+
137+ default:
138+ return false;
139+ }
140+ }
141+
142+ /**
143+ * Check if the state can be terminated. That is there are no more
144+ * tokens required in the input stream.
145+ * @return the only possible element that can occur next
146+ */
147+ public Element first() {
148+ switch (model.type) {
149+ case '*':
150+ case '?':
151+ case '|':
152+ case '&':
153+ return null;
154+
155+ case '+':
156+ return model.first();
157+
158+ case ',': {
159+ ContentModel m = (ContentModel)model.content;
160+ for (int i = 0 ; i < value ; i++, m = m.next);
161+ return m.first();
162+ }
163+
164+ default:
165+ return model.first();
166+ }
167+ }
168+
169+ /**
170+ * Advance this state to a new state. An exception is thrown if the
171+ * token is illegal at this point in the content model.
172+ * @return next state after reducing a token
173+ */
174+ public ContentModelState advance(Object token) {
175+ switch (model.type) {
176+ case '+':
177+ if (model.first(token)) {
178+ return new ContentModelState(model.content,
179+ new ContentModelState(model, next, value + 1)).advance(token);
180+ }
181+ if (value != 0) {
182+ if (next != null) {
183+ return next.advance(token);
184+ } else {
185+ return null;
186+ }
187+ }
188+ break;
189+
190+ case '*':
191+ if (model.first(token)) {
192+ return new ContentModelState(model.content, this).advance(token);
193+ }
194+ if (next != null) {
195+ return next.advance(token);
196+ } else {
197+ return null;
198+ }
199+
200+ case '?':
201+ if (model.first(token)) {
202+ return new ContentModelState(model.content, next).advance(token);
203+ }
204+ if (next != null) {
205+ return next.advance(token);
206+ } else {
207+ return null;
208+ }
209+
210+ case '|':
211+ for (ContentModel m = (ContentModel)model.content ; m != null ; m = m.next) {
212+ if (m.first(token)) {
213+ return new ContentModelState(m, next).advance(token);
214+ }
215+ }
216+ break;
217+
218+ case ',': {
219+ ContentModel m = (ContentModel)model.content;
220+ for (int i = 0 ; i < value ; i++, m = m.next);
221+
222+ if (m.first(token) || m.empty()) {
223+ if (m.next == null) {
224+ return new ContentModelState(m, next).advance(token);
225+ } else {
226+ return new ContentModelState(m,
227+ new ContentModelState(model, next, value + 1)).advance(token);
228+ }
229+ }
230+ break;
231+ }
232+
233+ case '&': {
234+ ContentModel m = (ContentModel)model.content;
235+ boolean complete = true;
236+
237+ for (int i = 0 ; m != null ; i++, m = m.next) {
238+ if ((value & (1L << i)) == 0) {
239+ if (m.first(token)) {
240+ return new ContentModelState(m,
241+ new ContentModelState(model, next, value | (1L << i))).advance(token);
242+ }
243+ if (!m.empty()) {
244+ complete = false;
245+ }
246+ }
247+ }
248+ if (complete) {
249+ if (next != null) {
250+ return next.advance(token);
251+ } else {
252+ return null;
253+ }
254+ }
255+ break;
256+ }
257+
258+ default:
259+ if (model.content == token) {
260+ if (next == null && (token instanceof Element) &&
261+ ((Element)token).content != null) {
262+ return new ContentModelState(((Element)token).content);
263+ }
264+ return next;
265+ }
266+ // PENDING: Currently we don't correctly deal with optional start
267+ // tags. This can most notably be seen with the 4.01 spec where
268+ // TBODY's start and end tags are optional.
269+ // Uncommenting this and the PENDING in ContentModel will
270+ // correctly skip the omit tags, but the delegate is not notified.
271+ // Some additional API needs to be added to track skipped tags,
272+ // and this can then be added back.
273+/*
274+ if ((model.content instanceof Element)) {
275+ Element e = (Element)model.content;
276+
277+ if (e.omitStart() && e.content != null) {
278+ return new ContentModelState(e.content, next).advance(
279+ token);
280+ }
281+ }
282+*/
283+ }
284+
285+ // We used to throw this exception at this point. However, it
286+ // was determined that throwing this exception was more expensive
287+ // than returning null, and we could not justify to ourselves why
288+ // it was necessary to throw an exception, rather than simply
289+ // returning null. I'm leaving it in a commented out state so
290+ // that it can be easily restored if the situation ever arises.
291+ //
292+ // throw new IllegalArgumentException("invalid token: " + token);
293+ return null;
294+ }
295+}