1 package com.sun.org.apache.regexp.internal; 2 3 59 60 import com.sun.org.apache.regexp.internal.RE; 61 import java.util.Hashtable ; 62 63 76 public class RECompiler 77 { 78 char[] instruction; int lenInstruction; 82 String pattern; int len; int idx; int parens; 88 static final int NODE_NORMAL = 0; static final int NODE_NULLABLE = 1; static final int NODE_TOPLEVEL = 2; 93 static final char ESC_MASK = 0xfff0; static final char ESC_BACKREF = 0xffff; static final char ESC_COMPLEX = 0xfffe; static final char ESC_CLASS = 0xfffd; 99 static final int maxBrackets = 10; static int brackets = 0; static int[] bracketStart = null; static int[] bracketEnd = null; static int[] bracketMin = null; static int[] bracketOpt = null; static final int bracketUnbounded = -1; static final int bracketFinished = -2; 109 static Hashtable hashPOSIX = new Hashtable (); 111 static 112 { 113 hashPOSIX.put("alnum", new Character (RE.POSIX_CLASS_ALNUM)); 114 hashPOSIX.put("alpha", new Character (RE.POSIX_CLASS_ALPHA)); 115 hashPOSIX.put("blank", new Character (RE.POSIX_CLASS_BLANK)); 116 hashPOSIX.put("cntrl", new Character (RE.POSIX_CLASS_CNTRL)); 117 hashPOSIX.put("digit", new Character (RE.POSIX_CLASS_DIGIT)); 118 hashPOSIX.put("graph", new Character (RE.POSIX_CLASS_GRAPH)); 119 hashPOSIX.put("lower", new Character (RE.POSIX_CLASS_LOWER)); 120 hashPOSIX.put("print", new Character (RE.POSIX_CLASS_PRINT)); 121 hashPOSIX.put("punct", new Character (RE.POSIX_CLASS_PUNCT)); 122 hashPOSIX.put("space", new Character (RE.POSIX_CLASS_SPACE)); 123 hashPOSIX.put("upper", new Character (RE.POSIX_CLASS_UPPER)); 124 hashPOSIX.put("xdigit", new Character (RE.POSIX_CLASS_XDIGIT)); 125 hashPOSIX.put("javastart", new Character (RE.POSIX_CLASS_JSTART)); 126 hashPOSIX.put("javapart", new Character (RE.POSIX_CLASS_JPART)); 127 } 128 129 132 public RECompiler() 133 { 134 instruction = new char[128]; 136 lenInstruction = 0; 137 } 138 139 144 void ensure(int n) 145 { 146 int curlen = instruction.length; 148 149 if (lenInstruction + n >= curlen) 151 { 152 while (lenInstruction + n >= curlen) 154 { 155 curlen *= 2; 156 } 157 158 char[] newInstruction = new char[curlen]; 160 System.arraycopy(instruction, 0, newInstruction, 0, lenInstruction); 161 instruction = newInstruction; 162 } 163 } 164 165 169 void emit(char c) 170 { 171 ensure(1); 173 174 instruction[lenInstruction++] = c; 176 } 177 178 185 void nodeInsert(char opcode, int opdata, int insertAt) 186 { 187 ensure(RE.nodeSize); 189 190 System.arraycopy(instruction, insertAt, instruction, insertAt + RE.nodeSize, lenInstruction - insertAt); 192 instruction[insertAt + RE.offsetOpcode] = opcode; 193 instruction[insertAt + RE.offsetOpdata] = (char)opdata; 194 instruction[insertAt + RE.offsetNext] = 0; 195 lenInstruction += RE.nodeSize; 196 } 197 198 203 void setNextOfEnd(int node, int pointTo) 204 { 205 int next; 207 while ((next = instruction[node + RE.offsetNext]) != 0) 208 { 209 node += next; 210 } 211 212 instruction[node + RE.offsetNext] = (char)(short)(pointTo - node); 214 } 215 216 222 int node(char opcode, int opdata) 223 { 224 ensure(RE.nodeSize); 226 227 instruction[lenInstruction + RE.offsetOpcode] = opcode; 229 instruction[lenInstruction + RE.offsetOpdata] = (char)opdata; 230 instruction[lenInstruction + RE.offsetNext] = 0; 231 lenInstruction += RE.nodeSize; 232 233 return lenInstruction - RE.nodeSize; 235 } 236 237 238 242 void internalError() throws Error 243 { 244 throw new Error ("Internal error!"); 245 } 246 247 251 void syntaxError(String s) throws RESyntaxException 252 { 253 throw new RESyntaxException(s); 254 } 255 256 259 void allocBrackets() 260 { 261 if (bracketStart == null) 263 { 264 bracketStart = new int[maxBrackets]; 266 bracketEnd = new int[maxBrackets]; 267 bracketMin = new int[maxBrackets]; 268 bracketOpt = new int[maxBrackets]; 269 270 for (int i = 0; i < maxBrackets; i++) 272 { 273 bracketStart[i] = bracketEnd[i] = bracketMin[i] = bracketOpt[i] = -1; 274 } 275 } 276 } 277 278 282 void bracket() throws RESyntaxException 283 { 284 if (idx >= len || pattern.charAt(idx++) != '{') 286 { 287 internalError(); 288 } 289 290 if (idx >= len || !Character.isDigit(pattern.charAt(idx))) 292 { 293 syntaxError("Expected digit"); 294 } 295 296 StringBuffer number = new StringBuffer (); 298 while (idx < len && Character.isDigit(pattern.charAt(idx))) 299 { 300 number.append(pattern.charAt(idx++)); 301 } 302 try 303 { 304 bracketMin[brackets] = Integer.parseInt(number.toString()); 305 } 306 catch (NumberFormatException e) 307 { 308 syntaxError("Expected valid number"); 309 } 310 311 if (idx >= len) 313 { 314 syntaxError("Expected comma or right bracket"); 315 } 316 317 if (pattern.charAt(idx) == '}') 319 { 320 idx++; 321 bracketOpt[brackets] = 0; 322 return; 323 } 324 325 if (idx >= len || pattern.charAt(idx++) != ',') 327 { 328 syntaxError("Expected comma"); 329 } 330 331 if (idx >= len) 333 { 334 syntaxError("Expected comma or right bracket"); 335 } 336 337 if (pattern.charAt(idx) == '}') 339 { 340 idx++; 341 bracketOpt[brackets] = bracketUnbounded; 342 return; 343 } 344 345 if (idx >= len || !Character.isDigit(pattern.charAt(idx))) 347 { 348 syntaxError("Expected digit"); 349 } 350 351 number.setLength(0); 353 while (idx < len && Character.isDigit(pattern.charAt(idx))) 354 { 355 number.append(pattern.charAt(idx++)); 356 } 357 try 358 { 359 bracketOpt[brackets] = Integer.parseInt(number.toString()) - bracketMin[brackets]; 360 } 361 catch (NumberFormatException e) 362 { 363 syntaxError("Expected valid number"); 364 } 365 366 if (bracketOpt[brackets] <= 0) 368 { 369 syntaxError("Bad range"); 370 } 371 372 if (idx >= len || pattern.charAt(idx++) != '}') 374 { 375 syntaxError("Missing close brace"); 376 } 377 } 378 379 388 char escape() throws RESyntaxException 389 { 390 if (pattern.charAt(idx) != '\\') 392 { 393 internalError(); 394 } 395 396 if (idx + 1 == len) 398 { 399 syntaxError("Escape terminates string"); 400 } 401 402 idx += 2; 404 char escapeChar = pattern.charAt(idx - 1); 405 switch (escapeChar) 406 { 407 case RE.E_BOUND: 408 case RE.E_NBOUND: 409 return ESC_COMPLEX; 410 411 case RE.E_ALNUM: 412 case RE.E_NALNUM: 413 case RE.E_SPACE: 414 case RE.E_NSPACE: 415 case RE.E_DIGIT: 416 case RE.E_NDIGIT: 417 return ESC_CLASS; 418 419 case 'u': 420 case 'x': 421 { 422 int hexDigits = (escapeChar == 'u' ? 4 : 2); 424 425 int val = 0; 427 for ( ; idx < len && hexDigits-- > 0; idx++) 428 { 429 char c = pattern.charAt(idx); 431 432 if (c >= '0' && c <= '9') 434 { 435 val = (val << 4) + c - '0'; 437 } 438 else 439 { 440 c = Character.toLowerCase(c); 442 if (c >= 'a' && c <= 'f') 443 { 444 val = (val << 4) + (c - 'a') + 10; 446 } 447 else 448 { 449 syntaxError("Expected " + hexDigits + " hexadecimal digits after \\" + escapeChar); 452 } 453 } 454 } 455 return (char)val; 456 } 457 458 case 't': 459 return '\t'; 460 461 case 'n': 462 return '\n'; 463 464 case 'r': 465 return '\r'; 466 467 case 'f': 468 return '\f'; 469 470 case '0': 471 case '1': 472 case '2': 473 case '3': 474 case '4': 475 case '5': 476 case '6': 477 case '7': 478 case '8': 479 case '9': 480 481 if ((idx < len && Character.isDigit(pattern.charAt(idx))) || escapeChar == '0') 483 { 484 int val = escapeChar - '0'; 486 if (idx < len && Character.isDigit(pattern.charAt(idx))) 487 { 488 val = ((val << 3) + (pattern.charAt(idx++) - '0')); 489 if (idx < len && Character.isDigit(pattern.charAt(idx))) 490 { 491 val = ((val << 3) + (pattern.charAt(idx++) - '0')); 492 } 493 } 494 return (char)val; 495 } 496 497 return ESC_BACKREF; 499 500 default: 501 502 return escapeChar; 504 } 505 } 506 507 512 int characterClass() throws RESyntaxException 513 { 514 if (pattern.charAt(idx) != '[') 516 { 517 internalError(); 518 } 519 520 if ((idx + 1) >= len || pattern.charAt(++idx) == ']') 522 { 523 syntaxError("Empty or unterminated class"); 524 } 525 526 if (idx < len && pattern.charAt(idx) == ':') 528 { 529 idx++; 531 532 int idxStart = idx; 534 while (idx < len && pattern.charAt(idx) >= 'a' && pattern.charAt(idx) <= 'z') 535 { 536 idx++; 537 } 538 539 if ((idx + 1) < len && pattern.charAt(idx) == ':' && pattern.charAt(idx + 1) == ']') 541 { 542 String charClass = pattern.substring(idxStart, idx); 544 545 Character i = (Character )hashPOSIX.get(charClass); 547 if (i != null) 548 { 549 idx += 2; 551 552 return node(RE.OP_POSIXCLASS, i.charValue()); 554 } 555 syntaxError("Invalid POSIX character class '" + charClass + "'"); 556 } 557 syntaxError("Invalid POSIX character class syntax"); 558 } 559 560 int ret = node(RE.OP_ANYOF, 0); 562 563 char CHAR_INVALID = Character.MAX_VALUE; 565 char last = CHAR_INVALID; 566 char simpleChar = 0; 567 boolean include = true; 568 boolean definingRange = false; 569 int idxFirst = idx; 570 char rangeStart = Character.MIN_VALUE; 571 char rangeEnd; 572 RERange range = new RERange(); 573 while (idx < len && pattern.charAt(idx) != ']') 574 { 575 576 switchOnCharacter: 577 578 switch (pattern.charAt(idx)) 580 { 581 case '^': 582 include = !include; 583 if (idx == idxFirst) 584 { 585 range.include(Character.MIN_VALUE, Character.MAX_VALUE, true); 586 } 587 idx++; 588 continue; 589 590 case '\\': 591 { 592 char c; 594 switch (c = escape ()) 595 { 596 case ESC_COMPLEX: 597 case ESC_BACKREF: 598 599 syntaxError("Bad character class"); 601 602 case ESC_CLASS: 603 604 if (definingRange) 606 { 607 syntaxError("Bad character class"); 608 } 609 610 switch (pattern.charAt(idx - 1)) 612 { 613 case RE.E_NSPACE: 614 case RE.E_NDIGIT: 615 case RE.E_NALNUM: 616 syntaxError("Bad character class"); 617 618 case RE.E_SPACE: 619 range.include('\t', include); 620 range.include('\r', include); 621 range.include('\f', include); 622 range.include('\n', include); 623 range.include('\b', include); 624 range.include(' ', include); 625 break; 626 627 case RE.E_ALNUM: 628 range.include('a', 'z', include); 629 range.include('A', 'Z', include); 630 range.include('_', include); 631 632 634 case RE.E_DIGIT: 635 range.include('0', '9', include); 636 break; 637 } 638 639 last = CHAR_INVALID; 641 break; 642 643 default: 644 645 simpleChar = c; 647 break switchOnCharacter; 648 } 649 } 650 continue; 651 652 case '-': 653 654 if (definingRange) 656 { 657 syntaxError("Bad class range"); 658 } 659 definingRange = true; 660 661 rangeStart = (last == CHAR_INVALID ? 0 : last); 663 664 if ((idx + 1) < len && pattern.charAt(++idx) == ']') 666 { 667 simpleChar = Character.MAX_VALUE; 668 break; 669 } 670 continue; 671 672 default: 673 simpleChar = pattern.charAt(idx++); 674 break; 675 } 676 677 if (definingRange) 679 { 680 rangeEnd = simpleChar; 682 683 if (rangeStart >= rangeEnd) 685 { 686 syntaxError("Bad character class"); 687 } 688 range.include(rangeStart, rangeEnd, include); 689 690 last = CHAR_INVALID; 692 definingRange = false; 693 } 694 else 695 { 696 if ((idx + 1) >= len || pattern.charAt(idx + 1) != '-') 698 { 699 range.include(simpleChar, include); 700 } 701 last = simpleChar; 702 } 703 } 704 705 if (idx == len) 707 { 708 syntaxError("Unterminated character class"); 709 } 710 711 idx++; 713 714 instruction[ret + RE.offsetOpdata] = (char)range.num; 716 for (int i = 0; i < range.num; i++) 717 { 718 emit((char)range.minRange[i]); 719 emit((char)range.maxRange[i]); 720 } 721 return ret; 722 } 723 724 732 int atom() throws RESyntaxException 733 { 734 int ret = node(RE.OP_ATOM, 0); 736 737 int lenAtom = 0; 739 740 742 atomLoop: 743 744 while (idx < len) 745 { 746 if ((idx + 1) < len) 748 { 749 char c = pattern.charAt(idx + 1); 750 751 if (pattern.charAt(idx) == '\\') 753 { 754 int idxEscape = idx; 755 escape(); 756 if (idx < len) 757 { 758 c = pattern.charAt(idx); 759 } 760 idx = idxEscape; 761 } 762 763 switch (c) 765 { 766 case '{': 767 case '?': 768 case '*': 769 case '+': 770 771 if (lenAtom != 0) 774 { 775 break atomLoop; 776 } 777 } 778 } 779 780 switch (pattern.charAt(idx)) 782 { 783 case ']': 784 case '^': 785 case '$': 786 case '.': 787 case '[': 788 case '(': 789 case ')': 790 case '|': 791 break atomLoop; 792 793 case '{': 794 case '?': 795 case '*': 796 case '+': 797 798 if (lenAtom == 0) 800 { 801 syntaxError("Missing operand to closure"); 803 } 804 break atomLoop; 805 806 case '\\': 807 808 { 809 int idxBeforeEscape = idx; 811 char c = escape(); 812 813 if ((c & ESC_MASK) == ESC_MASK) 815 { 816 idx = idxBeforeEscape; 818 break atomLoop; 819 } 820 821 emit(c); 823 lenAtom++; 824 } 825 break; 826 827 default: 828 829 emit(pattern.charAt(idx++)); 831 lenAtom++; 832 break; 833 } 834 } 835 836 if (lenAtom == 0) 838 { 839 internalError(); 840 } 841 842 instruction[ret + RE.offsetOpdata] = (char)lenAtom; 844 return ret; 845 } 846 847 853 int terminal(int[] flags) throws RESyntaxException 854 { 855 switch (pattern.charAt(idx)) 856 { 857 case RE.OP_EOL: 858 case RE.OP_BOL: 859 case RE.OP_ANY: 860 return node(pattern.charAt(idx++), 0); 861 862 case '[': 863 return characterClass(); 864 865 case '(': 866 return expr(flags); 867 868 case ')': 869 syntaxError("Unexpected close paren"); 870 871 case '|': 872 internalError(); 873 874 case ']': 875 syntaxError("Mismatched class"); 876 877 case 0: 878 syntaxError("Unexpected end of input"); 879 880 case '?': 881 case '+': 882 case '{': 883 case '*': 884 syntaxError("Missing operand to closure"); 885 886 case '\\': 887 { 888 int idxBeforeEscape = idx; 890 891 switch (escape()) 893 { 894 case ESC_CLASS: 895 case ESC_COMPLEX: 896 flags[0] &= ~NODE_NULLABLE; 897 return node(RE.OP_ESCAPE, pattern.charAt(idx - 1)); 898 899 case ESC_BACKREF: 900 { 901 char backreference = (char)(pattern.charAt(idx - 1) - '0'); 902 if (parens <= backreference) 903 { 904 syntaxError("Bad backreference"); 905 } 906 flags[0] |= NODE_NULLABLE; 907 return node(RE.OP_BACKREF, backreference); 908 } 909 910 default: 911 912 idx = idxBeforeEscape; 915 flags[0] &= ~NODE_NULLABLE; 916 break; 917 } 918 } 919 } 920 921 flags[0] &= ~NODE_NULLABLE; 924 return atom(); 925 } 926 927 933 int closure(int[] flags) throws RESyntaxException 934 { 935 int idxBeforeTerminal = idx; 937 938 int[] terminalFlags = { NODE_NORMAL }; 940 941 int ret = terminal(terminalFlags); 943 944 flags[0] |= terminalFlags[0]; 946 947 if (idx >= len) 949 { 950 return ret; 951 } 952 boolean greedy = true; 953 char closureType = pattern.charAt(idx); 954 switch (closureType) 955 { 956 case '?': 957 case '*': 958 959 flags[0] |= NODE_NULLABLE; 961 962 case '+': 963 964 idx++; 966 967 case '{': 968 969 int opcode = instruction[ret + RE.offsetOpcode]; 971 if (opcode == RE.OP_BOL || opcode == RE.OP_EOL) 972 { 973 syntaxError("Bad closure operand"); 974 } 975 if ((terminalFlags[0] & NODE_NULLABLE) != 0) 976 { 977 syntaxError("Closure operand can't be nullable"); 978 } 979 break; 980 } 981 982 if (idx < len && pattern.charAt(idx) == '?') 984 { 985 idx++; 986 greedy = false; 987 } 988 989 if (greedy) 990 { 991 switch (closureType) 993 { 994 case '{': 995 { 996 boolean found = false; 998 int i; 999 allocBrackets(); 1000 for (i = 0; i < brackets; i++) 1001 { 1002 if (bracketStart[i] == idx) 1003 { 1004 found = true; 1005 break; 1006 } 1007 } 1008 1009 if (!found) 1011 { 1012 if (brackets >= maxBrackets) 1013 { 1014 syntaxError("Too many bracketed closures (limit is 10)"); 1015 } 1016 bracketStart[brackets] = idx; 1017 bracket(); 1018 bracketEnd[brackets] = idx; 1019 i = brackets++; 1020 } 1021 1022 if (--bracketMin[i] > 0) 1024 { 1025 idx = idxBeforeTerminal; 1027 break; 1028 } 1029 1030 if (bracketOpt[i] == bracketFinished) 1032 { 1033 closureType = '*'; 1036 bracketOpt[i] = 0; 1037 idx = bracketEnd[i]; 1038 } 1039 else 1040 if (bracketOpt[i] == bracketUnbounded) 1041 { 1042 idx = idxBeforeTerminal; 1043 bracketOpt[i] = bracketFinished; 1044 break; 1045 } 1046 else 1047 if (bracketOpt[i]-- > 0) 1048 { 1049 idx = idxBeforeTerminal; 1051 closureType = '?'; 1052 } 1053 else 1054 { 1055 idx = bracketEnd[i]; 1057 break; 1058 } 1059 } 1060 1061 1063 case '?': 1064 case '*': 1065 1066 if (!greedy) 1067 { 1068 break; 1069 } 1070 1071 if (closureType == '?') 1072 { 1073 nodeInsert(RE.OP_BRANCH, 0, ret); setNextOfEnd(ret, node (RE.OP_BRANCH, 0)); int nothing = node (RE.OP_NOTHING, 0); setNextOfEnd(ret, nothing); setNextOfEnd(ret + RE.nodeSize, nothing); } 1080 1081 if (closureType == '*') 1082 { 1083 nodeInsert(RE.OP_BRANCH, 0, ret); setNextOfEnd(ret + RE.nodeSize, node(RE.OP_BRANCH, 0)); setNextOfEnd(ret + RE.nodeSize, node(RE.OP_GOTO, 0)); setNextOfEnd(ret + RE.nodeSize, ret); setNextOfEnd(ret, node(RE.OP_BRANCH, 0)); setNextOfEnd(ret, node(RE.OP_NOTHING, 0)); } 1091 break; 1092 1093 case '+': 1094 { 1095 int branch; 1097 branch = node(RE.OP_BRANCH, 0); setNextOfEnd(ret, branch); setNextOfEnd(node(RE.OP_GOTO, 0), ret); setNextOfEnd(branch, node(RE.OP_BRANCH, 0)); setNextOfEnd(ret, node(RE.OP_NOTHING, 0)); } 1103 break; 1104 } 1105 } 1106 else 1107 { 1108 setNextOfEnd(ret, node(RE.OP_END, 0)); 1110 1111 switch (closureType) 1113 { 1114 case '?': 1115 nodeInsert(RE.OP_RELUCTANTMAYBE, 0, ret); 1116 break; 1117 1118 case '*': 1119 nodeInsert(RE.OP_RELUCTANTSTAR, 0, ret); 1120 break; 1121 1122 case '+': 1123 nodeInsert(RE.OP_RELUCTANTPLUS, 0, ret); 1124 break; 1125 } 1126 1127 setNextOfEnd(ret, lenInstruction); 1129 } 1130 return ret; 1131 } 1132 1133 1139 int branch(int[] flags) throws RESyntaxException 1140 { 1141 int node; 1143 int ret = node(RE.OP_BRANCH, 0); 1144 int chain = -1; 1145 int[] closureFlags = new int[1]; 1146 boolean nullable = true; 1147 while (idx < len && pattern.charAt(idx) != '|' && pattern.charAt(idx) != ')') 1148 { 1149 closureFlags[0] = NODE_NORMAL; 1151 node = closure(closureFlags); 1152 if (closureFlags[0] == NODE_NORMAL) 1153 { 1154 nullable = false; 1155 } 1156 1157 if (chain != -1) 1159 { 1160 setNextOfEnd(chain, node); 1161 } 1162 1163 chain = node; 1165 } 1166 1167 if (chain == -1) 1169 { 1170 node(RE.OP_NOTHING, 0); 1171 } 1172 1173 if (nullable) 1175 { 1176 flags[0] |= NODE_NULLABLE; 1177 } 1178 return ret; 1179 } 1180 1181 1188 int expr(int[] flags) throws RESyntaxException 1189 { 1190 boolean paren = false; 1192 int ret = -1; 1193 int closeParens = parens; 1194 if ((flags[0] & NODE_TOPLEVEL) == 0 && pattern.charAt(idx) == '(') 1195 { 1196 idx++; 1197 paren = true; 1198 ret = node(RE.OP_OPEN, parens++); 1199 } 1200 flags[0] &= ~NODE_TOPLEVEL; 1201 1202 int branch = branch(flags); 1204 if (ret == -1) 1205 { 1206 ret = branch; 1207 } 1208 else 1209 { 1210 setNextOfEnd(ret, branch); 1211 } 1212 1213 while (idx < len && pattern.charAt(idx) == '|') 1215 { 1216 idx++; 1217 branch = branch(flags); 1218 setNextOfEnd(ret, branch); 1219 } 1220 1221 int end; 1223 if (paren) 1224 { 1225 if (idx < len && pattern.charAt(idx) == ')') 1226 { 1227 idx++; 1228 } 1229 else 1230 { 1231 syntaxError("Missing close paren"); 1232 } 1233 end = node(RE.OP_CLOSE, closeParens); 1234 } 1235 else 1236 { 1237 end = node(RE.OP_END, 0); 1238 } 1239 1240 setNextOfEnd(ret, end); 1242 1243 for (int next = -1, i = ret; next != 0; next = instruction[i + RE.offsetNext], i += next) 1245 { 1246 if (instruction[i + RE.offsetOpcode] == RE.OP_BRANCH) 1248 { 1249 setNextOfEnd(i + RE.nodeSize, end); 1250 } 1251 } 1252 1253 return ret; 1255 } 1256 1257 1267 public REProgram compile(String pattern) throws RESyntaxException 1268 { 1269 this.pattern = pattern; len = pattern.length(); idx = 0; lenInstruction = 0; parens = 1; brackets = 0; 1277 int[] flags = { NODE_TOPLEVEL }; 1279 1280 expr(flags); 1282 1283 if (idx != len) 1285 { 1286 if (pattern.charAt(idx) == ')') 1287 { 1288 syntaxError("Unmatched close paren"); 1289 } 1290 syntaxError("Unexpected input remains"); 1291 } 1292 1293 char[] ins = new char[lenInstruction]; 1295 System.arraycopy(instruction, 0, ins, 0, lenInstruction); 1296 return new REProgram(ins); 1297 } 1298 1299 1302 class RERange 1303 { 1304 int size = 16; int[] minRange = new int[size]; int[] maxRange = new int[size]; int num = 0; 1309 1313 void delete(int index) 1314 { 1315 if (num == 0 || index >= num) 1317 { 1318 return; 1319 } 1320 1321 while (index++ < num) 1323 { 1324 if (index - 1 >= 0) 1325 { 1326 minRange[index-1] = minRange[index]; 1327 maxRange[index-1] = maxRange[index]; 1328 } 1329 } 1330 1331 num--; 1333 } 1334 1335 1340 void merge(int min, int max) 1341 { 1342 for (int i = 0; i < num; i++) 1344 { 1345 if (min >= minRange[i] && max <= maxRange[i]) 1347 { 1348 return; 1349 } 1350 1351 else if (min <= minRange[i] && max >= maxRange[i]) 1353 { 1354 delete(i); 1355 merge(min, max); 1356 return; 1357 } 1358 1359 else if (min >= minRange[i] && min <= maxRange[i]) 1361 { 1362 delete(i); 1363 min = minRange[i]; 1364 merge(min, max); 1365 return; 1366 } 1367 1368 else if (max >= minRange[i] && max <= maxRange[i]) 1370 { 1371 delete(i); 1372 max = maxRange[i]; 1373 merge(min, max); 1374 return; 1375 } 1376 } 1377 1378 if (num >= size) 1380 { 1381 size *= 2; 1382 int[] newMin = new int[size]; 1383 int[] newMax = new int[size]; 1384 System.arraycopy(minRange, 0, newMin, 0, num); 1385 System.arraycopy(maxRange, 0, newMax, 0, num); 1386 minRange = newMin; 1387 maxRange = newMax; 1388 } 1389 minRange[num] = min; 1390 maxRange[num] = max; 1391 num++; 1392 } 1393 1394 1399 void remove(int min, int max) 1400 { 1401 for (int i = 0; i < num; i++) 1403 { 1404 if (minRange[i] >= min && maxRange[i] <= max) 1406 { 1407 delete(i); 1408 i--; 1409 return; 1410 } 1411 1412 else if (min >= minRange[i] && max <= maxRange[i]) 1414 { 1415 int minr = minRange[i]; 1416 int maxr = maxRange[i]; 1417 delete(i); 1418 if (minr < min - 1) 1419 { 1420 merge(minr, min - 1); 1421 } 1422 if (max + 1 < maxr) 1423 { 1424 merge(max + 1, maxr); 1425 } 1426 return; 1427 } 1428 1429 else if (minRange[i] >= min && minRange[i] <= max) 1431 { 1432 minRange[i] = max + 1; 1433 return; 1434 } 1435 1436 else if (maxRange[i] >= min && maxRange[i] <= max) 1438 { 1439 maxRange[i] = min - 1; 1440 return; 1441 } 1442 } 1443 } 1444 1445 1451 void include(int min, int max, boolean include) 1452 { 1453 if (include) 1454 { 1455 merge(min, max); 1456 } 1457 else 1458 { 1459 remove(min, max); 1460 } 1461 } 1462 1463 1468 void include(char minmax, boolean include) 1469 { 1470 include(minmax, minmax, include); 1471 } 1472 } 1473} 1474 | Popular Tags |