diff options
Diffstat (limited to 'libjava/classpath/gnu/javax/swing/text/html/parser/models/node.java')
-rw-r--r-- | libjava/classpath/gnu/javax/swing/text/html/parser/models/node.java | 339 |
1 files changed, 339 insertions, 0 deletions
diff --git a/libjava/classpath/gnu/javax/swing/text/html/parser/models/node.java b/libjava/classpath/gnu/javax/swing/text/html/parser/models/node.java new file mode 100644 index 000000000..f45a13b3e --- /dev/null +++ b/libjava/classpath/gnu/javax/swing/text/html/parser/models/node.java @@ -0,0 +1,339 @@ +/* node.java -- + Copyright (C) 2005 Free Software Foundation, Inc. + +This file is part of GNU Classpath. + +GNU Classpath is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2, or (at your option) +any later version. + +GNU Classpath 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 for more details. + +You should have received a copy of the GNU General Public License +along with GNU Classpath; see the file COPYING. If not, write to the +Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. */ + + +package gnu.javax.swing.text.html.parser.models; + +import gnu.java.lang.CPStringBuilder; + +import java.io.Serializable; + +/** + * Part of the internal representation of the content model. + * @author Audrius Meskauskas, Lithuania (AudriusA@Bioinformatics.org) + */ +public class node + implements Serializable +{ + private static final long serialVersionUID = 1; + + /** + * The token to match (can be instance of list). + */ + public Object token; + + /** + * True for the node that cannot be visited again. + */ + public boolean _closed; + + /** + * The binary operation for this node. + */ + public char binary; + + /** + * The unary opeation for this node. + */ + public char unary; + + /** + * The number of times the node already was visited. + */ + public int visits; + + /** + * The previous node in content model (used for closing nodes). + */ + public node previous; + + /** + * Creates a new node. + * @param binary_operator The operator, connecting all nodes in the list. + * The nodes, connected by the different operators, must be arranged into + * the different lists. + * @param unary_operator The unary operator for this node or zero if + * no such was specified. + * @param token The token to match. This can be either a string or + * the new instance of the list. + * @param a_previous The previous node in the list, null for the first + * node. This is used for propagating the closing operation for the + * comma delimited list. + */ + public node(char binary_operator, char unary_operator, Object a_token) + { + if (a_token != null) + if (a_token.getClass().equals(node.class)) + throw new Error("Creating node in node is redundant and ineffective."); + + binary = binary_operator; + unary = unary_operator; + token = a_token; + } + + /** + * Checks if this node is in the closed state. + * @return True if the node is closed. + */ + public boolean isClosed() + { + return _closed; + } + + /** + * Check if closing this node means closing the previous node. + */ + public boolean closePrevious() + { + return binary == ','; + } + + /** + * Return the token object if it could match as a next token in + * a token list of null if it could not. + * @return + */ + public Object findFreeNode() + { + boolean ok; + if (isClosed() || silenceAllowed()) + return null; + + // Try if the node would stay valid after a one more visit. + visits++; + ok = valid(); + visits--; + + if (ok) + { + if (token instanceof node) + return ((node) token).findFreeNode(); + else + return token; + } + else + return null; + } + + /** + * Check if the current situation is such that the node must be closed + * now. + */ + public boolean mustClose() + { + switch (unary) + { + case 0 : + return true; + + case '*' : + return false; + + case '+' : + return false; + + case '?' : + return visits <= 1; + + default : + throw new Error("Invalid unary operation " + unary + " ( '" + + (char) unary + "' )" + ); + } + } + + /** + * Do the match operation with the given token. This sets various + * flags. + * @param a_token The token to match. + * @return true if the the token matches node, false if it does not match + * or if the node is closed. + */ + public boolean performMatch(Object a_token) + { + if (isClosed()) + return false; + + boolean matches = compare(a_token); + if (matches) + matches(); + + return matches; + } + + /** + * Prepares the node for matching against a new list of tokens. + */ + public void reset() + { + _closed = false; + visits = 0; + } + + /** + * Check if the provided token can match this node. + * In the case of match, the node state changes, moving + * current position after the matched token. However if this method + * returns a suggested new token to insert before the provided one, + * the state of the list does not change. + * @return Boolean.TRUE if the match is found, + * Boolean.FALSE if the match is not possible and no token can be + * inserted to make the match valid. Otherwise, returns the + * token object that can be inserted before the last token in the + * list, probably (not for sure) making the match valid. + */ + public Object show(Object x) + { + if (compare(x)) + return performMatch(x) ? Boolean.TRUE : Boolean.FALSE; + + Object recommended = findFreeNode(); + return recommended != null ? recommended : Boolean.FALSE; + } + + /** + * Check if it would be a valid case if this node is visited zero times. + * Nodes with unary operator * or ? need not be matched to make a + * model valid. + */ + public boolean silenceAllowed() + { + return unary == '?' || unary == '*'; + } + + /** + * Returns a string representation of the list. + * @return String representation, similar to BNF expression. + */ + public String toString() + { + CPStringBuilder b = new CPStringBuilder(); + + b.append(token); + if (unary != 0) + b.append((char) unary); + else + b.append('\''); + + return b.toString(); + } + + /** + * Check if the node state is valid. + */ + public boolean valid() + { + switch (unary) + { + case 0 : + if (binary == '|') + return true; + else + return visits == 1; + + case '*' : + return true; + + case '+' : + return visits > 0; + + case '?' : + return visits <= 1; + + default : + throw new Error("Invalid unary operation " + unary + " ( '" + + (char) unary + "' )" + ); + } + } + + public boolean validPreliminary() + { + return visits == 0 || valid(); + } + + /** + * Closes this node and, if closePrevious() returs true, calls close() for + * the previous node. + */ + protected void close() + { + _closed = true; + if (previous != null && closePrevious()) + previous.close(); + } + + /** + * Compare the provided token object with the token object of this node. + */ + protected boolean compare(Object a_token) + { + if (token instanceof Object[]) + throw new Error("Invalid token object, probably the 'list' " + + "should be used. " + ); + + if (token instanceof node[]) + throw new Error("Do not use 'node' for the array of nodes, use 'list'. "); + + if (token instanceof node) + { + return ((node) token).performMatch(a_token); + } + + boolean rt = false; + + if (token == a_token) + rt = true; + if (token.equals(a_token)) + rt = true; + if (token.toString().equalsIgnoreCase(a_token.toString())) + rt = true; + + return rt; + } + + /** + * Fire the changes that must happen then the token matches this node. + */ + protected void matches() + { + visits++; + if (mustClose()) + close(); + } +} |