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.Hashtable;
\r
13 * ReplaceRule is a singly linked list of Objects which describe how to replace
\r
14 * the matched portion of a String. The only member method that you absolutely
\r
15 * need to define to use this class is apply(StringBuffer,RegRes) -- although
\r
16 * you may want define toString1() and clone1() (if you are unhappy with the
\r
17 * default methods) that are needed by the clone() or toString() methods on this
\r
18 * class. During the replacement process, each ReplaceRule tells the replacer
\r
19 * what to add to javajs.util.SB and uses the contents of the Regular expression
\r
20 * result to get the information it needs to do this. Here is an <a
\r
21 * href="http://javaregex.com/code/fancy.java.html">example</a>
\r
23 * @see com.stevesoft.pat.NullRule
\r
24 * @see com.stevesoft.pat.AmpersandRule
\r
25 * @see com.stevesoft.pat.BackRefRule
\r
26 * @see com.stevesoft.pat.LeftRule
\r
27 * @see com.stevesoft.pat.RightRule
\r
28 * @see com.stevesoft.pat.StringRule
\r
30 public abstract class ReplaceRule
\r
32 /** points to the next ReplaceRule in the linked list. */
\r
33 protected ReplaceRule next = null;
\r
36 * This function appends to the StringBufferLike the text you want to replaced
\r
37 * the portion of the String last matched.
\r
39 public abstract void apply(StringBufferLike sb, RegRes r);
\r
42 * A rule describing how to clone only the current ReplaceRule, and none of
\r
43 * the others in this linked list. It is called by clone() for each item in
\r
46 public Object clone1()
\r
48 return new RuleHolder(this);
\r
51 public final Object clone()
\r
53 ReplaceRule x = (ReplaceRule) clone1();
\r
54 ReplaceRule xsav = x;
\r
55 ReplaceRule y = this;
\r
56 while (y.next != null)
\r
58 x.next = (ReplaceRule) y.next.clone1();
\r
66 static ReplaceRule add(ReplaceRule head, ReplaceRule adding)
\r
70 return head = adding;
\r
72 head.addRule(adding);
\r
76 public ReplaceRule add(ReplaceRule adding)
\r
78 return add(this, adding);
\r
81 /** Add another ReplaceRule to the linked list. */
\r
82 public void addRule(ReplaceRule r)
\r
94 static Regex getvar = null;
\r
96 final static Regex getv()
\r
98 // Thanks to Michael Jimenez for pointing out the need
\r
99 // to clone getvar rather than simply returning it.
\r
100 // Previously this was not thread safe.
\r
101 // if(getvar != null) return getvar;
\r
102 if (getvar != null)
\r
104 return (Regex) getvar.clone();
\r
106 getvar = new Regex("(?:\\\\(\\d+)|" + // ref 1
\r
107 "\\$(?:" + "(\\d+)|" + // ref 2
\r
108 "(\\w+)|" + // ref 3
\r
109 "([&'`])|" + // ref 4
\r
110 "\\{(?:(\\d+)|" + // ref 5
\r
111 "([^\n}\\\\]+))}" + // ref 6
\r
112 ")|" + "\\\\([nrbtaef])|" + // ref 7
\r
113 "\\\\c([\u0000-\uFFFF])|" + // ref 8
\r
114 "\\\\x([A-Fa-f0-9]{2})|" + // ref 9
\r
115 "\\\\([\u0000-\uFFFF])" + // ref 10
\r
121 static Hashtable defs = new Hashtable();
\r
123 public static boolean isDefined(String s)
\r
125 return defs.get(s) != null;
\r
128 public static void define(String s, Regex r)
\r
133 public static void define(String s, ReplaceRule r)
\r
139 String name = getClass().getName();
\r
141 public static void define(String s, Transformer t)
\r
146 public static void undefine(String s)
\r
152 * This tells how to convert just the current element (and none of the other
\r
153 * items in the linked list) to a String. This method is called by toString()
\r
154 * for each item in the linked list.
\r
156 public String toString1()
\r
158 return "${" + name + "}";
\r
161 /** Convert to a String. */
\r
162 public final String toString()
\r
164 javajs.util.SB sb = new javajs.util.SB();
\r
165 sb.append(toString1());
\r
166 ReplaceRule rr = this.next;
\r
169 sb.append(rr.toString1());
\r
172 return sb.toString();
\r
176 * Modified the behavior of a ReplaceRule by supplying an argument. If a
\r
177 * ReplaceRule named "foo" is defined and the pattern "s/x/${foo:5}/" is given
\r
178 * to Regex.perlCode, then the "foo" the definition of "foo" will be retrieved
\r
179 * and arg("5") will be called. If the result is non-null, that is the
\r
180 * ReplaceRule that will be used. If the result is null, then the pattern
\r
181 * works just as if it were "s/x/${foo}/".
\r
183 * @see com.stevesoft.pat.Validator#arg(java.lang.String)
\r
185 public ReplaceRule arg(String s)
\r
190 static int getHexDigit(char c)
\r
192 if (c >= '0' && c <= '9')
\r
196 if (c >= 'a' && c <= 'f')
\r
198 return c - 'a' + 10;
\r
200 return c - 'A' + 10;
\r