001: /*
002: * @(#)PatternMatchHelper.java 1.3 05/05/25
003: *
004: * Copyright (c) 2001-2004 Sun Microsystems, Inc. All Rights Reserved.
005: *
006: * See the file "LICENSE.txt" for information on usage and redistribution
007: * of this file, and for a DISCLAIMER OF ALL WARRANTIES.
008: */
009: package pnuts.regex.jsr51;
010:
011: import pnuts.lang.Package;
012: import pnuts.lang.Context;
013: import pnuts.lang.PnutsFunction;
014: import pnuts.lang.PnutsException;
015: import java.util.*;
016: import java.util.regex.*;
017: import java.io.*;
018:
019: class MatchContext implements Serializable {
020: Matcher matcher;
021: int count;
022: }
023:
024: /**
025: * This is a helper class for pnuts.regex module, which utilizes
026: * java.util.regex package in J2SDK1.4.0.
027: */
028: class PatternMatchHelper implements Serializable {
029:
030: String lastExpr;
031: String lastOption;
032: Pattern pattern;
033: final static Object[] NO_PARAM = new Object[0];
034: final static String CONTEXT_SYMBOL = "pnuts.regex.jsr51".intern();
035:
036: static String escapePattern(String pattern) {
037: StringBuffer sbuf = new StringBuffer();
038: for (int i = 0; i < pattern.length(); i++) {
039: char c = pattern.charAt(i);
040: switch (c) {
041: case '(':
042: case ')':
043: case '{':
044: case '}':
045: case '[':
046: case ']':
047: case '^':
048: case '$':
049: case '.':
050: case '?':
051: case '*':
052: case '+':
053: case '\\':
054: case '|':
055: sbuf.append('\\');
056: }
057: sbuf.append(c);
058: }
059: return sbuf.toString();
060: }
061:
062: synchronized Pattern getPattern(String expr, String option,
063: Context context) {
064: Pattern p;
065: if ((expr == lastExpr || expr.equals(lastExpr))
066: && (option == lastOption || option != null
067: && option.equals(lastOption))) {
068: p = pattern;
069: } else {
070: int flag = 0;
071: if (option != null) {
072: for (int i = 0; i < option.length(); i++) {
073: switch (option.charAt(i)) {
074: case 'i':
075: flag |= Pattern.CASE_INSENSITIVE;
076: break;
077: case 's':
078: flag |= Pattern.DOTALL;
079: break;
080: case 'm':
081: flag |= Pattern.MULTILINE;
082: break;
083: case 'u':
084: flag |= Pattern.UNICODE_CASE;
085: break;
086: case 'c':
087: flag |= Pattern.CANON_EQ;
088: break;
089: case 'n':
090: expr = escapePattern(expr);
091: break;
092: case 'g':
093: break;
094: default:
095: throw new PnutsException("pnuts.regex.errors",
096: "illegal.regex.option",
097: new Object[] { option }, context);
098: }
099: }
100: }
101:
102: try {
103: p = pattern = Pattern.compile(expr, flag);
104: lastExpr = expr;
105: lastOption = option;
106: } catch (PatternSyntaxException e) {
107: throw new PnutsException("pnuts.regex.errors",
108: "illegal.regex.pattern", new Object[] { expr },
109: context);
110: }
111: }
112: return p;
113: }
114:
115: static Object split(Pattern pattern, CharSequence input) {
116: Matcher m = pattern.matcher(input);
117: ArrayList list = new ArrayList();
118: IntList start = new IntList();
119: IntList end = new IntList();
120: int off = 0;
121:
122: while (m.find()) {
123: start.add(off);
124: end.add(m.start());
125: off = m.end();
126: }
127: start.add(off);
128: end.add(input.length());
129: int size = start.size();
130: int s[] = new int[size];
131: int e[] = new int[size];
132: start.copyInto(s);
133: end.copyInto(e);
134: return new CharSequenceList(input, s, e);
135: }
136:
137: static boolean match(Pattern pattern, CharSequence input,
138: MatchContext mc) {
139: Matcher m = pattern.matcher(input);
140: boolean result = m.find();
141: mc.matcher = m;
142: mc.count = (result ? 1 : 0);
143: return result;
144: }
145:
146: static String getMatch(int idx, MatchContext mc) {
147: Matcher matcher = mc.matcher;
148: if (matcher == null) {
149: return null;
150: } else {
151: try {
152: return matcher.group(idx);
153: } catch (Exception e1) {
154: return null;
155: }
156: }
157: }
158:
159: static int getMatchStart(int idx, MatchContext mc) {
160: Matcher matcher = mc.matcher;
161: if (matcher == null) {
162: return -1;
163: } else {
164: try {
165: return matcher.start(idx);
166: } catch (Exception e1) {
167: return -1;
168: }
169: }
170: }
171:
172: static int getMatchEnd(int idx, MatchContext mc) {
173: Matcher matcher = mc.matcher;
174: if (matcher == null) {
175: return -1;
176: } else {
177: try {
178: return matcher.end(idx);
179: } catch (Exception e1) {
180: return -1;
181: }
182: }
183: }
184:
185: static int getNumberOfGroups(MatchContext mc) {
186: Matcher matcher = mc.matcher;
187: if (matcher != null) {
188: return matcher.groupCount();
189: } else {
190: return -1;
191: }
192: }
193:
194: static int getMatchCount(MatchContext mc) {
195: return mc.count;
196: }
197:
198: static Object matchAll(Pattern pattern, CharSequence input,
199: final Context context) {
200: Matcher matcher = pattern.matcher(input);
201: boolean result = matcher.find();
202: int matchCount = 0;
203: while (result) {
204: matchCount++;
205: result = matcher.find();
206: }
207: return new Integer(matchCount);
208: }
209:
210: static Object matchAll(Pattern pattern, CharSequence input,
211: PnutsFunction func, final Context context) {
212:
213: final Matcher matcher = pattern.matcher(input);
214:
215: if (func != null && !func.defined(1) && !func.defined(-1)) {
216: throw new IllegalArgumentException();
217: }
218: if (func != null) {
219: boolean result = matcher.find();
220: if (result) {
221: int matchCount = 0;
222: MatchContext mc = new MatchContext();
223: mc.matcher = matcher;
224: while (result) {
225: matchCount++;
226: Context ctx = (Context) context.clone();
227: ctx.set(CONTEXT_SYMBOL, mc);
228: func.call(new Object[] { input.subSequence(matcher
229: .start(), matcher.end()) }, ctx);
230: result = matcher.find();
231: }
232: return new Integer(matchCount);
233: }
234: } else {
235: return new MatchIterator(matcher, input);
236: }
237: return null;
238: }
239:
240: static class MatchIterator implements Iterator {
241: boolean checkNeeded = true;
242: Matcher matcher;
243: CharSequence input;
244: boolean result;
245:
246: MatchIterator(Matcher matcher, CharSequence input) {
247: this .matcher = matcher;
248: this .input = input;
249: }
250:
251: synchronized void check() {
252: if (checkNeeded) {
253: result = matcher.find();
254: checkNeeded = false;
255: }
256: }
257:
258: public boolean hasNext() {
259: check();
260: return result;
261: }
262:
263: public Object next() {
264: check();
265: if (!result) {
266: throw new NoSuchElementException();
267: }
268: checkNeeded = true;
269: return input.subSequence(matcher.start(), matcher.end());
270: }
271:
272: public void remove() {
273: throw new UnsupportedOperationException();
274: }
275: }
276:
277: static Object substitute(Pattern pattern, Object replacement,
278: CharSequence input, boolean g_option, boolean n_option,
279: MatchContext mc, Context context) {
280: Matcher m = pattern.matcher(input);
281: mc.matcher = m;
282: int len = input.length();
283: Object ret;
284: int matchCount = 0;
285:
286: if (replacement instanceof CharSequence) {
287: if (n_option) {
288: boolean result = m.find();
289: if (result) {
290: int start;
291: int idx = 0;
292: StringBuffer sbuf = new StringBuffer(len);
293: if (g_option) {
294: while (result) {
295: start = m.start();
296: sbuf.append(input.subSequence(idx, start));
297: sbuf.append(replacement);
298: idx = m.end();
299: if (idx == len)
300: break;
301: result = m.find();
302: }
303: sbuf.append(input.subSequence(idx, input
304: .length()));
305: } else {
306: start = m.start();
307: sbuf.append(input.subSequence(0, start));
308: sbuf.append(replacement);
309: idx = m.end();
310: sbuf.append(input.subSequence(idx, input
311: .length()));
312: }
313: ret = sbuf.toString();
314: } else {
315: ret = input;
316: }
317: } else {
318: StringBuffer sb = new StringBuffer(len);
319: m.reset();
320: String str = replacement.toString();
321: boolean result = m.find();
322: if (result) {
323: if (g_option) {
324: while (result) {
325: matchCount++;
326: m.appendReplacement(sb, str);
327: result = m.find();
328: }
329: } else {
330: matchCount++;
331: m.appendReplacement(sb, str);
332: }
333: m.appendTail(sb);
334: ret = sb.toString();
335: } else {
336: ret = input;
337: }
338: }
339: } else if (replacement instanceof PnutsFunction) {
340: PnutsFunction func = (PnutsFunction) replacement;
341: boolean hasArg = false;
342: if (func.defined(1)) {
343: hasArg = true;
344: } else if (!func.defined(0) && !func.defined(-1)) {
345: throw new IllegalArgumentException();
346: }
347: StringBuffer sbuf = new StringBuffer(len);
348: boolean result = m.find();
349: int idx = 0;
350: if (result) {
351: int start;
352: while (result) {
353: matchCount++;
354: start = m.start();
355: sbuf.append(input.subSequence(idx, start));
356:
357: Context ctx = (Context) context.clone();
358: mc.matcher = m;
359: ctx.set(CONTEXT_SYMBOL, mc);
360: Object v;
361: idx = m.end();
362: if (hasArg) {
363: v = func.call(new Object[] { input.subSequence(
364: start, idx) }, ctx);
365: } else {
366: v = func.call(NO_PARAM, ctx);
367:
368: }
369: if (v instanceof String) {
370: sbuf.append((String) v);
371: }
372: if (idx == len)
373: break;
374: if (!g_option)
375: break;
376: result = m.find();
377: }
378: }
379: sbuf.append(input.subSequence(idx, input.length()));
380: ret = sbuf.toString();
381: } else {
382: throw new IllegalArgumentException();
383: }
384: mc.count = matchCount;
385: return ret;
386: }
387:
388: /**
389: * split(pattern, input {, options })
390: */
391: class split extends PnutsFunction {
392: public split() {
393: super ("split");
394: }
395:
396: public boolean defined(int nargs) {
397: return (nargs == 2 || nargs == 3);
398: }
399:
400: protected Object exec(Object[] args, Context context) {
401: String option;
402: int nargs = args.length;
403: if (nargs == 3) {
404: option = (String) args[2];
405: } else if (nargs == 2) {
406: option = null;
407: } else {
408: undefined(args, context);
409: return null;
410: }
411: Pattern p;
412: Object arg0 = args[0];
413: if (arg0 instanceof Pattern) {
414: p = (Pattern) arg0;
415: } else if (arg0 instanceof String) {
416: p = getPattern((String) arg0, option, context);
417: } else {
418: throw new IllegalArgumentException(String.valueOf(arg0));
419: }
420: CharSequence input = (CharSequence) args[1];
421: return split(p, input);
422: }
423:
424: public String toString() {
425: return "function split(pattern, CharSequence {, options })";
426: }
427: }
428:
429: /**
430: * match(pattern, input {, options })
431: */
432: class match extends PnutsFunction {
433:
434: public match() {
435: super ("match");
436: }
437:
438: public boolean defined(int narg) {
439: return (narg == 2 || narg == 3);
440: }
441:
442: protected Object exec(Object[] args, Context context) {
443: int nargs = args.length;
444: String option;
445: if (nargs == 3) {
446: option = (String) args[2];
447: } else if (nargs == 2) {
448: option = null;
449: } else {
450: undefined(args, context);
451: return null;
452: }
453: Pattern p;
454: Object arg0 = args[0];
455: if (arg0 instanceof Pattern) {
456: p = (Pattern) arg0;
457: } else if (arg0 instanceof String) {
458: p = getPattern((String) arg0, option, context);
459: } else {
460: throw new IllegalArgumentException(String.valueOf(arg0));
461: }
462: CharSequence input = (CharSequence) args[1];
463:
464: MatchContext mc = (MatchContext) context
465: .get(CONTEXT_SYMBOL);
466: if (mc == null) {
467: context.set(CONTEXT_SYMBOL, mc = new MatchContext());
468: }
469: return new Boolean(match(p, input, mc));
470: }
471:
472: public String toString() {
473: return "function match(pattern, CharSequence input {, options } )";
474: }
475: }
476:
477: static MatchContext mc = new MatchContext();
478:
479: /**
480: * substitute(pattern, replacement, input {, options })
481: */
482: class substitute extends PnutsFunction {
483: public substitute() {
484: super ("substitute");
485: }
486:
487: public boolean defined(int narg) {
488: return (narg == 3 || narg == 4);
489: }
490:
491: protected Object exec(Object[] args, Context context) {
492: String option;
493: int nargs = args.length;
494: if (nargs == 4) {
495: option = (String) args[3];
496: } else if (nargs == 3) {
497: option = null;
498: } else {
499: undefined(args, context);
500: return null;
501: }
502: Pattern p;
503: Object arg0 = args[0];
504: if (arg0 instanceof Pattern) {
505: p = (Pattern) arg0;
506: } else if (arg0 instanceof String) {
507: p = getPattern((String) arg0, option, context);
508: } else {
509: throw new IllegalArgumentException(String.valueOf(arg0));
510: }
511: boolean g_option = (option != null && (option.indexOf('g') >= 0));
512: boolean n_option = (option != null && (option.indexOf('n') >= 0));
513:
514: Object replacement = args[1];
515: CharSequence input = (CharSequence) args[2];
516:
517: MatchContext mc = new MatchContext();
518: context.set(CONTEXT_SYMBOL, mc);
519: return substitute(p, replacement, input, g_option,
520: n_option, mc, context);
521: }
522:
523: public String toString() {
524: return "function substitute(pattern, (func()|CharSequence) replacement, CharSequence input {, options } )";
525: }
526: }
527:
528: /**
529: * matchAll(pattern, input {, func(word) {, option }} )
530: */
531: class matchAll extends PnutsFunction {
532: public matchAll() {
533: super ("matchAll");
534: }
535:
536: public boolean defined(int nargs) {
537: return nargs == 2 || nargs == 3 || nargs == 4;
538: }
539:
540: protected Object exec(Object[] args, Context context) {
541: String option;
542: PnutsFunction func;
543: boolean nullfunc = false;
544: int nargs = args.length;
545: if (nargs == 4) {
546: func = (PnutsFunction) args[2];
547: if (func == null) {
548: nullfunc = true;
549: }
550: option = (String) args[3];
551: } else if (nargs == 3) {
552: func = (PnutsFunction) args[2];
553: if (func == null) {
554: nullfunc = true;
555: }
556: option = null;
557: } else if (nargs == 2) {
558: func = null;
559: option = null;
560: } else {
561: undefined(args, context);
562: return null;
563: }
564: Object arg0 = args[0];
565: Pattern p;
566: if (arg0 instanceof Pattern) {
567: p = (Pattern) arg0;
568: } else if (arg0 instanceof String) {
569: p = getPattern((String) arg0, option, context);
570: } else {
571: throw new IllegalArgumentException(String.valueOf(arg0));
572: }
573: if (nullfunc) {
574: return matchAll(p, (CharSequence) args[1], context);
575: } else {
576: return matchAll(p, (CharSequence) args[1], func,
577: context);
578: }
579: }
580:
581: public String toString() {
582: return "function matchAll(pattern, CharSequence {, func() {, options }} )";
583: }
584: }
585:
586: class formatMatch extends PnutsFunction {
587: public formatMatch() {
588: super ("formatMatch");
589: }
590:
591: public boolean defined(int nargs) {
592: return nargs == 1;
593: }
594:
595: protected Object exec(Object[] args, Context context) {
596: if (args.length != 1) {
597: undefined(args, context);
598: return null;
599: }
600: MatchContext mc = (MatchContext) context
601: .get(CONTEXT_SYMBOL);
602: if (mc == null) {
603: return null;
604: }
605: Matcher matcher = mc.matcher;
606: if (matcher == null) {
607: return null;
608: }
609: StringBuffer result = new StringBuffer();
610: int cursor = 0;
611: String replacement = args[0].toString();
612:
613: while (cursor < replacement.length()) {
614: char nextChar = replacement.charAt(cursor);
615: if (nextChar == '\\') {
616: cursor++;
617: nextChar = replacement.charAt(cursor);
618: result.append(nextChar);
619: cursor++;
620: } else if (nextChar == '$') {
621: // Skip past $
622: cursor++;
623:
624: // The first number is always a group
625: int refNum = (int) replacement.charAt(cursor) - '0';
626: if ((refNum < 0) || (refNum > 9))
627: throw new IllegalArgumentException(
628: "Illegal group reference");
629: cursor++;
630:
631: // Capture the largest legal group string
632: boolean done = false;
633: while (!done) {
634: if (cursor >= replacement.length()) {
635: break;
636: }
637: int nextDigit = replacement.charAt(cursor) - '0';
638: if ((nextDigit < 0) || (nextDigit > 9)) { // not a number
639: break;
640: }
641: int newRefNum = (refNum * 10) + nextDigit;
642: if (matcher.groupCount() < newRefNum) {
643: done = true;
644: } else {
645: refNum = newRefNum;
646: cursor++;
647: }
648: }
649:
650: // Append group
651: if (matcher.group(refNum) != null)
652: result.append(matcher.group(refNum));
653: } else {
654: result.append(nextChar);
655: cursor++;
656: }
657: }
658: return result.toString();
659: }
660:
661: public String toString() {
662: return "function formatMatch(String template)";
663: }
664: }
665:
666: /**
667: * regex(pattern{, option})
668: */
669: class regex extends PnutsFunction {
670:
671: public regex() {
672: super ("regex");
673: }
674:
675: public boolean defined(int nargs) {
676: return nargs == 1 || nargs == 2;
677: }
678:
679: protected Object exec(Object[] args, Context context) {
680: String option = null;
681: int nargs = args.length;
682: if (nargs == 2) {
683: option = (String) args[1];
684: } else if (nargs != 1) {
685: undefined(args, context);
686: return null;
687: }
688: Object expr = args[0];
689: if (expr instanceof Pattern) {
690: return expr;
691: } else if (expr instanceof String) {
692: return getPattern((String) expr, option, context);
693: } else {
694: throw new IllegalArgumentException(String.valueOf(expr));
695: }
696: }
697:
698: public String toString() {
699: return "function regex(String pattern {, option })";
700: }
701: }
702:
703: /**
704: * getMatch(index)
705: */
706: class getMatch extends PnutsFunction {
707:
708: public getMatch() {
709: super ("getMatch");
710: }
711:
712: public boolean defined(int narg) {
713: return (narg == 1);
714: }
715:
716: protected Object exec(Object[] args, Context context) {
717: if (args.length == 1) {
718: MatchContext mc = (MatchContext) context
719: .get(CONTEXT_SYMBOL);
720: if (mc == null) {
721: return null;
722: }
723: int idx = ((Integer) args[0]).intValue();
724: return getMatch(idx, mc);
725: } else {
726: undefined(args, context);
727: return null;
728: }
729: }
730:
731: public String toString() {
732: return "function getMatch(int n)";
733: }
734: }
735:
736: /**
737: * getMatches()
738: */
739: class getMatches extends PnutsFunction {
740:
741: public getMatches() {
742: super ("getMatches");
743: }
744:
745: public boolean defined(int narg) {
746: return (narg == 0);
747: }
748:
749: protected Object exec(Object[] args, Context context) {
750: if (args.length == 0) {
751: MatchContext mc = (MatchContext) context
752: .get(CONTEXT_SYMBOL);
753: if (mc == null) {
754: return null;
755: }
756: Matcher matcher = mc.matcher;
757: if (matcher != null) {
758: int c = matcher.groupCount();
759: Object[] array = new Object[c];
760: for (int i = 0; i < c; i++) {
761: array[i] = getMatch(i + 1, mc);
762: }
763: return array;
764: } else {
765: return null;
766: }
767: } else {
768: undefined(args, context);
769: return null;
770: }
771: }
772:
773: public String toString() {
774: return "function getMatches()";
775: }
776: }
777:
778: /**
779: * getMatchStart(index)
780: */
781: class getMatchStart extends PnutsFunction {
782:
783: public getMatchStart() {
784: super ("getMatchStart");
785: }
786:
787: public boolean defined(int narg) {
788: return (narg == 1);
789: }
790:
791: protected Object exec(Object[] args, Context context) {
792: if (args.length == 1) {
793: MatchContext mc = (MatchContext) context
794: .get(CONTEXT_SYMBOL);
795: if (mc == null) {
796: return null;
797: }
798: int idx = ((Integer) args[0]).intValue();
799: int start = getMatchStart(idx, mc);
800: if (start >= 0) {
801: return new Integer(start);
802: } else {
803: return null;
804: }
805: } else {
806: undefined(args, context);
807: return null;
808: }
809: }
810:
811: public String toString() {
812: return "function getMatchStart(int n)";
813: }
814: }
815:
816: /**
817: * getMatchEnd(index)
818: */
819: class getMatchEnd extends PnutsFunction {
820:
821: public getMatchEnd() {
822: super ("getMatchEnd");
823: }
824:
825: public boolean defined(int narg) {
826: return (narg == 1);
827: }
828:
829: protected Object exec(Object[] args, Context context) {
830: if (args.length == 1) {
831: MatchContext mc = (MatchContext) context
832: .get(CONTEXT_SYMBOL);
833: if (mc == null) {
834: return null;
835: }
836: int idx = ((Integer) args[0]).intValue();
837: int end = getMatchEnd(idx, mc);
838: if (end >= 0) {
839: return new Integer(end);
840: } else {
841: return null;
842: }
843: } else {
844: undefined(args, context);
845: return null;
846: }
847: }
848:
849: public String toString() {
850: return "function getMatchEnd(int n)";
851: }
852: }
853:
854: /**
855: * getNumberOfGroups()
856: */
857: class getNumberOfGroups extends PnutsFunction {
858: public getNumberOfGroups() {
859: super ("getNumberOfGroups");
860: }
861:
862: public boolean defined(int narg) {
863: return (narg == 0);
864: }
865:
866: protected Object exec(Object[] args, Context context) {
867: if (args.length == 0) {
868: MatchContext mc = (MatchContext) context
869: .get(CONTEXT_SYMBOL);
870: if (mc == null) {
871: return null;
872: }
873: int num = getNumberOfGroups(mc);
874: if (num < 0) {
875: return null;
876: } else {
877: return new Integer(num);
878: }
879: } else {
880: undefined(args, context);
881: return null;
882: }
883: }
884:
885: public String toString() {
886: return "function getNumberOfGroups()";
887: }
888: }
889:
890: /**
891: * getMatchCount()
892: */
893: class getMatchCount extends PnutsFunction {
894:
895: public getMatchCount() {
896: super ("getMatchCount");
897: }
898:
899: public boolean defined(int narg) {
900: return (narg == 0);
901: }
902:
903: protected Object exec(Object[] args, Context context) {
904: if (args.length != 0) {
905: undefined(args, context);
906: return null;
907: }
908: MatchContext mc = (MatchContext) context
909: .get(CONTEXT_SYMBOL);
910: if (mc != null) {
911: return new Integer(getMatchCount(mc));
912: } else {
913: return new Integer(0);
914: }
915: }
916:
917: public String toString() {
918: return "function getMatchCount()";
919: }
920: }
921:
922: /**
923: * whichRegexAPI()
924: */
925: class whichRegexAPI extends PnutsFunction {
926:
927: public whichRegexAPI() {
928: super ("whichRegexAPI");
929: }
930:
931: public boolean defined(int narg) {
932: return (narg == 0);
933: }
934:
935: protected Object exec(Object[] args, Context context) {
936: if (args.length == 0) {
937: return CONTEXT_SYMBOL;
938: } else {
939: undefined(args, context);
940: return null;
941: }
942: }
943:
944: public String toString() {
945: return "function whichRegexAPI()";
946: }
947: }
948:
949: public void registerAll(Package pkg, Context context) {
950: pkg.set("match".intern(), new match(), context);
951: pkg.set("matchAll".intern(), new matchAll(), context);
952: pkg.set("split".intern(), new split(), context);
953: pkg.set("substitute".intern(), new substitute(), context);
954: pkg.set("formatMatch".intern(), new formatMatch(), context);
955: pkg.set("regex".intern(), new regex(), context);
956: pkg.set("getMatch".intern(), new getMatch(), context);
957: pkg.set("getMatches".intern(), new getMatches(), context);
958: pkg.set("getMatchStart".intern(), new getMatchStart(), context);
959: pkg.set("getMatchEnd".intern(), new getMatchEnd(), context);
960: pkg.set("getNumberOfGroups".intern(), new getNumberOfGroups(),
961: context);
962: pkg.set("getMatchCount".intern(), new getMatchCount(), context);
963: pkg.set("whichRegexAPI".intern(), new whichRegexAPI(), context);
964: }
965: }
|