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