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

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