/* * Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */package javax.swing.text.html.parser;import java.util.Vector;import java.util.Enumeration;import java.io.*;/** * A representation of a content model. A content model is * basically a restricted BNF expression. It is restricted in * the sense that it must be deterministic. This means that you * don't have to represent it as a finite state automata.<p> * See Annex H on page 556 of the SGML handbook for more information. * * @author Arthur van Hoff * */public final class ContentModel implements Serializable { /** * Type. Either '*', '?', '+', ',', '|', '&'. */ public int type; /** * The content. Either an Element or a ContentModel. */ public Object content; /** * The next content model (in a ',', '|' or '&' expression). */ public ContentModel next; public ContentModel() { } /** * Create a content model for an element. */ public ContentModel(Element content) { this(0, content, null); } /** * Create a content model of a particular type. */ public ContentModel(int type, ContentModel content) { this(type, content, null); } /** * Create a content model of a particular type. */ public ContentModel(int type, Object content, ContentModel next) { this.type = type; this.content = content; this.next = next; } /** * Return true if the content model could * match an empty input stream. */ public boolean empty() { switch (type) { case '*': case '?': return true; case '+': case '|': for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) { if (m.empty()) { return true; } } return false; case ',': case '&': for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) { if (!m.empty()) { return false; } } return true; default: return false; } } /** * Update elemVec with the list of elements that are * part of the this contentModel. */ public void getElements(Vector<Element> elemVec) { switch (type) { case '*': case '?': case '+': ((ContentModel)content).getElements(elemVec); break; case ',': case '|': case '&': for (ContentModel m=(ContentModel)content; m != null; m=m.next){ m.getElements(elemVec); } break; default: elemVec.addElement((Element)content); } } private boolean valSet[]; private boolean val[]; // A cache used by first(). This cache was found to speed parsing // by about 10% (based on measurements of the 4-12 code base after // buffering was fixed). /** * Return true if the token could potentially be the * first token in the input stream. */ public boolean first(Object token) { switch (type) { case '*': case '?': case '+': return ((ContentModel)content).first(token); case ',': for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) { if (m.first(token)) { return true; } if (!m.empty()) { return false; } } return false; case '|': case '&': { Element e = (Element) token; if (valSet == null) { valSet = new boolean[Element.maxIndex + 1]; val = new boolean[Element.maxIndex + 1]; // All Element instances are created before this ever executes } if (valSet[e.index]) { return val[e.index]; } for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) { if (m.first(token)) { val[e.index] = true; break; } } valSet[e.index] = true; return val[e.index]; } default: return (content == token); // PENDING: refer to comment in ContentModelState/* if (content == token) { return true; } Element e = (Element)content; if (e.omitStart() && e.content != null) { return e.content.first(token); } return false;*/ } } /** * Return the element that must be next. */ public Element first() { switch (type) { case '&': case '|': case '*': case '?': return null; case '+': case ',': return ((ContentModel)content).first(); default: return (Element)content; } } /** * Convert to a string. */ public String toString() { switch (type) { case '*': return content + "*"; case '?': return content + "?"; case '+': return content + "+"; case ',': case '|': case '&': char data[] = {' ', (char)type, ' '}; String str = ""; for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) { str = str + m; if (m.next != null) { str += new String(data); } } return "(" + str + ")"; default: return content.toString(); } }}
/*
* Copyright (c) 1998, 2004, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package javax.swing.text.html.parser;
import java.util.Vector;
import java.util.Enumeration;
import java.io.*;
/**
* A representation of a content model. A content model is
* basically a restricted BNF expression. It is restricted in
* the sense that it must be deterministic. This means that you
* don't have to represent it as a finite state automata.<p>
* See Annex H on page 556 of the SGML handbook for more information.
*
* @author Arthur van Hoff
*
*/
public final class ContentModel implements Serializable {
/**
* Type. Either '*', '?', '+', ',', '|', '&'.
*/
public int type;
/**
* The content. Either an Element or a ContentModel.
*/
public Object content;
/**
* The next content model (in a ',', '|' or '&' expression).
*/
public ContentModel next;
public ContentModel() {
}
/**
* Create a content model for an element.
*/
public ContentModel(Element content) {
this(0, content, null);
}
/**
* Create a content model of a particular type.
*/
public ContentModel(int type, ContentModel content) {
this(type, content, null);
}
/**
* Create a content model of a particular type.
*/
public ContentModel(int type, Object content, ContentModel next) {
this.type = type;
this.content = content;
this.next = next;
}
/**
* Return true if the content model could
* match an empty input stream.
*/
public boolean empty() {
switch (type) {
case '*':
case '?':
return true;
case '+':
case '|':
for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
if (m.empty()) {
return true;
}
}
return false;
case ',':
case '&':
for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
if (!m.empty()) {
return false;
}
}
return true;
default:
return false;
}
}
/**
* Update elemVec with the list of elements that are
* part of the this contentModel.
*/
public void getElements(Vector<Element> elemVec) {
switch (type) {
case '*':
case '?':
case '+':
((ContentModel)content).getElements(elemVec);
break;
case ',':
case '|':
case '&':
for (ContentModel m=(ContentModel)content; m != null; m=m.next){
m.getElements(elemVec);
}
break;
default:
elemVec.addElement((Element)content);
}
}
private boolean valSet[];
private boolean val[];
// A cache used by first(). This cache was found to speed parsing
// by about 10% (based on measurements of the 4-12 code base after
// buffering was fixed).
/**
* Return true if the token could potentially be the
* first token in the input stream.
*/
public boolean first(Object token) {
switch (type) {
case '*':
case '?':
case '+':
return ((ContentModel)content).first(token);
case ',':
for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
if (m.first(token)) {
return true;
}
if (!m.empty()) {
return false;
}
}
return false;
case '|':
case '&': {
Element e = (Element) token;
if (valSet == null) {
valSet = new boolean[Element.maxIndex + 1];
val = new boolean[Element.maxIndex + 1];
// All Element instances are created before this ever executes
}
if (valSet[e.index]) {
return val[e.index];
}
for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
if (m.first(token)) {
val[e.index] = true;
break;
}
}
valSet[e.index] = true;
return val[e.index];
}
default:
return (content == token);
// PENDING: refer to comment in ContentModelState
/*
if (content == token) {
return true;
}
Element e = (Element)content;
if (e.omitStart() && e.content != null) {
return e.content.first(token);
}
return false;
*/
}
}
/**
* Return the element that must be next.
*/
public Element first() {
switch (type) {
case '&':
case '|':
case '*':
case '?':
return null;
case '+':
case ',':
return ((ContentModel)content).first();
default:
return (Element)content;
}
}
/**
* Convert to a string.
*/
public String toString() {
switch (type) {
case '*':
return content + "*";
case '?':
return content + "?";
case '+':
return content + "+";
case ',':
case '|':
case '&':
char data[] = {' ', (char)type, ' '};
String str = "";
for (ContentModel m = (ContentModel)content ; m != null ; m = m.next) {
str = str + m;
if (m.next != null) {
str += new String(data);
}
}
return "(" + str + ")";
default:
return content.toString();
}
}
}