📄 rulebasedbreakiterator.java
字号:
/* * @(#)RuleBasedBreakIterator.java 1.13 03/01/23 * * Copyright 2003 Sun Microsystems, Inc. All rights reserved. * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms. *//* * @(#)RuleBasedBreakIterator.java 1.3 99/04/07 * * (C) Copyright Taligent, Inc. 1996, 1997 - All Rights Reserved * (C) Copyright IBM Corp. 1996 - 2002 - All Rights Reserved * * The original version of this source code and documentation * is copyrighted and owned by Taligent, Inc., a wholly-owned * subsidiary of IBM. These materials are provided under terms * of a License Agreement between Taligent and Sun. This technology * is protected by multiple US and International patents. * * This notice and attribution to Taligent may not be removed. * Taligent is a registered trademark of Taligent, Inc. */package java.text;import java.util.Vector;import java.util.Stack;import java.util.Hashtable;import java.util.Enumeration;import java.text.CharacterIterator;import java.text.StringCharacterIterator;import sun.text.CompactByteArray;/** * <p>A subclass of BreakIterator whose behavior is specified using a list of rules.</p> * * <p>There are two kinds of rules, which are separated by semicolons: <i>substitutions</i> * and <i>regular expressions.</i></p> * * <p>A substitution rule defines a name that can be used in place of an expression. It * consists of a name, which is a string of characters contained in angle brackets, an equals * sign, and an expression. (There can be no whitespace on either side of the equals sign.) * To keep its syntactic meaning intact, the expression must be enclosed in parentheses or * square brackets. A substitution is visible after its definition, and is filled in using * simple textual substitution. Substitution definitions can contain other substitutions, as * long as those substitutions have been defined first. Substitutions are generally used to * make the regular expressions (which can get quite complex) shorted and easier to read. * They typically define either character categories or commonly-used subexpressions.</p> * * <p>There is one special substitution. If the description defines a substitution * called "<ignore>", the expression must be a [] expression, and the * expression defines a set of characters (the "<em>ignore characters</em>") that * will be transparent to the BreakIterator. A sequence of characters will break the * same way it would if any ignore characters it contains are taken out. Break * positions never occur befoer ignore characters.</p> * * <p>A regular expression uses a subset of the normal Unix regular-expression syntax, and * defines a sequence of characters to be kept together. With one significant exception, the * iterator uses a longest-possible-match algorithm when matching text to regular * expressions. The iterator also treats descriptions containing multiple regular expressions * as if they were ORed together (i.e., as if they were separated by |).</p> * * <p>The special characters recognized by the regular-expression parser are as follows:</p> * * <blockquote> * <table border="1" width="100%"> * <tr> * <td width="6%">*</td> * <td width="94%">Specifies that the expression preceding the asterisk may occur any number * of times (including not at all).</td> * </tr> * <tr> * <td width="6%">{}</td> * <td width="94%">Encloses a sequence of characters that is optional.</td> * </tr> * <tr> * <td width="6%">()</td> * <td width="94%">Encloses a sequence of characters. If followed by *, the sequence * repeats. Otherwise, the parentheses are just a grouping device and a way to delimit * the ends of expressions containing |.</td> * </tr> * <tr> * <td width="6%">|</td> * <td width="94%">Separates two alternative sequences of characters. Either one * sequence or the other, but not both, matches this expression. The | character can * only occur inside ().</td> * </tr> * <tr> * <td width="6%">.</td> * <td width="94%">Matches any character.</td> * </tr> * <tr> * <td width="6%">*?</td> * <td width="94%">Specifies a non-greedy asterisk. *? works the same way as *, except * when there is overlap between the last group of characters in the expression preceding the * * and the first group of characters following the *. When there is this kind of * overlap, * will match the longest sequence of characters that match the expression before * the *, and *? will match the shortest sequence of characters matching the expression * before the *?. For example, if you have "xxyxyyyxyxyxxyxyxyy" in the text, * "x[xy]*x" will match through to the last x (i.e., "<strong>xxyxyyyxyxyxxyxyx</strong>yy", * but "x[xy]*?x" will only match the first two xes ("<strong>xx</strong>yxyyyxyxyxxyxyxyy").</td> * </tr> * <tr> * <td width="6%">[]</td> * <td width="94%">Specifies a group of alternative characters. A [] expression will * match any single character that is specified in the [] expression. For more on the * syntax of [] expressions, see below.</td> * </tr> * <tr> * <td width="6%">/</td> * <td width="94%">Specifies where the break position should go if text matches this * expression. (e.g., "[a-z]*/[:Zs:]*[1-0]" will match if the iterator sees a run * of letters, followed by a run of whitespace, followed by a digit, but the break position * will actually go before the whitespace). Expressions that don't contain / put the * break position at the end of the matching text.</td> * </tr> * <tr> * <td width="6%">\</td> * <td width="94%">Escape character. The \ itself is ignored, but causes the next * character to be treated as literal character. This has no effect for many * characters, but for the characters listed above, this deprives them of their special * meaning. (There are no special escape sequences for Unicode characters, or tabs and * newlines; these are all handled by a higher-level protocol. In a Java string, * "\n" will be converted to a literal newline character by the time the * regular-expression parser sees it. Of course, this means that \ sequences that are * visible to the regexp parser must be written as \\ when inside a Java string.) All * characters in the ASCII range except for letters, digits, and control characters are * reserved characters to the parser and must be preceded by \ even if they currently don't * mean anything.</td> * </tr> * <tr> * <td width="6%">!</td> * <td width="94%">If ! appears at the beginning of a regular expression, it tells the regexp * parser that this expression specifies the backwards-iteration behavior of the iterator, * and not its normal iteration behavior. This is generally only used in situations * where the automatically-generated backwards-iteration brhavior doesn't produce * satisfactory results and must be supplemented with extra client-specified rules.</td> * </tr> * <tr> * <td width="6%"><em>(all others)</em></td> * <td width="94%">All other characters are treated as literal characters, which must match * the corresponding character(s) in the text exactly.</td> * </tr> * </table> * </blockquote> * * <p>Within a [] expression, a number of other special characters can be used to specify * groups of characters:</p> * * <blockquote> * <table border="1" width="100%"> * <tr> * <td width="6%">-</td> * <td width="94%">Specifies a range of matching characters. For example * "[a-p]" matches all lowercase Latin letters from a to p (inclusive). The - * sign specifies ranges of continuous Unicode numeric values, not ranges of characters in a * language's alphabetical order: "[a-z]" doesn't include capital letters, nor does * it include accented letters such as a-umlaut.</td> * </tr> * <tr> * <td width="6%">::</td> * <td width="94%">A pair of colons containing a one- or two-letter code matches all * characters in the corresponding Unicode category. The two-letter codes are the same * as the two-letter codes in the Unicode database (for example, "[:Sc::Sm:]" * matches all currency symbols and all math symbols). Specifying a one-letter code is * the same as specifying all two-letter codes that begin with that letter (for example, * "[:L:]" matches all letters, and is equivalent to * "[:Lu::Ll::Lo::Lm::Lt:]"). Anything other than a valid two-letter Unicode * category code or a single letter that begins a Unicode category code is illegal within * colons.</td> * </tr> * <tr> * <td width="6%">[]</td> * <td width="94%">[] expressions can nest. This has no effect, except when used in * conjunction with the ^ token.</td> * </tr> * <tr> * <td width="6%">^</td> * <td width="94%">Excludes the character (or the characters in the [] expression) following * it from the group of characters. For example, "[a-z^p]" matches all Latin * lowercase letters except p. "[:L:^[\u4e00-\u9fff]]" matches all letters * except the Han ideographs.</td> * </tr> * <tr> * <td width="6%"><em>(all others)</em></td> * <td width="94%">All other characters are treated as literal characters. (For * example, "[aeiou]" specifies just the letters a, e, i, o, and u.)</td> * </tr> * </table> * </blockquote> * * <p>For a more complete explanation, see <a * href="http://www.ibm.com/java/education/boundaries/boundaries.html">http://www.ibm.com/java/education/boundaries/boundaries.html</a>. * For examples, see the resource data (which is annotated).</p> * * @author Richard Gillam * @version $RCSFile$ $Revision: 1.1 $ $Date: 1998/11/05 19:32:04 $ */class RuleBasedBreakIterator extends BreakIterator { /** * A token used as a character-category value to identify ignore characters */ protected static final byte IGNORE = -1; /** * The state number of the starting state */ private static final short START_STATE = 1; /** * The state-transition value indicating "stop" */ private static final short STOP_STATE = 0; /** * The textual description this iterator was created from */ private String description; /** * A table that indexes from character values to character category numbers */ private CompactByteArray charCategoryTable = null; /** * The table of state transitions used for forward iteration */ private short[] stateTable = null; /** * The table of state transitions used to sync up the iterator with the * text in backwards and random-access iteration */ private short[] backwardsStateTable = null; /** * A list of flags indicating which states in the state table are accepting * ("end") states */ private boolean[] endStates = null; /** * A list of flags indicating which states in the state table are * lookahead states (states which turn lookahead on and off) */ private boolean[] lookaheadStates = null; /** * The number of character categories (and, thus, the number of columns in * the state tables) */ private int numCategories; /** * The character iterator through which this BreakIterator accesses the text */ private CharacterIterator text = null; //======================================================================= // constructors //======================================================================= /** * Constructs a RuleBasedBreakIterator according to the description * provided. If the description is malformed, throws an * IllegalArgumentException. Normally, instead of constructing a * RuleBasedBreakIterator directory, you'll use the factory methods * on BreakIterator to create one indirectly from a description * in the framework's resource files. You'd use this when you want * special behavior not provided by the built-in iterators. */ public RuleBasedBreakIterator(String description) { this.description = description; // the actual work is done by the Builder class Builder builder = makeBuilder(); builder.buildBreakIterator(); } /** * Creates a Builder. */ protected Builder makeBuilder() { return new Builder(); } //======================================================================= // boilerplate //======================================================================= /** * Clones this iterator. * @return A newly-constructed RuleBasedBreakIterator with the same * behavior as this one.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -