/interpreter/tags/at2-build270707/src/edu/vub/at/objects/natives/NATText.java
Java | 230 lines | 144 code | 33 blank | 53 comment | 10 complexity | a363848d0b36d56ee37f924d5ac81089 MD5 | raw file
1/** 2 * AmbientTalk/2 Project 3 * NATText.java created on 26-jul-2006 at 16:45:43 4 * (c) Programming Technology Lab, 2006 - 2007 5 * Authors: Tom Van Cutsem & Stijn Mostinckx 6 * 7 * Permission is hereby granted, free of charge, to any person 8 * obtaining a copy of this software and associated documentation 9 * files (the "Software"), to deal in the Software without 10 * restriction, including without limitation the rights to use, 11 * copy, modify, merge, publish, distribute, sublicense, and/or 12 * sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following 14 * conditions: 15 * 16 * The above copyright notice and this permission notice shall be 17 * included in all copies or substantial portions of the Software. 18 * 19 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 20 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 21 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 22 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 23 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 24 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 25 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 26 * OTHER DEALINGS IN THE SOFTWARE. 27 */ 28package edu.vub.at.objects.natives; 29 30import edu.vub.at.exceptions.InterpreterException; 31import edu.vub.at.exceptions.XIllegalArgument; 32import edu.vub.at.exceptions.XTypeMismatch; 33import edu.vub.at.objects.ATBoolean; 34import edu.vub.at.objects.ATClosure; 35import edu.vub.at.objects.ATNil; 36import edu.vub.at.objects.ATNumber; 37import edu.vub.at.objects.ATNumeric; 38import edu.vub.at.objects.ATObject; 39import edu.vub.at.objects.ATTable; 40import edu.vub.at.objects.ATText; 41import edu.vub.at.objects.coercion.NativeTypeTags; 42import edu.vub.at.objects.natives.grammar.AGExpression; 43import edu.vub.util.Matcher; 44import edu.vub.util.Pattern; 45import edu.vub.util.PatternSyntaxException; 46 47/* 48import java.util.regex.Matcher; 49import java.util.regex.Pattern; 50import java.util.regex.PatternSyntaxException; 51*/ 52 53/** 54 * The native implementation of an AmbientTalk text string. 55 * A text string is implemented by a Java String. 56 * 57 * @author tvc 58 */ 59public final class NATText extends AGExpression implements ATText { 60 61 public final String javaValue; 62 63 /** 64 * This method currently serves as a hook for text creation. 65 * Currently text objects are not reused, but this might change in the future. 66 */ 67 public static final NATText atValue(String javaString) { 68 return new NATText(javaString); 69 } 70 71 private NATText(String javaString) { 72 javaValue = javaString; 73 } 74 75 public boolean isNativeText() { return true; } 76 public NATText asNativeText() throws XTypeMismatch { return this; } 77 78 public NATText meta_print() throws InterpreterException { 79 return NATText.atValue("\"" + javaValue + "\""); 80 } 81 82 public ATObject meta_clone() throws InterpreterException { 83 return this; 84 } 85 86 public ATTable meta_typeTags() throws InterpreterException { 87 return NATTable.of(NativeTypeTags._TEXT_, NativeTypeTags._ISOLATE_); 88 } 89 90 // comparison and identity operations 91 92 public ATBoolean base__opeql__opeql_(ATObject comparand) throws InterpreterException { 93 return NATBoolean.atValue(this.equals(comparand)); 94 } 95 96 public boolean equals(Object comparand) { 97 return (comparand instanceof NATText) && 98 ((NATText) comparand).javaValue.equals(this.javaValue); 99 } 100 101 public int hashCode() { 102 return javaValue.hashCode(); 103 } 104 105 // base-level interface 106 107 /** 108 * Explodes a text string into a table of constinuent characters 109 */ 110 public ATTable base_explode() throws InterpreterException { 111 ATObject[] chars = new ATObject[javaValue.length()]; 112 char[] rawchars = javaValue.toCharArray(); 113 for (int i = 0; i < chars.length; i++) { 114 chars[i] = NATText.atValue(new Character(rawchars[i]).toString()); 115 } 116 return NATTable.atValue(chars); 117 } 118 119 /** 120 * Split the string according to the given regular expression. 121 * For regular expression syntax, see the Java API. 122 */ 123 public ATTable base_split(ATText regexp) throws InterpreterException { 124 String[] elements = null; 125 try { 126 // Backport from JDK 1.4 to 1.3 127 // elements = javaValue.split(regexp.asNativeText().javaValue); 128 elements = Pattern.compile(regexp.asNativeText().javaValue).split(new StringBuffer(javaValue)); 129 } catch (PatternSyntaxException e) { 130 throw new XIllegalArgument("Illegal argument to split: " + e.getMessage()); 131 } 132 133 ATObject[] tbl = new ATObject[elements.length]; 134 for (int i = 0; i < elements.length; i++) { 135 tbl[i] = NATText.atValue(elements[i]); 136 } 137 return NATTable.atValue(tbl); 138 } 139 140 public ATNil base_find_do_(ATText regexp, ATClosure consumer) throws InterpreterException { 141 Pattern p = null; 142 143 try { 144 p = Pattern.compile(regexp.asNativeText().javaValue); 145 } catch (PatternSyntaxException e) { 146 throw new XIllegalArgument("Illegal argument to find:do: " + e.getMessage()); 147 } 148 149 Matcher m = p.matcher(new StringBuffer(javaValue)); 150 while (m.find()) { 151 consumer.base_apply(NATTable.atValue(new ATObject[] { NATText.atValue(m.group()) })); 152 } 153 return OBJNil._INSTANCE_; 154 } 155 156 public ATText base_replace_by_(ATText regexp, ATClosure transformer) throws InterpreterException { 157 Pattern p = null; 158 159 try { 160 p = Pattern.compile(regexp.asNativeText().javaValue); 161 } catch (PatternSyntaxException e) { 162 throw new XIllegalArgument("Illegal argument to replace:by: " + e.getMessage()); 163 } 164 165 Matcher m = p.matcher(new StringBuffer(javaValue)); 166 StringBuffer sb = new StringBuffer(); 167 while (m.find()) { 168 ATObject replacement = transformer.base_apply(NATTable.atValue(new ATObject[] { NATText.atValue(m.group()) })); 169 m.appendReplacement(sb, replacement.asNativeText().javaValue); 170 } 171 m.appendTail(sb); 172 return NATText.atValue(sb.toString()); 173 } 174 175 public ATText base_toUpperCase() { 176 return NATText.atValue(javaValue.toUpperCase()); 177 } 178 179 public ATText base_toLowerCase() { 180 return NATText.atValue(javaValue.toLowerCase()); 181 } 182 183 public ATNumber base_length() { 184 return NATNumber.atValue(javaValue.length()); 185 } 186 187 public ATText base__oppls_(ATObject other) throws InterpreterException { 188 return NATText.atValue(javaValue + 189 (other.isNativeText() ? other.asNativeText().javaValue : other.meta_print().javaValue)); 190 } 191 192 public ATNumber base__opltx__opeql__opgtx_(ATText other) throws InterpreterException { 193 int cmp = javaValue.compareTo(other.asNativeText().javaValue); 194 if (cmp > 0) 195 return NATNumber.ONE; 196 else if (cmp < 0) 197 return NATNumber.MONE; 198 else 199 return NATNumber.ZERO; 200 } 201 202 public ATBoolean base__optil__opeql_(ATText regexp) throws InterpreterException { 203 try { 204 return NATBoolean.atValue(Pattern.matches(regexp.asNativeText().javaValue, new StringBuffer(javaValue))); 205 } catch (PatternSyntaxException e) { 206 throw new XIllegalArgument("Illegal regular expression for ~=: " + e.getMessage()); 207 } 208 } 209 210 public ATNumeric base_parseNumeric() throws InterpreterException { 211 try { 212 return NATNumber.atValue(Integer.parseInt(javaValue)); 213 } catch(NumberFormatException e) { 214 try { 215 return NATFraction.atValue(Double.parseDouble(javaValue)); 216 } catch(NumberFormatException e2) { 217 throw new XIllegalArgument("Cannot convert "+javaValue+" into a numeric object"); 218 } 219 } 220 } 221 222 public char asChar() throws XTypeMismatch { 223 if (javaValue.length() == 1) { 224 return javaValue.charAt(0); 225 } else { 226 throw new XTypeMismatch(Character.class, this); 227 } 228 } 229 230}