/interpreter/tags/at2dist041108/src/edu/vub/at/objects/natives/NATText.java

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