/interpreter/tags/at2-build270707/src/edu/vub/at/objects/natives/NATText.java

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