370 lines
14 KiB
Java
370 lines
14 KiB
Java
/* GENERATED SOURCE. DO NOT MODIFY. */
|
|
// © 2016 and later: Unicode, Inc. and others.
|
|
// License & terms of use: http://www.unicode.org/copyright.html
|
|
/********************************************************************
|
|
* COPYRIGHT:
|
|
* Copyright (c) 2001-2016, International Business Machines Corporation and
|
|
* others. All Rights Reserved.
|
|
********************************************************************/
|
|
|
|
package android.icu.text;
|
|
|
|
import java.util.HashSet;
|
|
import java.util.List;
|
|
import java.util.Set;
|
|
|
|
import android.icu.impl.Assert;
|
|
|
|
/**
|
|
* This class represents a node in the parse tree created by the RBBI Rule compiler.
|
|
*/
|
|
class RBBINode {
|
|
|
|
|
|
// enum NodeType {
|
|
static final int setRef = 0;
|
|
static final int uset = 1;
|
|
static final int varRef = 2;
|
|
static final int leafChar = 3;
|
|
static final int lookAhead = 4;
|
|
static final int tag = 5;
|
|
static final int endMark = 6;
|
|
static final int opStart = 7;
|
|
static final int opCat = 8;
|
|
static final int opOr = 9;
|
|
static final int opStar = 10;
|
|
static final int opPlus = 11;
|
|
static final int opQuestion = 12;
|
|
static final int opBreak = 13;
|
|
static final int opReverse = 14;
|
|
static final int opLParen = 15;
|
|
static final int nodeTypeLimit = 16; // For Assertion checking only.
|
|
|
|
static final String [] nodeTypeNames = {
|
|
"setRef",
|
|
"uset",
|
|
"varRef",
|
|
"leafChar",
|
|
"lookAhead",
|
|
"tag",
|
|
"endMark",
|
|
"opStart",
|
|
"opCat",
|
|
"opOr",
|
|
"opStar",
|
|
"opPlus",
|
|
"opQuestion",
|
|
"opBreak",
|
|
"opReverse",
|
|
"opLParen"
|
|
};
|
|
|
|
// enum OpPrecedence {
|
|
static final int precZero = 0;
|
|
static final int precStart = 1;
|
|
static final int precLParen = 2;
|
|
static final int precOpOr = 3;
|
|
static final int precOpCat = 4;
|
|
|
|
int fType; // enum NodeType
|
|
RBBINode fParent;
|
|
RBBINode fLeftChild;
|
|
RBBINode fRightChild;
|
|
UnicodeSet fInputSet; // For uset nodes only.
|
|
int fPrecedence = precZero; // enum OpPrecedence, For binary ops only.
|
|
|
|
String fText; // Text corresponding to this node.
|
|
// May be lazily evaluated when (if) needed
|
|
// for some node types.
|
|
int fFirstPos; // Position in the rule source string of the
|
|
// first text associated with the node.
|
|
// If there's a left child, this will be the same
|
|
// as that child's left pos.
|
|
int fLastPos; // Last position in the rule source string
|
|
// of any text associated with this node.
|
|
// If there's a right child, this will be the same
|
|
// as that child's last position.
|
|
|
|
boolean fNullable; // See Aho DFA table generation algorithm
|
|
int fVal; // For leafChar nodes, the value.
|
|
// Values are the character category,
|
|
// corresponds to columns in the final
|
|
// state transition table.
|
|
|
|
boolean fLookAheadEnd; // For endMark nodes, set true if
|
|
// marking the end of a look-ahead rule.
|
|
|
|
boolean fRuleRoot; // True if this node is the root of a rule.
|
|
boolean fChainIn; // True if chaining into this rule is allowed
|
|
// (no '^' present).
|
|
|
|
|
|
Set<RBBINode> fFirstPosSet; // See Aho DFA table generation algorithm
|
|
Set<RBBINode> fLastPosSet; // See Aho.
|
|
Set<RBBINode> fFollowPos; // See Aho.
|
|
|
|
int fSerialNum; // Debugging aids. Each node gets a unique serial number.
|
|
static int gLastSerial;
|
|
|
|
RBBINode(int t) {
|
|
Assert.assrt(t < nodeTypeLimit);
|
|
fSerialNum = ++gLastSerial;
|
|
fType = t;
|
|
|
|
fFirstPosSet = new HashSet<RBBINode>();
|
|
fLastPosSet = new HashSet<RBBINode>();
|
|
fFollowPos = new HashSet<RBBINode>();
|
|
if (t == opCat) {
|
|
fPrecedence = precOpCat;
|
|
} else if (t == opOr) {
|
|
fPrecedence = precOpOr;
|
|
} else if (t == opStart) {
|
|
fPrecedence = precStart;
|
|
} else if (t == opLParen) {
|
|
fPrecedence = precLParen;
|
|
} else {
|
|
fPrecedence = precZero;
|
|
}
|
|
}
|
|
|
|
RBBINode(RBBINode other) {
|
|
fSerialNum = ++gLastSerial;
|
|
fType = other.fType;
|
|
fInputSet = other.fInputSet;
|
|
fPrecedence = other.fPrecedence;
|
|
fText = other.fText;
|
|
fFirstPos = other.fFirstPos;
|
|
fLastPos = other.fLastPos;
|
|
fNullable = other.fNullable;
|
|
fVal = other.fVal;
|
|
fRuleRoot = false;
|
|
fChainIn = other.fChainIn;
|
|
fFirstPosSet = new HashSet<RBBINode>(other.fFirstPosSet);
|
|
fLastPosSet = new HashSet<RBBINode>(other.fLastPosSet);
|
|
fFollowPos = new HashSet<RBBINode>(other.fFollowPos);
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// cloneTree Make a copy of the subtree rooted at this node.
|
|
// Discard any variable references encountered along the way,
|
|
// and replace with copies of the variable's definitions.
|
|
// Used to replicate the expression underneath variable
|
|
// references in preparation for generating the DFA tables.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
RBBINode cloneTree() {
|
|
RBBINode n;
|
|
|
|
if (fType == RBBINode.varRef) {
|
|
// If the current node is a variable reference, skip over it
|
|
// and clone the definition of the variable instead.
|
|
n = fLeftChild.cloneTree();
|
|
} else if (fType == RBBINode.uset) {
|
|
n = this;
|
|
} else {
|
|
n = new RBBINode(this);
|
|
if (fLeftChild != null) {
|
|
n.fLeftChild = fLeftChild.cloneTree();
|
|
n.fLeftChild.fParent = n;
|
|
}
|
|
if (fRightChild != null) {
|
|
n.fRightChild = fRightChild.cloneTree();
|
|
n.fRightChild.fParent = n;
|
|
}
|
|
}
|
|
return n;
|
|
}
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// flattenVariables Walk a parse tree, replacing any variable
|
|
// references with a copy of the variable's definition.
|
|
// Aside from variables, the tree is not changed.
|
|
//
|
|
// Return the root of the tree. If the root was not a variable
|
|
// reference, it remains unchanged - the root we started with
|
|
// is the root we return. If, however, the root was a variable
|
|
// reference, the root of the newly cloned replacement tree will
|
|
// be returned, and the original tree deleted.
|
|
//
|
|
// This function works by recursively walking the tree
|
|
// without doing anything until a variable reference is
|
|
// found, then calling cloneTree() at that point. Any
|
|
// nested references are handled by cloneTree(), not here.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
static final private int kRecursiveDepthLimit = 3500;
|
|
RBBINode flattenVariables(int depth) {
|
|
if (depth > kRecursiveDepthLimit) {
|
|
throw new IllegalArgumentException("The input is too long");
|
|
}
|
|
if (fType == varRef) {
|
|
RBBINode retNode = fLeftChild.cloneTree();
|
|
retNode.fRuleRoot = this.fRuleRoot;
|
|
retNode.fChainIn = this.fChainIn;
|
|
return retNode;
|
|
}
|
|
|
|
if (fLeftChild != null) {
|
|
fLeftChild = fLeftChild.flattenVariables(depth+1);
|
|
fLeftChild.fParent = this;
|
|
}
|
|
if (fRightChild != null) {
|
|
fRightChild = fRightChild.flattenVariables(depth+1);
|
|
fRightChild.fParent = this;
|
|
}
|
|
return this;
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// flattenSets Walk the parse tree, replacing any nodes of type setRef
|
|
// with a copy of the expression tree for the set. A set's
|
|
// equivalent expression tree is precomputed and saved as
|
|
// the left child of the uset node.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void flattenSets() {
|
|
Assert.assrt(fType != setRef);
|
|
|
|
if (fLeftChild != null) {
|
|
if (fLeftChild.fType == setRef) {
|
|
RBBINode setRefNode = fLeftChild;
|
|
RBBINode usetNode = setRefNode.fLeftChild;
|
|
RBBINode replTree = usetNode.fLeftChild;
|
|
fLeftChild = replTree.cloneTree();
|
|
fLeftChild.fParent = this;
|
|
} else {
|
|
fLeftChild.flattenSets();
|
|
}
|
|
}
|
|
|
|
if (fRightChild != null) {
|
|
if (fRightChild.fType == setRef) {
|
|
RBBINode setRefNode = fRightChild;
|
|
RBBINode usetNode = setRefNode.fLeftChild;
|
|
RBBINode replTree = usetNode.fLeftChild;
|
|
fRightChild = replTree.cloneTree();
|
|
fRightChild.fParent = this;
|
|
// delete setRefNode;
|
|
} else {
|
|
fRightChild.flattenSets();
|
|
}
|
|
}
|
|
}
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// findNodes() Locate all the nodes of the specified type, starting
|
|
// at the specified root.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
void findNodes(List<RBBINode> dest, int kind) {
|
|
if (fType == kind) {
|
|
dest.add(this);
|
|
}
|
|
if (fLeftChild != null) {
|
|
fLeftChild.findNodes(dest, kind);
|
|
}
|
|
if (fRightChild != null) {
|
|
fRightChild.findNodes(dest, kind);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
//-------------------------------------------------------------------------
|
|
//
|
|
// print. Print out a single node, for debugging.
|
|
//
|
|
//-------------------------------------------------------------------------
|
|
///CLOVER:OFF
|
|
static void printNode(RBBINode n) {
|
|
|
|
if (n==null) {
|
|
System.out.print (" -- null --\n");
|
|
} else {
|
|
RBBINode.printInt( n.fSerialNum, 10);
|
|
RBBINode.printString(nodeTypeNames[n.fType], 11);
|
|
RBBINode.printInt(n.fParent==null? 0 : n.fParent.fSerialNum, 11);
|
|
RBBINode.printInt(n.fLeftChild==null? 0 : n.fLeftChild.fSerialNum, 11);
|
|
RBBINode.printInt(n.fRightChild==null? 0 : n.fRightChild.fSerialNum, 12);
|
|
RBBINode.printInt(n.fFirstPos, 12);
|
|
RBBINode.printInt(n.fVal, 7);
|
|
|
|
if (n.fType == varRef) {
|
|
System.out.print(" " + n.fText);
|
|
}
|
|
}
|
|
System.out.println("");
|
|
}
|
|
///CLOVER:ON
|
|
|
|
|
|
// Print a String in a fixed field size.
|
|
// Debugging function.
|
|
///CLOVER:OFF
|
|
static void printString(String s, int minWidth) {
|
|
for (int i = minWidth; i < 0; i++) {
|
|
// negative width means pad leading spaces, not fixed width.
|
|
System.out.print(' ');
|
|
}
|
|
for (int i = s.length(); i < minWidth; i++) {
|
|
System.out.print(' ');
|
|
}
|
|
System.out.print(s);
|
|
}
|
|
///CLOVER:ON
|
|
|
|
//
|
|
// Print an int in a fixed size field.
|
|
// Debugging function.
|
|
//
|
|
///CLOVER:OFF
|
|
static void printInt(int i, int minWidth) {
|
|
String s = Integer.toString(i);
|
|
printString(s, Math.max(minWidth, s.length() + 1));
|
|
}
|
|
///CLOVER:ON
|
|
|
|
///CLOVER:OFF
|
|
static void printHex(int i, int minWidth) {
|
|
String s = Integer.toString(i, 16);
|
|
String leadingZeroes = "00000"
|
|
.substring(0, Math.max(0, 5 - s.length()));
|
|
s = leadingZeroes + s;
|
|
printString(s, minWidth);
|
|
}
|
|
///CLOVER:ON
|
|
|
|
|
|
// -------------------------------------------------------------------------
|
|
//
|
|
// print. Print out the tree of nodes rooted at "this"
|
|
//
|
|
// -------------------------------------------------------------------------
|
|
///CLOVER:OFF
|
|
void printTree(boolean printHeading) {
|
|
if (printHeading) {
|
|
System.out.println( "-------------------------------------------------------------------");
|
|
System.out.println(" Serial type Parent LeftChild RightChild position value");
|
|
}
|
|
printNode(this);
|
|
// Only dump the definition under a variable reference if asked to.
|
|
// Unconditionally dump children of all other node types.
|
|
if (fType != varRef) {
|
|
if (fLeftChild != null) {
|
|
fLeftChild.printTree(false);
|
|
}
|
|
|
|
if (fRightChild != null) {
|
|
fRightChild.printTree(false);
|
|
}
|
|
}
|
|
}
|
|
///CLOVER:ON
|
|
|
|
}
|