780 /** |
780 /** |
781 * Regular expression modifier values. Instead of being passed as |
781 * Regular expression modifier values. Instead of being passed as |
782 * arguments, they can also be passed as inline modifiers. |
782 * arguments, they can also be passed as inline modifiers. |
783 * For example, the following statements have the same effect. |
783 * For example, the following statements have the same effect. |
784 * <pre> |
784 * <pre> |
785 * RegExp r1 = RegExp.compile("abc", Pattern.I|Pattern.M); |
785 * Pattern p1 = Pattern.compile("abc", Pattern.CASE_INSENSITIVE|Pattern.MULTILINE); |
786 * RegExp r2 = RegExp.compile("(?im)abc", 0); |
786 * Pattern p2 = Pattern.compile("(?im)abc", 0); |
787 * </pre> |
787 * </pre> |
788 * |
|
789 * The flags are duplicated so that the familiar Perl match flag |
|
790 * names are available. |
|
791 */ |
788 */ |
792 |
789 |
793 /** |
790 /** |
794 * Enables Unix lines mode. |
791 * Enables Unix lines mode. |
795 * |
792 * |
2525 break; |
2522 break; |
2526 if (read() != '<') |
2523 if (read() != '<') |
2527 throw error("\\k is not followed by '<' for named capturing group"); |
2524 throw error("\\k is not followed by '<' for named capturing group"); |
2528 String name = groupname(read()); |
2525 String name = groupname(read()); |
2529 if (!namedGroups().containsKey(name)) |
2526 if (!namedGroups().containsKey(name)) |
2530 throw error("(named capturing group <"+ name+"> does not exit"); |
2527 throw error("named capturing group <" + name + "> does not exist"); |
2531 if (create) { |
2528 if (create) { |
2532 hasGroupRef = true; |
2529 hasGroupRef = true; |
2533 if (has(CASE_INSENSITIVE)) |
2530 if (has(CASE_INSENSITIVE)) |
2534 root = new CIBackRef(namedGroups().get(name), has(UNICODE_CASE)); |
2531 root = new CIBackRef(namedGroups().get(name), has(UNICODE_CASE)); |
2535 else |
2532 else |
2920 * Parses and returns the name of a "named capturing group", the trailing |
2917 * Parses and returns the name of a "named capturing group", the trailing |
2921 * ">" is consumed after parsing. |
2918 * ">" is consumed after parsing. |
2922 */ |
2919 */ |
2923 private String groupname(int ch) { |
2920 private String groupname(int ch) { |
2924 StringBuilder sb = new StringBuilder(); |
2921 StringBuilder sb = new StringBuilder(); |
2925 sb.append(Character.toChars(ch)); |
2922 if (!ASCII.isAlpha(ch)) |
2926 while (ASCII.isLower(ch=read()) || ASCII.isUpper(ch) || |
2923 throw error("capturing group name does not start with a Latin letter"); |
2927 ASCII.isDigit(ch)) { |
2924 do { |
2928 sb.append(Character.toChars(ch)); |
2925 sb.append((char) ch); |
2929 } |
2926 } while (ASCII.isAlnum(ch=read())); |
2930 if (sb.length() == 0) |
|
2931 throw error("named capturing group has 0 length name"); |
|
2932 if (ch != '>') |
2927 if (ch != '>') |
2933 throw error("named capturing group is missing trailing '>'"); |
2928 throw error("named capturing group is missing trailing '>'"); |
2934 return sb.toString(); |
2929 return sb.toString(); |
2935 } |
2930 } |
2936 |
2931 |
2972 head.next = expr(tail); |
2967 head.next = expr(tail); |
2973 head = tail = new Ques(head, Qtype.INDEPENDENT); |
2968 head = tail = new Ques(head, Qtype.INDEPENDENT); |
2974 break; |
2969 break; |
2975 case '<': // (?<xxx) look behind |
2970 case '<': // (?<xxx) look behind |
2976 ch = read(); |
2971 ch = read(); |
2977 if (ASCII.isLower(ch) || ASCII.isUpper(ch)) { |
2972 if (ch != '=' && ch != '!') { |
2978 // named captured group |
2973 // named captured group |
2979 String name = groupname(ch); |
2974 String name = groupname(ch); |
2980 if (namedGroups().containsKey(name)) |
2975 if (namedGroups().containsKey(name)) |
2981 throw error("Named capturing group <" + name |
2976 throw error("Named capturing group <" + name |
2982 + "> is already defined"); |
2977 + "> is already defined"); |
3003 head = tail = (hasSupplementary ? |
2998 head = tail = (hasSupplementary ? |
3004 new BehindS(head, info.maxLength, |
2999 new BehindS(head, info.maxLength, |
3005 info.minLength) : |
3000 info.minLength) : |
3006 new Behind(head, info.maxLength, |
3001 new Behind(head, info.maxLength, |
3007 info.minLength)); |
3002 info.minLength)); |
3008 } else if (ch == '!') { |
3003 } else { // if (ch == '!') |
3009 head = tail = (hasSupplementary ? |
3004 head = tail = (hasSupplementary ? |
3010 new NotBehindS(head, info.maxLength, |
3005 new NotBehindS(head, info.maxLength, |
3011 info.minLength) : |
3006 info.minLength) : |
3012 new NotBehind(head, info.maxLength, |
3007 new NotBehind(head, info.maxLength, |
3013 info.minLength)); |
3008 info.minLength)); |
3014 } else { |
|
3015 throw error("Unknown look-behind group"); |
|
3016 } |
3009 } |
3017 // clear all top-closure-nodes inside lookbehind |
3010 // clear all top-closure-nodes inside lookbehind |
3018 if (saveTCNCount < topClosureNodes.size()) |
3011 if (saveTCNCount < topClosureNodes.size()) |
3019 topClosureNodes.subList(saveTCNCount, topClosureNodes.size()).clear(); |
3012 topClosureNodes.subList(saveTCNCount, topClosureNodes.size()).clear(); |
3020 break; |
3013 break; |