]> gitweb.fperrin.net Git - Dictionary.git/blob - jars/icu4j-4_4_2-src/main/tests/translit/src/com/ibm/icu/dev/test/util/Pick.java
go
[Dictionary.git] / jars / icu4j-4_4_2-src / main / tests / translit / src / com / ibm / icu / dev / test / util / Pick.java
1 /*\r
2  *******************************************************************************\r
3  * Copyright (C) 2002-2010, International Business Machines Corporation and    *\r
4  * others. All Rights Reserved.                                                *\r
5  *******************************************************************************\r
6  */\r
7 package com.ibm.icu.dev.test.util;\r
8 \r
9 import java.util.ArrayList;\r
10 import java.util.Arrays;\r
11 import java.util.HashSet;\r
12 import java.util.Random;\r
13 import java.util.Set;\r
14 \r
15 import com.ibm.icu.text.UTF16;\r
16 import com.ibm.icu.text.UnicodeSet;\r
17 \r
18 abstract public class Pick {\r
19     private static boolean DEBUG = false;\r
20     \r
21     // for using to get strings\r
22     \r
23     static class Target {\r
24         private Pick pick;\r
25         private Random random;\r
26         private Quoter quoter;\r
27         \r
28         public static Target make(Pick pick, Random random, Quoter quoter) {\r
29             Target result = new Target();\r
30             result.pick = pick;\r
31             result.random = random;\r
32             result.quoter = quoter;\r
33             return result;\r
34         }\r
35         public String next() {\r
36             quoter.clear();\r
37             pick.addTo(this);\r
38             return get();\r
39         }        \r
40         public String get() {\r
41             return quoter.toString();\r
42         }\r
43         private void copyState(Target other) {\r
44             random = other.random;\r
45         }\r
46         private void clear() {\r
47             quoter.clear();\r
48         }\r
49         /*private int length() {\r
50             return quoter.length();\r
51         }*/\r
52         private Target append(int codepoint) {\r
53             quoter.append(codepoint);\r
54             return this;\r
55         }\r
56         private Target append(String s) {\r
57             quoter.append(s);\r
58             return this;\r
59         }\r
60         // must return value between 0 (inc) and 1 (exc)\r
61         private double nextDouble() {\r
62             return random.nextDouble();\r
63         }\r
64     }\r
65 \r
66     // for Building\r
67     \r
68     public Pick replace(String toReplace, Pick replacement) {\r
69        Replacer visitor = new Replacer(toReplace, replacement);\r
70        return visit(visitor);\r
71     }\r
72 \r
73     public Pick name(String nameStr) {\r
74         name = nameStr;\r
75         return this;\r
76     }\r
77     \r
78     static public Pick.Sequence makeSequence() {\r
79         return new Sequence();\r
80     }\r
81     static public Pick.Alternation makeAlternation() {\r
82         return new Alternation();\r
83     }\r
84     /*\r
85     static public Pick.Sequence and(Object item) {\r
86         return new Sequence().and2(item);\r
87     }\r
88     static public Pick.Sequence and(Object[] items) {\r
89         return new Sequence().and2(items);\r
90     }\r
91     static public Pick.Alternation or(int itemWeight, Object item) {\r
92         return new Alternation().or2(itemWeight, item);\r
93     }\r
94     static public Pick.Alternation or(Object[] items) {\r
95         return new Alternation().or2(1, items);\r
96     }\r
97     static public Pick.Alternation or(int itemWeight, Object[] items) {\r
98         return new Alternation().or2(itemWeight, items);\r
99     }\r
100     static public Pick.Alternation or(int[] itemWeights, Object[] items) {\r
101         return new Alternation().or2(itemWeights, items);\r
102     }\r
103     \r
104     static public Pick maybe(int percent, Object item) {\r
105         return new Repeat(0, 1, new int[]{100-percent, percent}, item);\r
106         //return Pick.or(1.0-percent, NOTHING).or2(percent, item);\r
107     }\r
108     static public Pick repeat(int minCount, int maxCount, int itemWeights, Object item) {\r
109         return new Repeat(minCount, maxCount, itemWeights, item);\r
110     }\r
111     \r
112     static public Pick codePoint(String source) {\r
113         return new CodePoint(new UnicodeSet(source));\r
114     }\r
115     */\r
116     \r
117     static public Pick repeat(int minCount, int maxCount, int[] itemWeights, Pick item) {\r
118         return new Repeat(minCount, maxCount, itemWeights, item);\r
119     }\r
120     \r
121     static public Pick codePoint(UnicodeSet source) {\r
122         return new CodePoint(source);\r
123     }\r
124     static public Pick string(String source) {\r
125         return new Literal(source);\r
126     }\r
127     /*\r
128     static public Pick unquoted(String source) {\r
129         return new Literal(source);\r
130     }\r
131     static public Pick string(int minLength, int maxLength, Pick item) {\r
132         return new Morph(item, minLength, maxLength);\r
133     }\r
134     */\r
135     \r
136     public abstract String getInternal(int depth, Set alreadySeen);\r
137     // Internals\r
138    \r
139     protected String name;\r
140     \r
141     protected abstract void addTo(Target target);\r
142     protected abstract boolean match(String input, Position p);\r
143     \r
144     public static class Sequence extends ListPick {\r
145         public Sequence and2 (Pick item) {\r
146             addInternal(new Pick[] {item}); // we don't care about perf\r
147             return this; // for chaining\r
148         }\r
149         public Sequence and2 (Pick[] itemArray) {\r
150             addInternal(itemArray);\r
151             return this; // for chaining\r
152         }\r
153         protected void addTo(Target target) {\r
154             for (int i = 0; i < items.length; ++i) {\r
155                 items[i].addTo(target);\r
156             }\r
157         }\r
158         public String getInternal(int depth, Set alreadySeen) {\r
159             String result = checkName(name, alreadySeen);\r
160             if (result.startsWith("$")) return result;\r
161             result = indent(depth) + result + "SEQ(";\r
162             for (int i = 0; i < items.length; ++i) {\r
163                 if (i != 0) result += ", ";\r
164                 result += items[i].getInternal(depth+1, alreadySeen);\r
165             }\r
166             result += ")";\r
167             return result;\r
168         }\r
169         // keep private\r
170         private Sequence() {}\r
171         protected boolean match(String input, Position p) {\r
172             int originalIndex = p.index;\r
173             for (int i = 0; i < items.length; ++i) {\r
174                 if (!items[i].match(input, p)) {\r
175                     p.index = originalIndex;\r
176                     return false;\r
177                 }\r
178             }\r
179             return true;\r
180         }\r
181     }\r
182     \r
183     String checkName(String nameStr, Set alreadySeen) {\r
184         if (nameStr == null) return "";\r
185         if (alreadySeen.contains(nameStr)) return nameStr;\r
186         alreadySeen.add(nameStr);\r
187         return "{" + nameStr + "=}";\r
188     }\r
189 \r
190     public static class Alternation extends ListPick {\r
191         private WeightedIndex weightedIndex = new WeightedIndex(0);\r
192            \r
193         public Alternation or2 (Pick[] newItems) {\r
194             return or2(1, newItems);\r
195         }\r
196         public Alternation or2 (int itemWeight, Pick item) {\r
197             return or2(itemWeight, new Pick[] {item}); // we don't care about perf\r
198         }\r
199         public Alternation or2 (int itemWeight, Pick[] newItems) {\r
200             int[] itemWeights = new int[newItems.length];\r
201             Arrays.fill(itemWeights,itemWeight);\r
202             return or2(itemWeights, newItems); // we don't care about perf\r
203         }\r
204         public Alternation or2 (int[] itemWeights, Pick[] newItems) {\r
205             if (newItems.length != itemWeights.length) {\r
206                 throw new ArrayIndexOutOfBoundsException(\r
207                     "or lengths must be equal: " + newItems.length + " != " + itemWeights.length);\r
208             }\r
209            // int lastLen = this.items.length;\r
210             addInternal(newItems);\r
211             weightedIndex.add(itemWeights);\r
212             return this; // for chaining\r
213         }\r
214         protected void addTo(Target target) {\r
215             items[weightedIndex.toIndex(target.nextDouble())].addTo(target);\r
216         }    \r
217         \r
218         public String getInternal(int depth, Set alreadySeen) {\r
219             String result = checkName(name, alreadySeen);\r
220             if (result.startsWith("$")) return result;\r
221             result = indent(depth) + result + "OR(";\r
222             for (int i = 0; i < items.length; ++i) {\r
223                 if (i != 0) result += ", ";\r
224                 result += items[i].getInternal(depth+1, alreadySeen) + "/" + weightedIndex.weights[i];\r
225             }\r
226             return result + ")";\r
227         }\r
228         // keep private\r
229         private Alternation() {}\r
230         // take first matching option\r
231         protected boolean match(String input, Position p) {\r
232             for (int i = 0; i < weightedIndex.weights.length; ++i) {\r
233                 if (p.isFailure(this,i)) continue;\r
234                 if (items[i].match(input, p)) return true;\r
235                 p.setFailure(this, i);\r
236             }\r
237             return false;\r
238         }\r
239     }\r
240     \r
241     private static String indent(int depth) {\r
242         String result = "\r\n";\r
243         for (int i = 0; i < depth; ++i) {\r
244             result += " ";\r
245         }\r
246         return result;\r
247     }\r
248     \r
249     private static class Repeat extends ItemPick {\r
250         WeightedIndex weightedIndex;\r
251         int minCount = 0;\r
252             \r
253         private Repeat(int minCount, int maxCount, int[] itemWeights, Pick item) {\r
254             super(item);\r
255             weightedIndex = new WeightedIndex(minCount).add(maxCount-minCount+1, itemWeights);\r
256         }\r
257         /*private Repeat(int minCount, int maxCount, int itemWeight, Pick item) {\r
258             super(item);\r
259             weightedIndex = new WeightedIndex(minCount).add(maxCount-minCount+1, itemWeight);\r
260         }*/\r
261         /*\r
262         private Repeat(int minCount, int maxCount, Object item) {\r
263             this.item = convert(item);\r
264             weightedIndex = new WeightedIndex(minCount).add(maxCount-minCount+1, 1);\r
265         }\r
266         */\r
267         protected void addTo(Target target) {\r
268             //int count ;\r
269             for (int i = weightedIndex.toIndex(target.nextDouble()); i > 0; --i) {\r
270                 item.addTo(target);\r
271             }\r
272         }\r
273         public String getInternal(int depth, Set alreadySeen) {\r
274             String result = checkName(name, alreadySeen);\r
275             if (result.startsWith("$")) return result;\r
276             result = indent(depth) + result + "REPEAT(" + weightedIndex\r
277             + "; "+ item.getInternal(depth+1, alreadySeen) \r
278             + ")";\r
279             return result;\r
280         }\r
281         \r
282         // match longest, e.g. up to just before a failure\r
283         protected boolean match(String input, Position p) {\r
284             //int bestMatch = p.index;\r
285             int count = 0;\r
286             for (int i = 0; i < weightedIndex.weights.length; ++i) {\r
287                 if (p.isFailure(this,i)) break;\r
288                 if (!item.match(input, p)) {\r
289                     p.setFailure(this,i);\r
290                     break;\r
291                 } \r
292                 //bestMatch = p.index;\r
293                 count++;               \r
294             }\r
295             if (count >= minCount) {\r
296                 return true;\r
297             }\r
298             // TODO fix failure\r
299             return false;\r
300         }\r
301     }\r
302     \r
303     private static class CodePoint extends FinalPick {\r
304         private UnicodeSet source;\r
305         \r
306         private CodePoint(UnicodeSet source) {\r
307             this.source = source;\r
308         }\r
309         protected void addTo(Target target) {\r
310             target.append(source.charAt(pick(target.random,0,source.size()-1)));\r
311         }\r
312         protected boolean match(String s, Position p) {\r
313             int cp = UTF16.charAt(s, p.index);\r
314             if (source.contains(cp)) {\r
315                 p.index += UTF16.getCharCount(cp);\r
316                 return true;\r
317             }\r
318             p.setMax("codePoint");\r
319             return false;\r
320         }\r
321         public String getInternal(int depth, Set alreadySeen) {\r
322             String result = checkName(name, alreadySeen);\r
323             if (result.startsWith("$")) return result;\r
324             return source.toString();\r
325         }\r
326     }\r
327 \r
328     static class Morph extends ItemPick {\r
329         Morph(Pick item) {\r
330             super(item);\r
331         }\r
332     \r
333         private String lastValue = null;\r
334         private Target addBuffer = Target.make(this, null, new Quoter.RuleQuoter());\r
335         private StringBuffer mergeBuffer = new StringBuffer();\r
336     \r
337         private static final int COPY_NEW = 0, COPY_BOTH = 1, COPY_LAST = 3, SKIP = 4,\r
338                                  LEAST_SKIP = 4;\r
339         // give weights to the above. make sure we delete about the same as we insert\r
340         private static final WeightedIndex choice = new WeightedIndex(0)\r
341             .add(new int[] {10, 10, 100, 10});\r
342         \r
343         protected void addTo(Target target) {\r
344             // get contents into separate buffer\r
345             addBuffer.copyState(target);\r
346             addBuffer.clear();\r
347             item.addTo(addBuffer);\r
348             String newValue = addBuffer.get();\r
349             if (DEBUG) System.out.println("Old: " + lastValue + ", New:" + newValue);\r
350 \r
351             // if not first one, merge with old\r
352             if (lastValue != null) {\r
353                 mergeBuffer.setLength(0);\r
354                 int lastIndex = 0;\r
355                 int newIndex = 0;\r
356                 // the new length is a random value between old and new.\r
357                 int newLenLimit = (int) pick(target.random, lastValue.length(), newValue.length());\r
358                 \r
359                 while (mergeBuffer.length() < newLenLimit\r
360                   && newIndex < newValue.length()\r
361                   && lastIndex < lastValue.length()) {\r
362                     int c = choice.toIndex(target.nextDouble());\r
363                     if (c == COPY_NEW || c == COPY_BOTH || c == SKIP) {\r
364                         newIndex = getChar(newValue, newIndex, mergeBuffer, c < LEAST_SKIP);\r
365                         if (mergeBuffer.length() >= newLenLimit) break;\r
366                     }\r
367                     if (c == COPY_LAST || c == COPY_BOTH || c == SKIP) {\r
368                         lastIndex = getChar(lastValue, lastIndex, mergeBuffer, c < LEAST_SKIP);\r
369                     }\r
370                 }\r
371                 newValue = mergeBuffer.toString();\r
372             }\r
373             lastValue = newValue;\r
374             target.append(newValue);\r
375             if (DEBUG) System.out.println("Result: " + newValue);\r
376         }\r
377 \r
378         public String getInternal(int depth, Set alreadySeen) {\r
379             String result = checkName(name, alreadySeen);\r
380             if (result.startsWith("$")) return result;\r
381             return indent(depth) + result + "MORPH("\r
382                 + item.getInternal(depth+1, alreadySeen)\r
383                 + ")";\r
384         }\r
385 \r
386         /* (non-Javadoc)\r
387          * @see Pick#match(java.lang.String, Pick.Position)\r
388          */\r
389         protected boolean match(String input, Position p) {\r
390             // TODO Auto-generated method stub\r
391             return false;\r
392         }\r
393     }\r
394     \r
395     /* Add character if we can\r
396      */\r
397     static int getChar(String newValue, int newIndex, StringBuffer mergeBuffer, boolean copy) {\r
398         if (newIndex >= newValue.length()) return newIndex;\r
399         int cp = UTF16.charAt(newValue,newIndex);\r
400         if (copy) UTF16.append(mergeBuffer, cp);\r
401         return newIndex + UTF16.getCharCount(cp);\r
402     }\r
403 \r
404     /*   \r
405             // quoted add\r
406             appendQuoted(target, addBuffer.toString(), quoteBuffer);\r
407             // fix buffers\r
408             StringBuffer swapTemp = addBuffer;\r
409             addBuffer = source;\r
410             source = swapTemp;\r
411         }\r
412     }\r
413     */\r
414 \r
415 \r
416     static class Quote extends ItemPick {\r
417         Quote(Pick item) {\r
418             super(item);\r
419         }\r
420         protected void addTo(Target target) {\r
421             target.quoter.setQuoting(true);\r
422             item.addTo(target);\r
423             target.quoter.setQuoting(false);\r
424         }\r
425         \r
426         protected boolean match(String s, Position p) {\r
427             return false;\r
428         }\r
429 \r
430         public String getInternal(int depth, Set alreadySeen) {\r
431             String result = checkName(name, alreadySeen);\r
432             if (result.startsWith("$")) return result;\r
433             return indent(depth) + result + "QUOTE(" + item.getInternal(depth+1, alreadySeen)\r
434                 + ")";\r
435         }\r
436     }\r
437     \r
438     private static class Literal extends FinalPick {\r
439         public String toString() {\r
440             return name;     \r
441         }        \r
442         private Literal(String source) {  \r
443             this.name = source;\r
444         }\r
445         protected void addTo(Target target) {\r
446             target.append(name);\r
447         }\r
448         protected boolean match(String input, Position p) {\r
449             int len = name.length();\r
450             if (input.regionMatches(p.index, name, 0, len)) {\r
451                 p.index += len;\r
452                 return true;\r
453             }\r
454             p.setMax("literal");\r
455             return false;\r
456         }\r
457         public String getInternal(int depth, Set alreadySeen) {\r
458             return "'" + name + "'";\r
459         }\r
460     }\r
461     \r
462     public static class Position {\r
463         public ArrayList failures = new ArrayList();\r
464         public int index;\r
465         public int maxInt;\r
466         public String maxType;\r
467         public void setMax(String type) {\r
468             if (index >= maxInt) {\r
469                 maxType = type;\r
470             }\r
471         }\r
472         public String toString() {\r
473             return "index; " + index\r
474                 + ", maxInt:" + maxInt\r
475                 + ", maxType: " + maxType;\r
476         }\r
477         /*private static final Object BAD = new Object();\r
478         private static final Object GOOD = new Object();*/\r
479         \r
480         public boolean isFailure(Pick pick, int item) {\r
481             ArrayList val = (ArrayList)failures.get(index);\r
482             if (val == null) return false;\r
483             Set set = (Set)val.get(item);\r
484             if (set == null) return false;\r
485             return !set.contains(pick);\r
486         }\r
487         public void setFailure(Pick pick, int item) {\r
488             ArrayList val = (ArrayList)failures.get(index);\r
489             if (val == null) {\r
490                 val = new ArrayList();\r
491                 failures.set(index, val);\r
492             }\r
493             Set set = (Set)val.get(item);\r
494             if (set == null) {\r
495                 set = new HashSet();\r
496                 val.set(item, set);\r
497             }\r
498             set.add(pick);\r
499         }\r
500     }\r
501     \r
502     /*\r
503     public static final Pick NOTHING = new Nothing();\r
504     \r
505 \r
506     private static class Nothing extends FinalPick {\r
507         protected void addTo(Target target) {}\r
508         protected boolean match(String input, Position p) {\r
509             return true;\r
510         }\r
511         public String getInternal(int depth, Set alreadySeen) {\r
512             return indent(depth) + "\u00F8";\r
513         }\r
514     }\r
515     */\r
516     \r
517     // intermediates\r
518     \r
519     abstract static class Visitor {\r
520         Set already = new HashSet();\r
521         // Note: each visitor should return the Pick that will replace a (or a itself)\r
522         abstract Pick handle(Pick a);\r
523         boolean alreadyEntered(Pick item) {\r
524             boolean result = already.contains(item);\r
525             already.add(item);\r
526             return result;\r
527         }\r
528         void reset() {\r
529             already.clear();\r
530         }\r
531     }\r
532     \r
533     protected abstract Pick visit(Visitor visitor);\r
534     \r
535     static class Replacer extends Visitor {\r
536         String toReplace;\r
537         Pick replacement;\r
538         Replacer(String toReplace, Pick replacement) {\r
539             this.toReplace = toReplace;\r
540             this.replacement = replacement;\r
541         }\r
542         public Pick handle(Pick a) {\r
543             if (toReplace.equals(a.name)) {\r
544                 a = replacement;\r
545             } \r
546             return a;\r
547        }\r
548     }\r
549 \r
550     abstract private static class FinalPick extends Pick {\r
551         public Pick visit(Visitor visitor) {\r
552             return visitor.handle(this);\r
553        }\r
554     }\r
555     \r
556     private abstract static class ItemPick extends Pick {\r
557        protected Pick item;\r
558        \r
559        ItemPick (Pick item) {\r
560            this.item = item;\r
561        }\r
562        \r
563        public Pick visit(Visitor visitor) {\r
564            Pick result = visitor.handle(this);\r
565            if (visitor.alreadyEntered(this)) return result;\r
566            if (item != null) item = item.visit(visitor);\r
567            return result;\r
568        }\r
569     }\r
570    \r
571     private abstract static class ListPick extends Pick {\r
572         protected Pick[] items = new Pick[0];\r
573 \r
574         @SuppressWarnings("unused")\r
575         Pick simplify() {\r
576             if (items.length > 1) return this;\r
577             if (items.length == 1) return items[0];\r
578             return null;\r
579         }\r
580         \r
581         @SuppressWarnings("unused")\r
582         int size() {\r
583             return items.length;\r
584         }\r
585 \r
586         @SuppressWarnings("unused")\r
587         Pick getLast() {\r
588             return items[items.length-1];\r
589         }\r
590 \r
591         @SuppressWarnings("unused")\r
592         void setLast(Pick newOne) {\r
593             items[items.length-1] = newOne;\r
594         }\r
595 \r
596         protected void addInternal(Pick[] objs) {\r
597             int lastLen = items.length;\r
598             items = realloc(items, items.length + objs.length);\r
599             for (int i = 0; i < objs.length; ++i) {\r
600                 items[lastLen + i] = objs[i];\r
601             }\r
602         }\r
603 \r
604         public Pick visit(Visitor visitor) {\r
605             Pick result = visitor.handle(this);\r
606             if (visitor.alreadyEntered(this)) return result;\r
607             for (int i = 0; i < items.length; ++i) {\r
608                 items[i] = items[i].visit(visitor);\r
609             }\r
610             return result;\r
611         }\r
612     }\r
613     \r
614     /**\r
615      * Simple class to distribute a number between 0 (inclusive) and 1 (exclusive) among\r
616      * a number of indices, where each index is weighted.\r
617      * Item weights may be zero, but cannot be negative.\r
618      * @author Davis\r
619      */\r
620     // As in other case, we use an array for runtime speed; don't care about buildspeed.\r
621     public static class WeightedIndex {\r
622         private int[] weights = new int[0];\r
623         private int minCount = 0;\r
624         private double total;\r
625         \r
626         public WeightedIndex(int minCount) {\r
627             this.minCount = minCount;\r
628         }\r
629         \r
630         public WeightedIndex add(int count, int itemWeights) {\r
631             if (count > 0) {\r
632                 int[] newWeights = new int[count];\r
633                 if (itemWeights < 1) itemWeights = 1;\r
634                 Arrays.fill(newWeights, 0, count, itemWeights);\r
635                 add(1, newWeights);\r
636             }\r
637             return this; // for chaining\r
638         }\r
639 \r
640         public WeightedIndex add(int[] newWeights) {\r
641             return add(newWeights.length, newWeights);\r
642         }\r
643         \r
644         public WeightedIndex add(int maxCount, int[] newWeights) {\r
645             if (newWeights == null) newWeights = new int[]{1};\r
646             int oldLen = weights.length;\r
647             if (maxCount < newWeights.length) maxCount = newWeights.length;\r
648             weights = (int[]) realloc(weights, weights.length + maxCount);\r
649             System.arraycopy(newWeights, 0, weights, oldLen, newWeights.length);\r
650             int lastWeight = weights[oldLen + newWeights.length-1];\r
651             for (int i = oldLen + newWeights.length; i < maxCount; ++i) {\r
652                 weights[i] = lastWeight;\r
653             }\r
654             total = 0;\r
655             for (int i = 0; i < weights.length; ++i) {\r
656                 if (weights[i] < 0) {\r
657                     throw new RuntimeException("only positive weights: " + i);\r
658                 } \r
659                 total += weights[i];\r
660             }\r
661             return this; // for chaining\r
662         }\r
663         \r
664         // TODO, make this more efficient\r
665         public int toIndex(double zeroToOne) {\r
666             double weight = zeroToOne*total;\r
667             int i;\r
668             for (i = 0; i < weights.length; ++i) {\r
669                 weight -= weights[i];\r
670                 if (weight <= 0) break;\r
671             }\r
672             return i + minCount;\r
673         }\r
674         public String toString() {\r
675             String result = "";\r
676             for (int i = 0; i < minCount; ++i) {\r
677                 if (result.length() != 0) result += ",";\r
678                 result += "0";\r
679             }\r
680             for (int i = 0; i < weights.length; ++i) {\r
681                 if (result.length() != 0) result += ",";\r
682                 result += weights[i];\r
683             }\r
684             return result;\r
685         }\r
686     }\r
687     /*\r
688     private static Pick convert(Object obj) {\r
689         if (obj instanceof Pick) return (Pick)obj;\r
690         return new Literal(obj.toString(), false);\r
691     }\r
692     */\r
693     // Useful statics\r
694     \r
695     static public int pick(Random random, int start, int end) {\r
696         return start + (int)(random.nextDouble() * (end + 1 - start));\r
697     }\r
698     \r
699     static public double pick(Random random, double start, double end) {\r
700         return start + (random.nextDouble() * (end + 1 - start));\r
701     }\r
702     \r
703     static public boolean pick(Random random, double percent) {\r
704         return random.nextDouble() <= percent;\r
705     }\r
706     \r
707     static public int pick(Random random, UnicodeSet s) {\r
708         return s.charAt(pick(random, 0,s.size()-1));\r
709     }\r
710     \r
711     static public String pick(Random random, String[] source) {\r
712         return source[pick(random, 0, source.length-1)];\r
713     }\r
714     \r
715     // these utilities really ought to be in Java\r
716     \r
717 public static double[] realloc(double[] source, int newSize) {\r
718     double[] temp = new double[newSize];\r
719     if (newSize > source.length) newSize = source.length;\r
720     if (newSize != 0) System.arraycopy(source,0,temp,0,newSize);\r
721     return temp;\r
722 }\r
723     \r
724 public static int[] realloc(int[] source, int newSize) {\r
725     int[] temp = new int[newSize];\r
726     if (newSize > source.length) newSize = source.length;\r
727     if (newSize != 0) System.arraycopy(source,0,temp,0,newSize);\r
728     return temp;\r
729 }\r
730     \r
731     public static Pick[] realloc(Pick[] source, int newSize) {\r
732         Pick[] temp = new Pick[newSize];\r
733         if (newSize > source.length) newSize = source.length;\r
734         if (newSize != 0) System.arraycopy(source,0,temp,0,newSize);\r
735         return temp;\r
736     }\r
737     \r
738     // test utilities\r
739     /*private static void append(StringBuffer target, String toAdd, StringBuffer quoteBuffer) {\r
740         Utility.appendToRule(target, (int)-1, true, false, quoteBuffer); // close previous quote\r
741         if (DEBUG) System.out.println("\"" + toAdd + "\"");\r
742         target.append(toAdd);\r
743     }\r
744 \r
745     private static void appendQuoted(StringBuffer target, String toAdd, StringBuffer quoteBuffer) {\r
746         if (DEBUG) System.out.println("\"" + toAdd + "\"");\r
747         Utility.appendToRule(target, toAdd, false, false, quoteBuffer);\r
748     }*/\r
749 \r
750     /*\r
751     public static abstract class MatchHandler {\r
752         public abstract void handleString(String source, int start, int limit);\r
753         public abstract void handleSequence(String source, int start, int limit);\r
754         public abstract void handleAlternation(String source, int start, int limit);\r
755             \r
756     }\r
757     */\r
758     /*\r
759     // redistributes random value\r
760     // values are still between 0 and 1, but with a different distribution\r
761     public interface Spread {\r
762         public double spread(double value);\r
763     }\r
764     \r
765     // give the weight for the high end.\r
766     // values are linearly scaled according to the weight.\r
767     static public class SimpleSpread implements Spread {\r
768         static final Spread FLAT = new SimpleSpread(1.0);\r
769         boolean flat = false;\r
770         double aa, bb, cc;\r
771         public SimpleSpread(double maxWeight) {   \r
772             if (maxWeight > 0.999 && maxWeight < 1.001) {\r
773                 flat = true;\r
774             } else { \r
775                 double q = (maxWeight - 1.0);\r
776                 aa = -1/q;\r
777                 bb = 1/(q*q);\r
778                 cc = (2.0+q)/q;\r
779            }                 \r
780         }\r
781         public double spread(double value) {\r
782             if (flat) return value;\r
783             value = aa + Math.sqrt(bb + cc*value);\r
784             if (value < 0.0) return 0.0;    // catch math gorp\r
785             if (value >= 1.0) return 1.0;\r
786             return value;\r
787         }\r
788     }\r
789     static public int pick(Spread spread, Random random, int start, int end) {\r
790         return start + (int)(spread.spread(random.nextDouble()) * (end + 1 - start));\r
791     }\r
792     \r
793    */\r
794     \r
795 \r
796 }