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