/* */ package com.ibm.icu.text;
/* */
/* */ import com.ibm.icu.impl.IllegalIcuArgumentException;
/* */ import com.ibm.icu.impl.PatternProps;
/* */ import com.ibm.icu.impl.Utility;
/* */ import com.ibm.icu.lang.UCharacter;
/* */ import java.text.ParsePosition;
/* */ import java.util.ArrayList;
/* */ import java.util.HashMap;
/* */ import java.util.List;
/* */ import java.util.Map;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ class TransliteratorParser
/* */ {
/* */ public List<RuleBasedTransliterator.Data> dataVector;
/* */ public List<String> idBlockVector;
/* */ private RuleBasedTransliterator.Data curData;
/* */ public UnicodeSet compoundFilter;
/* */ private int direction;
/* */ private ParseData parseData;
/* */ private List<Object> variablesVector;
/* */ private Map<String, char[]> variableNames;
/* */ private StringBuffer segmentStandins;
/* */ private List<StringMatcher> segmentObjects;
/* */ private char variableNext;
/* */ private char variableLimit;
/* */ private String undefinedVariableName;
/* 116 */ private int dotStandIn = -1;
/* */
/* */
/* */ private static final String ID_TOKEN = "::";
/* */
/* */
/* */ private static final int ID_TOKEN_LEN = 2;
/* */
/* */
/* */ private static final char VARIABLE_DEF_OP = '=';
/* */
/* */
/* */ private static final char FORWARD_RULE_OP = '>';
/* */
/* */
/* */ private static final char REVERSE_RULE_OP = '<';
/* */
/* */
/* */ private static final char FWDREV_RULE_OP = '~';
/* */
/* */ private static final String OPERATORS = "=><←→↔";
/* */
/* */ private static final String HALF_ENDERS = "=><←→↔;";
/* */
/* */ private static final char QUOTE = '\'';
/* */
/* */ private static final char ESCAPE = '\\';
/* */
/* */ private static final char END_OF_RULE = ';';
/* */
/* */ private static final char RULE_COMMENT_CHAR = '#';
/* */
/* */ private static final char CONTEXT_ANTE = '{';
/* */
/* */ private static final char CONTEXT_POST = '}';
/* */
/* */ private static final char CURSOR_POS = '|';
/* */
/* */ private static final char CURSOR_OFFSET = '@';
/* */
/* */ private static final char ANCHOR_START = '^';
/* */
/* */ private static final char KLEENE_STAR = '*';
/* */
/* */ private static final char ONE_OR_MORE = '+';
/* */
/* */ private static final char ZERO_OR_ONE = '?';
/* */
/* */ private static final char DOT = '.';
/* */
/* */ private static final String DOT_SET = "[^[:Zp:][:Zl:]\\r\\n$]";
/* */
/* */ private static final char SEGMENT_OPEN = '(';
/* */
/* */ private static final char SEGMENT_CLOSE = ')';
/* */
/* */ private static final char FUNCTION = '&';
/* */
/* */ private static final char ALT_REVERSE_RULE_OP = '←';
/* */
/* */ private static final char ALT_FORWARD_RULE_OP = '→';
/* */
/* */ private static final char ALT_FWDREV_RULE_OP = '↔';
/* */
/* */ private static final char ALT_FUNCTION = '∆';
/* */
/* 182 */ private static UnicodeSet ILLEGAL_TOP = new UnicodeSet("[\\)]");
/* */
/* */
/* 185 */ private static UnicodeSet ILLEGAL_SEG = new UnicodeSet("[\\{\\}\\|\\@]");
/* */
/* */
/* 188 */ private static UnicodeSet ILLEGAL_FUNC = new UnicodeSet("[\\^\\(\\.\\*\\+\\?\\{\\}\\|\\@]");
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private class ParseData
/* */ implements SymbolTable
/* */ {
/* */ private ParseData() {}
/* */
/* */
/* */
/* */
/* */
/* */ public char[] lookup(String name)
/* */ {
/* 206 */ return (char[])TransliteratorParser.this.variableNames.get(name);
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */ public UnicodeMatcher lookupMatcher(int ch)
/* */ {
/* 215 */ int i = ch - TransliteratorParser.this.curData.variablesBase;
/* 216 */ if ((i >= 0) && (i < TransliteratorParser.this.variablesVector.size())) {
/* 217 */ return (UnicodeMatcher)TransliteratorParser.this.variablesVector.get(i);
/* */ }
/* 219 */ return null;
/* */ }
/* */
/* */
/* */
/* */
/* */ public String parseReference(String text, ParsePosition pos, int limit)
/* */ {
/* 227 */ int start = pos.getIndex();
/* 228 */ int i = start;
/* 229 */ while (i < limit) {
/* 230 */ char c = text.charAt(i);
/* 231 */ if (((i == start) && (!UCharacter.isUnicodeIdentifierStart(c))) || (!UCharacter.isUnicodeIdentifierPart(c))) {
/* */ break;
/* */ }
/* */
/* 235 */ i++;
/* */ }
/* 237 */ if (i == start) {
/* 238 */ return null;
/* */ }
/* 240 */ pos.setIndex(i);
/* 241 */ return text.substring(start, i);
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public boolean isMatcher(int ch)
/* */ {
/* 251 */ int i = ch - TransliteratorParser.this.curData.variablesBase;
/* 252 */ if ((i >= 0) && (i < TransliteratorParser.this.variablesVector.size())) {
/* 253 */ return TransliteratorParser.this.variablesVector.get(i) instanceof UnicodeMatcher;
/* */ }
/* 255 */ return true;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public boolean isReplacer(int ch)
/* */ {
/* 265 */ int i = ch - TransliteratorParser.this.curData.variablesBase;
/* 266 */ if ((i >= 0) && (i < TransliteratorParser.this.variablesVector.size())) {
/* 267 */ return TransliteratorParser.this.variablesVector.get(i) instanceof UnicodeReplacer;
/* */ }
/* 269 */ return true;
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private static abstract class RuleBody
/* */ {
/* */ String nextLine()
/* */ {
/* 293 */ String s = handleNextLine();
/* 294 */ if ((s != null) && (s.length() > 0) && (s.charAt(s.length() - 1) == '\\'))
/* */ {
/* */
/* 297 */ StringBuilder b = new StringBuilder(s);
/* */ do {
/* 299 */ b.deleteCharAt(b.length() - 1);
/* 300 */ s = handleNextLine();
/* 301 */ if (s == null) {
/* */ break;
/* */ }
/* 304 */ b.append(s);
/* */ }
/* 306 */ while ((s.length() > 0) && (s.charAt(s.length() - 1) == '\\'));
/* 307 */ s = b.toString();
/* */ }
/* 309 */ return s;
/* */ }
/* */
/* */
/* */ abstract void reset();
/* */
/* */
/* */ abstract String handleNextLine();
/* */ }
/* */
/* */
/* */ private static class RuleArray
/* */ extends TransliteratorParser.RuleBody
/* */ {
/* */ String[] array;
/* */
/* */ int i;
/* */
/* */ public RuleArray(String[] array)
/* */ {
/* 329 */ super();this.array = array;this.i = 0; }
/* */
/* 331 */ public String handleNextLine() { return this.i < this.array.length ? this.array[(this.i++)] : null; }
/* */
/* */ public void reset() {
/* 334 */ this.i = 0;
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private static class RuleHalf
/* */ {
/* */ public String text;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 368 */ public int cursor = -1;
/* 369 */ public int ante = -1;
/* 370 */ public int post = -1;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 381 */ public int cursorOffset = 0;
/* */
/* */
/* */
/* 385 */ private int cursorOffsetPos = 0;
/* */
/* 387 */ public boolean anchorStart = false;
/* 388 */ public boolean anchorEnd = false;
/* */
/* */
/* */
/* */
/* */
/* 394 */ private int nextSegmentNumber = 1;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public int parse(String rule, int pos, int limit, TransliteratorParser parser)
/* */ {
/* 404 */ int start = pos;
/* 405 */ StringBuffer buf = new StringBuffer();
/* 406 */ pos = parseSection(rule, pos, limit, parser, buf, TransliteratorParser.ILLEGAL_TOP, false);
/* 407 */ this.text = buf.toString();
/* */
/* 409 */ if ((this.cursorOffset > 0) && (this.cursor != this.cursorOffsetPos)) {
/* 410 */ TransliteratorParser.syntaxError("Misplaced |", rule, start);
/* */ }
/* */
/* 413 */ return pos;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private int parseSection(String rule, int pos, int limit, TransliteratorParser parser, StringBuffer buf, UnicodeSet illegal, boolean isSegment)
/* */ {
/* 444 */ int start = pos;
/* 445 */ ParsePosition pp = null;
/* 446 */ int quoteStart = -1;
/* 447 */ int quoteLimit = -1;
/* 448 */ int varStart = -1;
/* 449 */ int varLimit = -1;
/* 450 */ int[] iref = new int[1];
/* 451 */ int bufStart = buf.length();
/* */
/* */
/* 454 */ while (pos < limit)
/* */ {
/* */
/* 457 */ char c = rule.charAt(pos++);
/* 458 */ if (!PatternProps.isWhiteSpace(c))
/* */ {
/* */
/* */
/* 462 */ if ("=><←→↔;".indexOf(c) >= 0)
/* */ {
/* */
/* 465 */ if (!isSegment) break;
/* 466 */ TransliteratorParser.syntaxError("Unclosed segment", rule, start); break;
/* */ }
/* */
/* */
/* */
/* 471 */ if (this.anchorEnd)
/* */ {
/* 473 */ TransliteratorParser.syntaxError("Malformed variable reference", rule, start);
/* */ }
/* 475 */ if (UnicodeSet.resemblesPattern(rule, pos - 1)) {
/* 476 */ if (pp == null) {
/* 477 */ pp = new ParsePosition(0);
/* */ }
/* 479 */ pp.setIndex(pos - 1);
/* 480 */ buf.append(parser.parseSet(rule, pp));
/* 481 */ pos = pp.getIndex();
/* */
/* */
/* */ }
/* 485 */ else if (c == '\\') {
/* 486 */ if (pos == limit) {
/* 487 */ TransliteratorParser.syntaxError("Trailing backslash", rule, start);
/* */ }
/* 489 */ iref[0] = pos;
/* 490 */ int escaped = Utility.unescapeAt(rule, iref);
/* 491 */ pos = iref[0];
/* 492 */ if (escaped == -1) {
/* 493 */ TransliteratorParser.syntaxError("Malformed escape", rule, start);
/* */ }
/* 495 */ parser.checkVariableRange(escaped, rule, start);
/* 496 */ UTF16.append(buf, escaped);
/* */
/* */
/* */ }
/* 500 */ else if (c == '\'') {
/* 501 */ int iq = rule.indexOf('\'', pos);
/* 502 */ if (iq == pos) {
/* 503 */ buf.append(c);
/* 504 */ pos++;
/* */
/* */
/* */ }
/* */ else
/* */ {
/* */
/* */
/* 512 */ quoteStart = buf.length();
/* */ for (;;) {
/* 514 */ if (iq < 0) {
/* 515 */ TransliteratorParser.syntaxError("Unterminated quote", rule, start);
/* */ }
/* 517 */ buf.append(rule.substring(pos, iq));
/* 518 */ pos = iq + 1;
/* 519 */ if ((pos >= limit) || (rule.charAt(pos) != '\''))
/* */ break;
/* 521 */ iq = rule.indexOf('\'', pos + 1);
/* */ }
/* */
/* */
/* */
/* */
/* 527 */ quoteLimit = buf.length();
/* */
/* 529 */ for (iq = quoteStart; iq < quoteLimit; iq++) {
/* 530 */ parser.checkVariableRange(buf.charAt(iq), rule, start);
/* */ }
/* */ }
/* */ }
/* */ else
/* */ {
/* 536 */ parser.checkVariableRange(c, rule, start);
/* */
/* 538 */ if (illegal.contains(c)) {
/* 539 */ TransliteratorParser.syntaxError("Illegal character '" + c + '\'', rule, start);
/* */ }
/* */
/* 542 */ switch (c)
/* */ {
/* */
/* */
/* */
/* */ case '^':
/* 548 */ if ((buf.length() == 0) && (!this.anchorStart)) {
/* 549 */ this.anchorStart = true;
/* */ } else {
/* 551 */ TransliteratorParser.syntaxError("Misplaced anchor start", rule, start);
/* */ }
/* */
/* 554 */ break;
/* */
/* */
/* */
/* */ case '(':
/* 559 */ int bufSegStart = buf.length();
/* */
/* */
/* */
/* */
/* 564 */ int segmentNumber = this.nextSegmentNumber++;
/* */
/* */
/* 567 */ pos = parseSection(rule, pos, limit, parser, buf, TransliteratorParser.ILLEGAL_SEG, true);
/* */
/* */
/* */
/* */
/* */
/* 573 */ StringMatcher m = new StringMatcher(buf.substring(bufSegStart), segmentNumber, parser.curData);
/* */
/* */
/* */
/* */
/* 578 */ parser.setSegmentObject(segmentNumber, m);
/* 579 */ buf.setLength(bufSegStart);
/* 580 */ buf.append(parser.getSegmentStandin(segmentNumber));
/* */
/* 582 */ break;
/* */
/* */ case '&':
/* */ case '∆':
/* 586 */ iref[0] = pos;
/* 587 */ TransliteratorIDParser.SingleID single = TransliteratorIDParser.parseFilterID(rule, iref);
/* */
/* 589 */ if ((single == null) || (!Utility.parseChar(rule, iref, '(')))
/* */ {
/* 591 */ TransliteratorParser.syntaxError("Invalid function", rule, start);
/* */ }
/* */
/* 594 */ Transliterator t = single.getInstance();
/* 595 */ if (t == null) {
/* 596 */ TransliteratorParser.syntaxError("Invalid function ID", rule, start);
/* */ }
/* */
/* */
/* */
/* 601 */ int bufSegStart = buf.length();
/* */
/* */
/* 604 */ pos = parseSection(rule, iref[0], limit, parser, buf, TransliteratorParser.ILLEGAL_FUNC, true);
/* */
/* */
/* */
/* 608 */ FunctionReplacer r = new FunctionReplacer(t, new StringReplacer(buf.substring(bufSegStart), parser.curData));
/* */
/* */
/* */
/* */
/* 613 */ buf.setLength(bufSegStart);
/* 614 */ buf.append(parser.generateStandInFor(r));
/* */
/* 616 */ break;
/* */
/* */
/* */
/* */
/* */
/* */
/* */ case '$':
/* 624 */ if (pos == limit)
/* */ {
/* */
/* 627 */ this.anchorEnd = true;
/* */ }
/* */ else
/* */ {
/* 631 */ c = rule.charAt(pos);
/* 632 */ int r = UCharacter.digit(c, 10);
/* 633 */ if ((r >= 1) && (r <= 9)) {
/* 634 */ iref[0] = pos;
/* 635 */ r = Utility.parseNumber(rule, iref, 10);
/* 636 */ if (r < 0) {
/* 637 */ TransliteratorParser.syntaxError("Undefined segment reference", rule, start);
/* */ }
/* */
/* 640 */ pos = iref[0];
/* 641 */ buf.append(parser.getSegmentStandin(r));
/* */ } else {
/* 643 */ if (pp == null) {
/* 644 */ pp = new ParsePosition(0);
/* */ }
/* 646 */ pp.setIndex(pos);
/* 647 */ String name = parser.parseData.parseReference(rule, pp, limit);
/* */
/* 649 */ if (name == null)
/* */ {
/* */
/* */
/* */
/* */
/* 655 */ this.anchorEnd = true;
/* */ }
/* */ else {
/* 658 */ pos = pp.getIndex();
/* */
/* */
/* */
/* */
/* 663 */ varStart = buf.length();
/* 664 */ parser.appendVariableDef(name, buf);
/* 665 */ varLimit = buf.length();
/* */ }
/* */ } }
/* 668 */ break;
/* */ case '.':
/* 670 */ buf.append(parser.getDotStandIn());
/* 671 */ break;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ case '*':
/* */ case '+':
/* */ case '?':
/* 684 */ if ((isSegment) && (buf.length() == bufStart))
/* */ {
/* 686 */ TransliteratorParser.syntaxError("Misplaced quantifier", rule, start);
/* */ }
/* */ else
/* */ {
/* */ int qlimit;
/* */
/* */ int qstart;
/* */ int qlimit;
/* 694 */ if (buf.length() == quoteLimit)
/* */ {
/* 696 */ int qstart = quoteStart;
/* 697 */ qlimit = quoteLimit; } else { int qlimit;
/* 698 */ if (buf.length() == varLimit)
/* */ {
/* 700 */ int qstart = varStart;
/* 701 */ qlimit = varLimit;
/* */ }
/* */ else
/* */ {
/* 705 */ qstart = buf.length() - 1;
/* 706 */ qlimit = qstart + 1;
/* */ }
/* */ }
/* */ try
/* */ {
/* 711 */ m = new StringMatcher(buf.toString(), qstart, qlimit, 0, parser.curData);
/* */ }
/* */ catch (RuntimeException e) {
/* 714 */ String precontext = "..." + rule.substring(pos - 50, pos);
/* 715 */ String postContext = rule.substring(pos, pos + 50) + "...";
/* 716 */ throw new IllegalIcuArgumentException("Failure in rule: " + precontext + "$$$" + postContext).initCause(e);
/* */ }
/* */
/* */
/* 720 */ int min = 0;
/* 721 */ int max = Integer.MAX_VALUE;
/* 722 */ switch (c) {
/* */ case '+':
/* 724 */ min = 1;
/* 725 */ break;
/* */ case '?':
/* 727 */ min = 0;
/* 728 */ max = 1;
/* */ }
/* */
/* */
/* */
/* 733 */ UnicodeMatcher m = new Quantifier(m, min, max);
/* 734 */ buf.setLength(qstart);
/* 735 */ buf.append(parser.generateStandInFor(m));
/* */ }
/* 737 */ break;
/* */
/* */
/* */
/* */
/* */
/* */ case ')':
/* */ break;
/* */
/* */
/* */
/* */
/* */
/* */ case '{':
/* 751 */ if (this.ante >= 0) {
/* 752 */ TransliteratorParser.syntaxError("Multiple ante contexts", rule, start);
/* */ }
/* 754 */ this.ante = buf.length();
/* 755 */ break;
/* */ case '}':
/* 757 */ if (this.post >= 0) {
/* 758 */ TransliteratorParser.syntaxError("Multiple post contexts", rule, start);
/* */ }
/* 760 */ this.post = buf.length();
/* 761 */ break;
/* */ case '|':
/* 763 */ if (this.cursor >= 0) {
/* 764 */ TransliteratorParser.syntaxError("Multiple cursors", rule, start);
/* */ }
/* 766 */ this.cursor = buf.length();
/* 767 */ break;
/* */ case '@':
/* 769 */ if (this.cursorOffset < 0) {
/* 770 */ if (buf.length() > 0) {
/* 771 */ TransliteratorParser.syntaxError("Misplaced " + c, rule, start);
/* */ }
/* 773 */ this.cursorOffset -= 1;
/* 774 */ } else if (this.cursorOffset > 0) {
/* 775 */ if ((buf.length() != this.cursorOffsetPos) || (this.cursor >= 0)) {
/* 776 */ TransliteratorParser.syntaxError("Misplaced " + c, rule, start);
/* */ }
/* 778 */ this.cursorOffset += 1;
/* */ }
/* 780 */ else if ((this.cursor == 0) && (buf.length() == 0)) {
/* 781 */ this.cursorOffset = -1;
/* 782 */ } else if (this.cursor < 0) {
/* 783 */ this.cursorOffsetPos = buf.length();
/* 784 */ this.cursorOffset = 1;
/* */ } else {
/* 786 */ TransliteratorParser.syntaxError("Misplaced " + c, rule, start);
/* */ }
/* */
/* 789 */ break;
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ default:
/* 798 */ if ((c >= '!') && (c <= '~') && ((c < '0') || (c > '9')) && ((c < 'A') || (c > 'Z')) && ((c < 'a') || (c > 'z')))
/* */ {
/* */
/* */
/* 802 */ TransliteratorParser.syntaxError("Unquoted " + c, rule, start);
/* */ }
/* 804 */ buf.append(c); }
/* */
/* */ }
/* */ } }
/* 808 */ return pos;
/* */ }
/* */
/* */
/* */
/* */ void removeContext()
/* */ {
/* 815 */ this.text = this.text.substring(this.ante < 0 ? 0 : this.ante, this.post < 0 ? this.text.length() : this.post);
/* */
/* 817 */ this.ante = (this.post = -1);
/* 818 */ this.anchorStart = (this.anchorEnd = 0);
/* */ }
/* */
/* */
/* */
/* */
/* */ public boolean isValidOutput(TransliteratorParser parser)
/* */ {
/* 826 */ for (int i = 0; i < this.text.length();) {
/* 827 */ int c = UTF16.charAt(this.text, i);
/* 828 */ i += UTF16.getCharCount(c);
/* 829 */ if (!parser.parseData.isReplacer(c)) {
/* 830 */ return false;
/* */ }
/* */ }
/* 833 */ return true;
/* */ }
/* */
/* */
/* */
/* */
/* */ public boolean isValidInput(TransliteratorParser parser)
/* */ {
/* 841 */ for (int i = 0; i < this.text.length();) {
/* 842 */ int c = UTF16.charAt(this.text, i);
/* 843 */ i += UTF16.getCharCount(c);
/* 844 */ if (!parser.parseData.isMatcher(c)) {
/* 845 */ return false;
/* */ }
/* */ }
/* 848 */ return true;
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public void parse(String rules, int dir)
/* */ {
/* 867 */ parseRules(new RuleArray(new String[] { rules }), dir);
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ void parseRules(RuleBody ruleArray, int dir)
/* */ {
/* 896 */ boolean parsingIDs = true;
/* 897 */ int ruleCount = 0;
/* */
/* 899 */ this.dataVector = new ArrayList();
/* 900 */ this.idBlockVector = new ArrayList();
/* 901 */ this.curData = null;
/* 902 */ this.direction = dir;
/* 903 */ this.compoundFilter = null;
/* 904 */ this.variablesVector = new ArrayList();
/* 905 */ this.variableNames = new HashMap();
/* 906 */ this.parseData = new ParseData(null);
/* */
/* 908 */ List<RuntimeException> errors = new ArrayList();
/* 909 */ int errorCount = 0;
/* */
/* 911 */ ruleArray.reset();
/* */
/* 913 */ StringBuilder idBlockResult = new StringBuilder();
/* */
/* */
/* */
/* */
/* */
/* */
/* 920 */ this.compoundFilter = null;
/* 921 */ int compoundFilterOffset = -1;
/* */
/* */ for (;;)
/* */ {
/* 925 */ String rule = ruleArray.nextLine();
/* 926 */ if (rule == null) {
/* */ break;
/* */ }
/* 929 */ int pos = 0;
/* 930 */ int limit = rule.length();
/* 931 */ while (pos < limit) {
/* 932 */ char c = rule.charAt(pos++);
/* 933 */ if (!PatternProps.isWhiteSpace(c))
/* */ {
/* */
/* */
/* 937 */ if (c == '#') {
/* 938 */ pos = rule.indexOf("\n", pos) + 1;
/* 939 */ if (pos == 0)
/* */ {
/* */ break;
/* */ }
/* */
/* */
/* */ }
/* 946 */ else if (c != ';')
/* */ {
/* */
/* */
/* */ try
/* */ {
/* */
/* */
/* 954 */ ruleCount++;
/* */
/* */
/* */
/* 958 */ pos--;
/* */
/* */
/* 961 */ if ((pos + 2 + 1 <= limit) && (rule.regionMatches(pos, "::", 0, 2)))
/* */ {
/* 963 */ pos += 2;
/* 964 */ c = rule.charAt(pos);
/* 965 */ while ((PatternProps.isWhiteSpace(c)) && (pos < limit)) {
/* 966 */ pos++;
/* 967 */ c = rule.charAt(pos);
/* */ }
/* 969 */ int[] p = { pos };
/* */
/* 971 */ if (!parsingIDs) {
/* 972 */ if (this.curData != null) {
/* 973 */ if (this.direction == 0) {
/* 974 */ this.dataVector.add(this.curData);
/* */ } else
/* 976 */ this.dataVector.add(0, this.curData);
/* 977 */ this.curData = null;
/* */ }
/* 979 */ parsingIDs = true;
/* */ }
/* */
/* 982 */ TransliteratorIDParser.SingleID id = TransliteratorIDParser.parseSingleID(rule, p, this.direction);
/* */
/* */
/* 985 */ if ((p[0] != pos) && (Utility.parseChar(rule, p, ';')))
/* */ {
/* */
/* 988 */ if (this.direction == 0) {
/* 989 */ idBlockResult.append(id.canonID).append(';');
/* */ } else {
/* 991 */ idBlockResult.insert(0, id.canonID + ';');
/* */ }
/* */ }
/* */ else
/* */ {
/* 996 */ int[] withParens = { -1 };
/* 997 */ UnicodeSet f = TransliteratorIDParser.parseGlobalFilter(rule, p, this.direction, withParens, null);
/* 998 */ if ((f != null) && (Utility.parseChar(rule, p, ';'))) {
/* 999 */ if ((this.direction == 0 ? 1 : 0) == (withParens[0] == 0 ? 1 : 0))
/* */ {
/* 1001 */ if (this.compoundFilter != null)
/* */ {
/* 1003 */ syntaxError("Multiple global filters", rule, pos);
/* */ }
/* 1005 */ this.compoundFilter = f;
/* 1006 */ compoundFilterOffset = ruleCount;
/* */ }
/* */
/* */ }
/* */ else {
/* 1011 */ syntaxError("Invalid ::ID", rule, pos);
/* */ }
/* */ }
/* */
/* 1015 */ pos = p[0];
/* */ } else {
/* 1017 */ if (parsingIDs) {
/* 1018 */ if (this.direction == 0) {
/* 1019 */ this.idBlockVector.add(idBlockResult.toString());
/* */ } else
/* 1021 */ this.idBlockVector.add(0, idBlockResult.toString());
/* 1022 */ idBlockResult.delete(0, idBlockResult.length());
/* 1023 */ parsingIDs = false;
/* 1024 */ this.curData = new RuleBasedTransliterator.Data();
/* */
/* */
/* */
/* */
/* */
/* 1030 */ setVariableRange(61440, 63743);
/* */ }
/* */
/* 1033 */ if (resemblesPragma(rule, pos, limit)) {
/* 1034 */ int ppp = parsePragma(rule, pos, limit);
/* 1035 */ if (ppp < 0) {
/* 1036 */ syntaxError("Unrecognized pragma", rule, pos);
/* */ }
/* 1038 */ pos = ppp;
/* */ }
/* */ else {
/* 1041 */ pos = parseRule(rule, pos, limit);
/* */ }
/* */ }
/* */ } catch (IllegalArgumentException e) {
/* 1045 */ if (errorCount == 30) {
/* 1046 */ IllegalIcuArgumentException icuEx = new IllegalIcuArgumentException("\nMore than 30 errors; further messages squelched");
/* 1047 */ icuEx.initCause(e);
/* 1048 */ errors.add(icuEx);
/* */ break label766;
/* */ }
/* 1051 */ e.fillInStackTrace();
/* 1052 */ errors.add(e);
/* 1053 */ errorCount++;
/* 1054 */ pos = ruleEnd(rule, pos, limit) + 1;
/* */ }
/* */ } } } }
/* */ label766:
/* 1058 */ if ((parsingIDs) && (idBlockResult.length() > 0)) {
/* 1059 */ if (this.direction == 0) {
/* 1060 */ this.idBlockVector.add(idBlockResult.toString());
/* */ } else {
/* 1062 */ this.idBlockVector.add(0, idBlockResult.toString());
/* */ }
/* 1064 */ } else if ((!parsingIDs) && (this.curData != null)) {
/* 1065 */ if (this.direction == 0) {
/* 1066 */ this.dataVector.add(this.curData);
/* */ } else {
/* 1068 */ this.dataVector.add(0, this.curData);
/* */ }
/* */ }
/* */
/* 1072 */ for (int i = 0; i < this.dataVector.size(); i++) {
/* 1073 */ RuleBasedTransliterator.Data data = (RuleBasedTransliterator.Data)this.dataVector.get(i);
/* 1074 */ data.variables = new Object[this.variablesVector.size()];
/* 1075 */ this.variablesVector.toArray(data.variables);
/* 1076 */ data.variableNames = new HashMap();
/* 1077 */ data.variableNames.putAll(this.variableNames);
/* */ }
/* 1079 */ this.variablesVector = null;
/* */
/* */ try
/* */ {
/* 1083 */ if ((this.compoundFilter != null) && (
/* 1084 */ ((this.direction == 0) && (compoundFilterOffset != 1)) || ((this.direction == 1) && (compoundFilterOffset != ruleCount))))
/* */ {
/* */
/* */
/* 1088 */ throw new IllegalIcuArgumentException("Compound filters misplaced");
/* */ }
/* */
/* */
/* 1092 */ for (int i = 0; i < this.dataVector.size(); i++) {
/* 1093 */ RuleBasedTransliterator.Data data = (RuleBasedTransliterator.Data)this.dataVector.get(i);
/* 1094 */ data.ruleSet.freeze();
/* */ }
/* */
/* 1097 */ if ((this.idBlockVector.size() == 1) && (((String)this.idBlockVector.get(0)).length() == 0)) {
/* 1098 */ this.idBlockVector.remove(0);
/* */ }
/* */ } catch (IllegalArgumentException e) {
/* 1101 */ e.fillInStackTrace();
/* 1102 */ errors.add(e);
/* */ }
/* */
/* 1105 */ if (errors.size() != 0) {
/* 1106 */ for (int i = errors.size() - 1; i > 0; i--) {
/* 1107 */ RuntimeException previous = (RuntimeException)errors.get(i - 1);
/* 1108 */ while (previous.getCause() != null) {
/* 1109 */ previous = (RuntimeException)previous.getCause();
/* */ }
/* 1111 */ previous.initCause((Throwable)errors.get(i));
/* */ }
/* 1113 */ throw ((RuntimeException)errors.get(0));
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private int parseRule(String rule, int pos, int limit)
/* */ {
/* 1135 */ int start = pos;
/* 1136 */ char operator = '\000';
/* */
/* */
/* 1139 */ this.segmentStandins = new StringBuffer();
/* 1140 */ this.segmentObjects = new ArrayList();
/* */
/* 1142 */ RuleHalf left = new RuleHalf(null);
/* 1143 */ RuleHalf right = new RuleHalf(null);
/* */
/* 1145 */ this.undefinedVariableName = null;
/* 1146 */ pos = left.parse(rule, pos, limit, this);
/* */
/* 1148 */ if ((pos == limit) || ("=><←→↔".indexOf(operator = rule.charAt(--pos)) < 0))
/* */ {
/* 1150 */ syntaxError("No operator pos=" + pos, rule, start);
/* */ }
/* 1152 */ pos++;
/* */
/* */
/* 1155 */ if ((operator == '<') && (pos < limit) && (rule.charAt(pos) == '>'))
/* */ {
/* 1157 */ pos++;
/* 1158 */ operator = '~';
/* */ }
/* */
/* */
/* 1162 */ switch (operator) {
/* */ case '→':
/* 1164 */ operator = '>';
/* 1165 */ break;
/* */ case '←':
/* 1167 */ operator = '<';
/* 1168 */ break;
/* */ case '↔':
/* 1170 */ operator = '~';
/* */ }
/* */
/* */
/* 1174 */ pos = right.parse(rule, pos, limit, this);
/* */
/* 1176 */ if (pos < limit) {
/* 1177 */ if (rule.charAt(--pos) == ';') {
/* 1178 */ pos++;
/* */ }
/* */ else {
/* 1181 */ syntaxError("Unquoted operator", rule, start);
/* */ }
/* */ }
/* */
/* 1185 */ if (operator == '=')
/* */ {
/* */
/* */
/* */
/* */
/* */
/* */
/* 1193 */ if (this.undefinedVariableName == null) {
/* 1194 */ syntaxError("Missing '$' or duplicate definition", rule, start);
/* */ }
/* 1196 */ if ((left.text.length() != 1) || (left.text.charAt(0) != this.variableLimit)) {
/* 1197 */ syntaxError("Malformed LHS", rule, start);
/* */ }
/* 1199 */ if ((left.anchorStart) || (left.anchorEnd) || (right.anchorStart) || (right.anchorEnd))
/* */ {
/* 1201 */ syntaxError("Malformed variable def", rule, start);
/* */ }
/* */
/* 1204 */ int n = right.text.length();
/* 1205 */ char[] value = new char[n];
/* 1206 */ right.text.getChars(0, n, value, 0);
/* 1207 */ this.variableNames.put(this.undefinedVariableName, value);
/* */
/* 1209 */ this.variableLimit = ((char)(this.variableLimit + '\001'));
/* 1210 */ return pos;
/* */ }
/* */
/* */
/* */
/* 1215 */ if (this.undefinedVariableName != null) {
/* 1216 */ syntaxError("Undefined variable $" + this.undefinedVariableName, rule, start);
/* */ }
/* */
/* */
/* */
/* 1221 */ if (this.segmentStandins.length() > this.segmentObjects.size()) {
/* 1222 */ syntaxError("Undefined segment reference", rule, start);
/* */ }
/* 1224 */ for (int i = 0; i < this.segmentStandins.length(); i++) {
/* 1225 */ if (this.segmentStandins.charAt(i) == 0) {
/* 1226 */ syntaxError("Internal error", rule, start);
/* */ }
/* */ }
/* 1229 */ for (int i = 0; i < this.segmentObjects.size(); i++) {
/* 1230 */ if (this.segmentObjects.get(i) == null) {
/* 1231 */ syntaxError("Internal error", rule, start);
/* */ }
/* */ }
/* */
/* */
/* */
/* 1237 */ if (operator != '~') { if ((this.direction == 0 ? 1 : 0) != (operator == '>' ? 1 : 0))
/* */ {
/* 1239 */ return pos;
/* */ }
/* */ }
/* */
/* */
/* 1244 */ if (this.direction == 1) {
/* 1245 */ RuleHalf temp = left;
/* 1246 */ left = right;
/* 1247 */ right = temp;
/* */ }
/* */
/* */
/* */
/* */
/* 1253 */ if (operator == '~') {
/* 1254 */ right.removeContext();
/* 1255 */ left.cursor = -1;
/* 1256 */ left.cursorOffset = 0;
/* */ }
/* */
/* */
/* 1260 */ if (left.ante < 0) {
/* 1261 */ left.ante = 0;
/* */ }
/* 1263 */ if (left.post < 0) {
/* 1264 */ left.post = left.text.length();
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 1273 */ if ((right.ante >= 0) || (right.post >= 0) || (left.cursor >= 0) || ((right.cursorOffset != 0) && (right.cursor < 0)) || (right.anchorStart) || (right.anchorEnd) || (!left.isValidInput(this)) || (!right.isValidOutput(this)) || (left.ante > left.post))
/* */ {
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* 1284 */ syntaxError("Malformed rule", rule, start);
/* */ }
/* */
/* */
/* 1288 */ UnicodeMatcher[] segmentsArray = null;
/* 1289 */ if (this.segmentObjects.size() > 0) {
/* 1290 */ segmentsArray = new UnicodeMatcher[this.segmentObjects.size()];
/* 1291 */ this.segmentObjects.toArray(segmentsArray);
/* */ }
/* */
/* 1294 */ this.curData.ruleSet.addRule(new TransliterationRule(left.text, left.ante, left.post, right.text, right.cursor, right.cursorOffset, segmentsArray, left.anchorStart, left.anchorEnd, this.curData));
/* */
/* */
/* */
/* */
/* */
/* */
/* 1301 */ return pos;
/* */ }
/* */
/* */
/* */
/* */ private void setVariableRange(int start, int end)
/* */ {
/* 1308 */ if ((start > end) || (start < 0) || (end > 65535)) {
/* 1309 */ throw new IllegalIcuArgumentException("Invalid variable range " + start + ", " + end);
/* */ }
/* */
/* 1312 */ this.curData.variablesBase = ((char)start);
/* */
/* 1314 */ if (this.dataVector.size() == 0) {
/* 1315 */ this.variableNext = ((char)start);
/* 1316 */ this.variableLimit = ((char)(end + 1));
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */ private void checkVariableRange(int ch, String rule, int start)
/* */ {
/* 1326 */ if ((ch >= this.curData.variablesBase) && (ch < this.variableLimit)) {
/* 1327 */ syntaxError("Variable range character in rule", rule, start);
/* */ }
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private void pragmaMaximumBackup(int backup)
/* */ {
/* 1341 */ throw new IllegalIcuArgumentException("use maximum backup pragma not implemented yet");
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private void pragmaNormalizeRules(Normalizer.Mode mode)
/* */ {
/* 1355 */ throw new IllegalIcuArgumentException("use normalize rules pragma not implemented yet");
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ static boolean resemblesPragma(String rule, int pos, int limit)
/* */ {
/* 1367 */ return Utility.parsePattern(rule, pos, limit, "use ", null) >= 0;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ private int parsePragma(String rule, int pos, int limit)
/* */ {
/* 1380 */ int[] array = new int[2];
/* */
/* */
/* */
/* */
/* 1385 */ pos += 4;
/* */
/* */
/* */
/* */
/* */
/* 1391 */ int p = Utility.parsePattern(rule, pos, limit, "~variable range # #~;", array);
/* 1392 */ if (p >= 0) {
/* 1393 */ setVariableRange(array[0], array[1]);
/* 1394 */ return p;
/* */ }
/* */
/* 1397 */ p = Utility.parsePattern(rule, pos, limit, "~maximum backup #~;", array);
/* 1398 */ if (p >= 0) {
/* 1399 */ pragmaMaximumBackup(array[0]);
/* 1400 */ return p;
/* */ }
/* */
/* 1403 */ p = Utility.parsePattern(rule, pos, limit, "~nfd rules~;", null);
/* 1404 */ if (p >= 0) {
/* 1405 */ pragmaNormalizeRules(Normalizer.NFD);
/* 1406 */ return p;
/* */ }
/* */
/* 1409 */ p = Utility.parsePattern(rule, pos, limit, "~nfc rules~;", null);
/* 1410 */ if (p >= 0) {
/* 1411 */ pragmaNormalizeRules(Normalizer.NFC);
/* 1412 */ return p;
/* */ }
/* */
/* */
/* 1416 */ return -1;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ static final void syntaxError(String msg, String rule, int start)
/* */ {
/* 1429 */ int end = ruleEnd(rule, start, rule.length());
/* 1430 */ throw new IllegalIcuArgumentException(msg + " in \"" + Utility.escape(rule.substring(start, end)) + '"');
/* */ }
/* */
/* */ static final int ruleEnd(String rule, int start, int limit)
/* */ {
/* 1435 */ int end = Utility.quotedIndexOf(rule, start, limit, ";");
/* 1436 */ if (end < 0) {
/* 1437 */ end = limit;
/* */ }
/* 1439 */ return end;
/* */ }
/* */
/* */
/* */
/* */
/* */ private final char parseSet(String rule, ParsePosition pos)
/* */ {
/* 1447 */ UnicodeSet set = new UnicodeSet(rule, pos, this.parseData);
/* 1448 */ if (this.variableNext >= this.variableLimit) {
/* 1449 */ throw new RuntimeException("Private use variables exhausted");
/* */ }
/* 1451 */ set.compact();
/* 1452 */ return generateStandInFor(set);
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ char generateStandInFor(Object obj)
/* */ {
/* 1464 */ for (int i = 0; i < this.variablesVector.size(); i++) {
/* 1465 */ if (this.variablesVector.get(i) == obj) {
/* 1466 */ return (char)(this.curData.variablesBase + i);
/* */ }
/* */ }
/* */
/* 1470 */ if (this.variableNext >= this.variableLimit) {
/* 1471 */ throw new RuntimeException("Variable range exhausted");
/* */ }
/* 1473 */ this.variablesVector.add(obj);
/* 1474 */ return this.variableNext++;
/* */ }
/* */
/* */
/* */
/* */ public char getSegmentStandin(int seg)
/* */ {
/* 1481 */ if (this.segmentStandins.length() < seg) {
/* 1482 */ this.segmentStandins.setLength(seg);
/* */ }
/* 1484 */ char c = this.segmentStandins.charAt(seg - 1);
/* 1485 */ if (c == 0) {
/* 1486 */ if (this.variableNext >= this.variableLimit) {
/* 1487 */ throw new RuntimeException("Variable range exhausted");
/* */ }
/* 1489 */ c = this.variableNext++;
/* */
/* */
/* */
/* 1493 */ this.variablesVector.add(null);
/* 1494 */ this.segmentStandins.setCharAt(seg - 1, c);
/* */ }
/* 1496 */ return c;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */
/* */
/* */ public void setSegmentObject(int seg, StringMatcher obj)
/* */ {
/* 1507 */ while (this.segmentObjects.size() < seg) {
/* 1508 */ this.segmentObjects.add(null);
/* */ }
/* 1510 */ int index = getSegmentStandin(seg) - this.curData.variablesBase;
/* 1511 */ if ((this.segmentObjects.get(seg - 1) != null) || (this.variablesVector.get(index) != null))
/* */ {
/* 1513 */ throw new RuntimeException();
/* */ }
/* 1515 */ this.segmentObjects.set(seg - 1, obj);
/* 1516 */ this.variablesVector.set(index, obj);
/* */ }
/* */
/* */
/* */
/* */
/* */ char getDotStandIn()
/* */ {
/* 1524 */ if (this.dotStandIn == -1) {
/* 1525 */ this.dotStandIn = generateStandInFor(new UnicodeSet("[^[:Zp:][:Zl:]\\r\\n$]"));
/* */ }
/* 1527 */ return (char)this.dotStandIn;
/* */ }
/* */
/* */
/* */
/* */
/* */
/* */ private void appendVariableDef(String name, StringBuffer buf)
/* */ {
/* 1536 */ char[] ch = (char[])this.variableNames.get(name);
/* 1537 */ if (ch == null)
/* */ {
/* */
/* */
/* */
/* 1542 */ if (this.undefinedVariableName == null) {
/* 1543 */ this.undefinedVariableName = name;
/* 1544 */ if (this.variableNext >= this.variableLimit) {
/* 1545 */ throw new RuntimeException("Private use variables exhausted");
/* */ }
/* 1547 */ buf.append(this.variableLimit = (char)(this.variableLimit - '\001'));
/* */ } else {
/* 1549 */ throw new IllegalIcuArgumentException("Undefined variable $" + name);
/* */ }
/* */ }
/* */ else {
/* 1553 */ buf.append(ch);
/* */ }
/* */ }
/* */ }
/* Location: C:\Users\Ethan\Desktop\FontZip\FontTool\sfnttool.jar!\com\ibm\icu\text\TransliteratorParser.class
* Java compiler version: 5 (49.0)
* JD-Core Version: 0.7.1
*/