/interpreter/tags/at2dist110511/src/edu/vub/at/objects/natives/NATText.java
Java | 237 lines | 153 code | 31 blank | 53 comment | 13 complexity | 64e6a75d9dc86a78dd739f84b70cf358 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 java.util.HashMap; 31 32import edu.vub.at.eval.Evaluator; 33import edu.vub.at.exceptions.InterpreterException; 34import edu.vub.at.exceptions.XIllegalArgument; 35import edu.vub.at.exceptions.XTypeMismatch; 36import edu.vub.at.objects.ATBoolean; 37import edu.vub.at.objects.ATClosure; 38import edu.vub.at.objects.ATNil; 39import edu.vub.at.objects.ATNumber; 40import edu.vub.at.objects.ATNumeric; 41import edu.vub.at.objects.ATObject; 42import edu.vub.at.objects.ATTable; 43import edu.vub.at.objects.ATText; 44import edu.vub.at.objects.coercion.NativeTypeTags; 45import edu.vub.at.objects.natives.grammar.AGExpression; 46import edu.vub.util.Regexp; 47import edu.vub.util.TempFieldGenerator; 48 49import org.apache.regexp.RE; 50import org.apache.regexp.RESyntaxException; 51 52/* 53import java.util.regex.Matcher; 54import java.util.regex.Pattern; 55import java.util.regex.PatternSyntaxException; 56*/ 57 58/** 59 * The native implementation of an AmbientTalk text string. 60 * A text string is implemented by a Java String. 61 * 62 * @author tvcutsem 63 */ 64public final class NATText extends AGExpression implements ATText { 65 66 /** Text is represented as Java String */ 67 public final String javaValue; 68 69 /** 70 * This method currently serves as a hook for text creation. 71 * Currently text objects are not reused, but this might change in the future. 72 */ 73 public static final NATText atValue(String javaString) { 74 return new NATText(javaString); 75 } 76 77 private NATText(String javaString) { 78 javaValue = javaString; 79 } 80 81 public boolean isNativeText() { return true; } 82 public NATText asNativeText() throws XTypeMismatch { return this; } 83 84 public NATText meta_print() throws InterpreterException { 85 return NATText.atValue("\"" + javaValue + "\""); 86 } 87 88 public NATText impl_asCode(TempFieldGenerator objectMap) throws InterpreterException { 89 return NATText.atValue("\"" + javaValue + "\""); 90 } 91 92 public ATObject meta_clone() throws InterpreterException { 93 return this; 94 } 95 96 public ATTable meta_typeTags() throws InterpreterException { 97 return NATTable.of(NativeTypeTags._TEXT_, NativeTypeTags._ISOLATE_); 98 } 99 100 // comparison and identity operations 101 102 public ATBoolean base__opeql__opeql_(ATObject comparand) throws InterpreterException { 103 if (comparand.isNativeText()) { 104 return NATBoolean.atValue(javaValue.equals(comparand.asNativeText().javaValue)); 105 } else { 106 return NATBoolean._FALSE_; 107 } 108 } 109 110 public int hashCode() { 111 return javaValue.hashCode(); 112 } 113 114 // base-level interface 115 116 /** 117 * Explodes a text string into a table of constinuent characters 118 */ 119 public ATTable base_explode() throws InterpreterException { 120 ATObject[] chars = new ATObject[javaValue.length()]; 121 char[] rawchars = javaValue.toCharArray(); 122 for (int i = 0; i < chars.length; i++) { 123 chars[i] = NATText.atValue(new Character(rawchars[i]).toString()); 124 } 125 return NATTable.atValue(chars); 126 } 127 128 /** 129 * Split the string according to the given regular expression. 130 * For regular expression syntax, see the Apache Regexp API of class {@link RE}. 131 */ 132 public ATTable base_split(ATText regexp) throws InterpreterException { 133 try { 134 String[] elements = new RE(Regexp.compile(regexp.asNativeText().javaValue)).split(javaValue); 135 ATObject[] tbl = new ATObject[elements.length]; 136 for (int i = 0; i < elements.length; i++) { 137 tbl[i] = NATText.atValue(elements[i]); 138 } 139 return NATTable.atValue(tbl); 140 } catch (RESyntaxException e) { 141 throw new XIllegalArgument("Illegal argument to split: " + e.getMessage()); 142 } 143 } 144 145 public ATNil base_find_do_(ATText regexp, final ATClosure consumer) throws InterpreterException { 146 try { 147 RE pattern = new RE(Regexp.compile(regexp.asNativeText().javaValue)); 148 Regexp.findAll(pattern, javaValue, new Regexp.StringRunnable() { 149 public void run(String match) throws InterpreterException { 150 consumer.base_apply(NATTable.atValue(new ATObject[] { NATText.atValue(match) })); 151 } 152 }); 153 return Evaluator.getNil(); 154 } catch (RESyntaxException e) { 155 throw new XIllegalArgument("Illegal argument to find:do: " + e.getMessage()); 156 } 157 } 158 159 public ATText base_replace_by_(ATText regexp, final ATClosure transformer) throws InterpreterException { 160 try { 161 RE pattern = new RE(Regexp.compile(regexp.asNativeText().javaValue)); 162 return NATText.atValue(Regexp.replaceAll(pattern, javaValue, new Regexp.StringCallable() { 163 public String call(String match) throws InterpreterException { 164 ATObject replacement = transformer.base_apply(NATTable.atValue(new ATObject[] { NATText.atValue(match) })); 165 return replacement.asNativeText().javaValue; 166 } 167 })); 168 } catch (RESyntaxException e) { 169 throw new XIllegalArgument("Illegal argument to replace:by: " + e.getMessage()); 170 } 171 } 172 173 public ATText base_toUpperCase() { 174 return NATText.atValue(javaValue.toUpperCase()); 175 } 176 177 public ATText base_toLowerCase() { 178 return NATText.atValue(javaValue.toLowerCase()); 179 } 180 181 public ATNumber base_length() { 182 return NATNumber.atValue(javaValue.length()); 183 } 184 185 public ATText base__oppls_(ATObject other) throws InterpreterException { 186 return NATText.atValue(javaValue + 187 (other.isNativeText() ? other.asNativeText().javaValue : other.meta_print().javaValue)); 188 } 189 190 public ATNumber base__opltx__opeql__opgtx_(ATText other) throws InterpreterException { 191 int cmp = javaValue.compareTo(other.asNativeText().javaValue); 192 if (cmp > 0) 193 return NATNumber.ONE; 194 else if (cmp < 0) 195 return NATNumber.MONE; 196 else 197 return NATNumber.ZERO; 198 } 199 200 public ATBoolean base__optil__opeql_(ATText regexp) throws InterpreterException { 201 try { 202 return NATBoolean.atValue(new RE(Regexp.compile(regexp.asNativeText().javaValue)).match(javaValue)); 203 } catch (RESyntaxException e) { 204 throw new XIllegalArgument("Illegal regular expression for ~=: " + e.getMessage()); 205 } 206 } 207 208 public ATNumeric base_parseNumeric() throws InterpreterException { 209 try { 210 return NATNumber.atValue(Integer.parseInt(javaValue)); 211 } catch(NumberFormatException e) { 212 try { 213 return NATFraction.atValue(Double.parseDouble(javaValue)); 214 } catch(NumberFormatException e2) { 215 throw new XIllegalArgument("Cannot convert "+javaValue+" into a numeric object"); 216 } 217 } 218 } 219 220 public ATNumber base_toNumber() throws InterpreterException { 221 if (javaValue.length() == 1) { 222 return NATNumber.atValue(Character.getNumericValue(javaValue.charAt(0))); 223 } else { 224 throw new XTypeMismatch(Character.class, this); 225 } 226 } 227 228 /** Convert this text into a Java character */ 229 public char asChar() throws XTypeMismatch { 230 if (javaValue.length() == 1) { 231 return javaValue.charAt(0); 232 } else { 233 throw new XTypeMismatch(Character.class, this); 234 } 235 } 236 237}