2 // This software is now distributed according to
\r
3 // the Lesser Gnu Public License. Please see
\r
4 // http://www.gnu.org/copyleft/lesser.txt for
\r
6 // -- Happy Computing!
\r
8 package com.stevesoft.pat;
\r
10 import java.util.Vector;
\r
11 import com.stevesoft.pat.wrap.StringWrap;
\r
13 /** Replacement rule used by the Transformer.
\r
14 @see com.stevesoft.pat.Transformer
\r
16 class TransRepRule extends ReplaceRule {
\r
18 TransRepRule(Transformer t) { this.t = t; }
\r
19 public String toString1() { return ""; }
\r
20 public Object clone1() { return new TransRepRule(t); }
\r
21 public void apply(StringBufferLike sb,RegRes rr) {
\r
22 // get the ReplaceRule of the Regex that matched.
\r
23 next = t.tp.ra[t.tp.pn].getReplaceRule();
\r
27 /** Sometimes you want to replace a whole bunch of things
\r
28 that might occur within a single line of text. One efficient
\r
29 way to do this, both in terms of performance and programming
\r
30 ease, is with Transformer. The Transformer contains an array
\r
31 of Regex's and uses the Regex that matches earliest within the
\r
32 text to do the replacing, if two Regex's match at the same
\r
33 time it uses the one put in the Transformer first.
\r
35 This feature can be used to prevent transformations from
\r
36 occurring in certain regions. For example, if I add the rule
\r
37 s'//.*'$&' and then add the
\r
38 rule s/hello/goodbye/ the Transformer will replace "hello"
\r
39 with "goodbye" except when it occurs inside a double-slash
\r
40 style of comment. The transformation on the comment goes first,
\r
41 does nothing, and precludes transformation on the same region
\r
42 of text as the s/hello/goodbye/ rule.
\r
44 So far, at least, this class does not have the capability of
\r
45 turning into a giant robot :-)
\r
47 public class Transformer {
\r
49 Regex rp = new Regex();
\r
50 boolean auto_optimize;
\r
52 /** Get a replacer to that works with the current Regex.
\r
53 @see com.stevesoft.pat.Replacer
\r
55 public Replacer getReplacer() { return rp.getReplacer(); }
\r
57 /** Instantiate a new Transformer object. */
\r
58 public Transformer(boolean auto) {
\r
59 auto_optimize = auto;
\r
60 tp = new TransPat();
\r
61 rp.setReplaceRule(new TransRepRule(this));
\r
65 /** Add a new Regex to the set of Regex's. */
\r
66 public void add(Regex r) {
\r
67 if(auto_optimize) r.optimize();
\r
68 tp.ra[tp.ra_len++] = r;
\r
69 if(tp.ra.length==tp.ra_len) {
\r
70 Regex[] ra2 = new Regex[tp.ra_len+10];
\r
71 for(int i=0;i<tp.ra_len;i++)
\r
75 rp.numSubs_ = r.numSubs_ > rp.numSubs_ ? r.numSubs_ : rp.numSubs_;
\r
78 /** Returns the number of Regex's in this Transformer. */
\r
79 public int patterns() { return tp.ra_len; }
\r
81 /** Get the Regex at position i in this Transformer. */
\r
82 public Regex getRegexAt(int i) {
\r
84 throw new ArrayIndexOutOfBoundsException("i="+i+">="+patterns());
\r
86 throw new ArrayIndexOutOfBoundsException("i="+i+"< 0");
\r
89 /** Set the Regex at position i in this Transformer. */
\r
90 public void setRegexAt(Regex rx,int i) {
\r
92 throw new ArrayIndexOutOfBoundsException("i="+i+">="+patterns());
\r
94 throw new ArrayIndexOutOfBoundsException("i="+i+"< 0");
\r
98 /** Add a new Regex by calling Regex.perlCode
\r
99 @see com.stevesoft.pat.Regex#perlCode(java.lang.String)
\r
101 public void add(String rs) {
\r
102 Regex r = Regex.perlCode(rs);
\r
103 if(r == null) throw new NullPointerException("bad pattern to Regex.perlCode: "+rs);
\r
106 /** Add an array of Strings (which will be converted to
\r
107 Regex's via the Regex.perlCode method.
\r
108 @see com.stevesoft.pat.Regex#perlCode(java.lang.String)
\r
110 public void add(String[] array) {
\r
111 for(int i=0;i<array.length;i++)
\r
114 /** Replace all matches in the current String. */
\r
115 public String replaceAll(String s) {
\r
116 return dorep(s,0,s.length());
\r
118 public StringLike replaceAll(StringLike s) {
\r
119 return dorep(s,0,s.length());
\r
121 /** Replace all matching patterns beginning at position start. */
\r
122 public String replaceAllFrom(String s,int start) {
\r
123 return dorep(s,start,s.length());
\r
125 /** Replace all matching patterns beginning between the positions
\r
126 start and end inclusive. */
\r
127 public String replaceAllRegion(String s,int start,int end) {
\r
128 return dorep(s,start,end);
\r
131 Replacer repr = new Replacer();
\r
132 final StringLike dorep(StringLike s,int start,int end) {
\r
133 StringLike tfmd = repr.replaceAllRegion(s,rp,start,end);
\r
134 tp.lastMatchedTo = repr.lastMatchedTo;
\r
137 final String dorep(String s,int start,int end) {
\r
138 return dorep(new StringWrap(s),start,end).toString();
\r
141 /** Replace the first matching pattern in String s. */
\r
142 public String replaceFirst(String s) {
\r
143 return dorep(s,0,s.length());
\r
145 /** Replace the first matching pattern after position start in
\r
147 public String replaceFirstFrom(String s,int start) {
\r
148 return dorep(s,start,s.length());
\r
150 /** Replace the first matching pattern that begins between
\r
151 start and end inclusive. */
\r
152 public String replaceFirstRegion(String s,int start,int end) {
\r
153 return dorep(s,start,end);
\r