// // This software is now distributed according to // the Lesser Gnu Public License. Please see // http://www.gnu.org/copyleft/lesser.txt for // the details. // -- Happy Computing! // package com.stevesoft.pat; import com.stevesoft.pat.wrap.*; /** Internally used class. */ class RegHolder { Regex me = null; RegHolder prev = null; } /** * Internally used class. * * @see CodeRule */ class CodeVal { int pos; char code; CodeVal(int p, char c) { pos = p; code = c; } public String toString() { return "(" + pos + "," + code + ")"; } } /** * To use this class, first use either the getReplacer() method from Transformer * or Regex. You can then use replaceAll, replaceFirst, etc. methods on the * Replacer in the same way that you can from either of those two classes. *
* The only potential difference between using the methods of Replacer to do the * replacing is that Replacer remembers changes to the replacing object between * calls to replaceAll, replaceFirst etc. For details, see the example file trans3.java. * * @see com.stevesoft.pat.Transformer * @see com.stevesoft.pat.Regex */ public class Replacer { boolean first; /** Instantiate a new Replacer. */ public Replacer() { } public StringLike replaceFirstRegion(String s, Regex r, int start, int end) { return replaceFirstRegion(new StringWrap(s), r, start, end); } /** * This method replaces the first occurence of the Regex in the String * starting with position pos according to the Replacer rule of this object. */ public StringLike replaceFirstRegion(StringLike s, Regex r, int start, int end) { first = true; rh.me = r; rh.prev = null; return dorep(s, start, end); } public StringLike replaceFirst(StringLike s) { return replaceFirstRegion(s, 0, s.length()); } public StringLike replaceFirstFrom(StringLike s, int start) { return replaceFirstRegion(s, start, s.length()); } public StringLike replaceFirstRegion(StringLike s, int start, int end) { first = true; return dorep(s, start, end); } RegHolder rh = new RegHolder(); public StringLike replaceAllRegion(String s, Regex r, int start, int end) { return replaceAllRegion(new StringWrap(s), r, start, end); } /** * This method replaces all occurences of the Regex in the String starting * with postition pos according to the Replacer rule of this object. */ public StringLike replaceAllRegion(StringLike s, Regex r, int start, int end) { first = false; // reset rh.me = r; rh.prev = null; return dorep(s, start, end); } public StringLike replaceAll(StringLike s) { return replaceAllRegion(s, 0, s.length()); } public StringLike replaceAllFrom(StringLike s, int start) { return replaceAllRegion(s, start, s.length()); } public StringLike replaceAllRegion(StringLike s, int start, int end) { first = false; return dorep(s, start, end); } public String replaceAll(String s) { return replaceAllRegion(new StringWrap(s), 0, s.length()).toString(); } public String replaceAllFrom(String s, int start) { return replaceAllRegion(new StringWrap(s), start, s.length()) .toString(); } public String replaceAllRegion(String s, int start, int end) { first = false; return dorep(new StringWrap(s), start, end).toString(); } final public boolean isSpecial(ReplaceRule x) { while (x != null) { if (x instanceof SpecialRule || (x instanceof RuleHolder && ((RuleHolder) x).held instanceof SpecialRule)) { return true; } x = x.next; } return false; } final public void apply1(RegRes rr) { rr.charsMatched_++; apply(rr, null); rr.charsMatched_--; } final StringLike dorep(StringLike s, int start, int end) { StringLike ret = s; want_more_text = false; lastMatchedTo = 0; if (rh.me == null) { throw new NullPointerException("Replacer has null Regex pointer"); } if (rh.me._search(s, start, end)) { int rmn = rh.me.matchedTo(); if (rh.me.charsMatched() == 0 && !isSpecial(rh.me.getReplaceRule())) { apply1(rh.me); rmn++; } apply(rh.me); if (!first) { for (int i = rmn; !want_more_text && rh.me._search(s, i, end); i = rmn) { rmn = rh.me.matchedTo(); if (rh.me.charsMatched() == 0) { if (!isSpecial(rh.me.getReplaceRule())) { apply1(rh.me); } rmn++; } apply(rh.me); } } ret = finish(); ret = ret == null ? s : ret; } return ret; } StringBufferLike sb = null; StringLike src = null; int pos = 0; /** * This method allows you to apply the results of several matches in a * sequence to modify a String of text. Each call in the sequence must operate * on the same piece of text and the matchedFrom() of each RegRes given to * this method must be greater in value than the preceeding RegRes's * matchedTo() value. */ public void apply(RegRes r, ReplaceRule rp) { if (rp == null || (rp.next == null && rp instanceof AmpersandRule)) { return; } if (r.didMatch()) { if (src == null) { src = r.getStringLike(); } if (sb == null) { sb = new StringBufferLike(src.newStringBufferLike()); } int rmf = r.matchedFrom(); for (int ii = pos; ii < rmf; ii++) { sb.append(src.charAt(ii)); } for (ReplaceRule x = rp; x != null; x = x.next) { x.apply(sb, r); if (x instanceof SpecialRule) { if (x instanceof WantMoreTextReplaceRule && want_more_text_enable) { want_more_text = true; } else if (x instanceof PushRule) { RegHolder rh2 = new RegHolder(); rh2.me = ((PushRule) x).NewRule; rh2.prev = rh; rh = rh2; } else if (x instanceof PopRule) { if (rh.prev != null) { rh = rh.prev; } } else if (x instanceof ChangeRule) { rh.me = ((ChangeRule) x).NewRule; } } } if (!want_more_text) { pos = r.matchedTo(); } } } boolean want_more_text = false, want_more_text_enable = false; public boolean WantMoreText() { return want_more_text; } /** * Another form of apply, it is the same as apply(r,r.getReplaceRule()). */ public void apply(Regex r) { apply(r, r.getReplaceRule()); } /** * This finishes the replacement, appending the right() part of the last * RegRes given to substitute(RegRes). After this method is called, the * Replace object is reset to perform another substitution. If no RegRes * objects with a true didMatch are applied, this returns null. */ public StringLike finish() { if (src == null) { return null; } // sb.append(src.substring(pos,src.length())); int s_end = src.length(); for (int ii = pos; ii < s_end; ii++) { sb.append(src.charAt(ii)); } src = null; lastMatchedTo = pos; pos = 0; StringLike retstr = sb.toStringLike(); sb = null; return retstr; } int lastMatchedTo = 0; public Object clone() { Replacer r = new Replacer(); r.first = first; r.src = src; r.sb = sb; r.pos = pos; r.lastMatchedTo = lastMatchedTo; r.want_more_text = want_more_text; r.want_more_text_enable = want_more_text_enable; r.rh.me = rh.me; r.rh.prev = rh.prev; return r; } public int lastMatchedTo() { return lastMatchedTo; } public Regex getRegex() { return rh.me; } public void setSource(StringLike sl) { src = sl; } public void setBuffer(StringBufferLike sbl) { sb = sbl; } public void setPos(int pos) { this.pos = pos; } }