PageRenderTime 65ms CodeModel.GetById 21ms RepoModel.GetById 1ms app.codeStats 0ms

/TeXmacs-1.0.7.11-src/src/Style/Evaluate/evaluate_textual.cpp

#
C++ | 229 lines | 193 code | 18 blank | 18 comment | 95 complexity | fb00bff3757a5e2af28f2678a9b0e108 MD5 | raw file
Possible License(s): GPL-3.0, GPL-2.0, MPL-2.0-no-copyleft-exception
  1. /******************************************************************************
  2. * MODULE : evaluate_textual.cpp
  3. * DESCRIPTION: operations on text (strings, tuples and trees)
  4. * COPYRIGHT : (C) 2006 Joris van der Hoeven
  5. *******************************************************************************
  6. * This software falls under the GNU general public license version 3 or later.
  7. * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
  8. * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
  9. ******************************************************************************/
  10. #include "evaluate_main.hpp"
  11. #include "analyze.hpp"
  12. #include "vars.hpp"
  13. #include "language.hpp"
  14. #include "gui.hpp"
  15. #include "file.hpp"
  16. #include "dictionary.hpp"
  17. /******************************************************************************
  18. * Array-like operations on strings and compound structures
  19. ******************************************************************************/
  20. tree
  21. evaluate_merge (tree t) {
  22. int i, n= N(t);
  23. if (n == 0) return "";
  24. tree acc= evaluate (t[0]);
  25. if (is_concat (acc)) acc= tree_as_string (acc);
  26. for (i=1; i<n; i++) {
  27. tree add= evaluate (t[i]);
  28. if (is_atomic (acc) && (is_atomic (add) || is_concat (add)))
  29. acc= acc->label * tree_as_string (add);
  30. else if (is_tuple (acc) && is_tuple (add))
  31. acc= acc * add;
  32. else if (is_func (acc, MACRO) && is_func (add, MACRO) &&
  33. (N(acc) == N(add)) &&
  34. (acc (0, N(acc)-1) == add (0, N(add)-1)))
  35. {
  36. tree r = copy (acc);
  37. tree u1= copy (acc[N(acc)-1]);
  38. tree u2= copy (add[N(add)-1]);
  39. tree u (CONCAT, u1, u2);
  40. if (u1 == "") u= u2;
  41. else if (u2 == "") u= u1;
  42. else if (is_atomic (u1) && is_atomic (u2))
  43. u= u1->label * u2->label;
  44. r[N(r)-1]= u;
  45. acc= r;
  46. }
  47. else return evaluate_error ("bad merge");
  48. }
  49. return acc;
  50. }
  51. tree
  52. evaluate_length (tree t) {
  53. if (N(t)!=1) return evaluate_error ("bad length");
  54. tree t1= evaluate (t[0]);
  55. if (is_compound (t1)) {
  56. if (is_tuple (t1)) return as_string (N (t1));
  57. return evaluate_error ("bad length");
  58. }
  59. return as_string (N (t1->label));
  60. }
  61. tree
  62. evaluate_range (tree t) {
  63. if (N(t)!=3) return evaluate_error ("bad range");
  64. tree t1= evaluate (t[0]);
  65. tree t2= evaluate (t[1]);
  66. tree t3= evaluate (t[2]);
  67. if (!(is_int (t2) && is_int (t3))) return evaluate_error ("bad range");
  68. if (is_compound (t1)) {
  69. if (is_tuple (t1)) {
  70. int i1= max (0, as_int (t2));
  71. int i2= min (N (t1), as_int (t3));
  72. i2 = max (i1, i2);
  73. return t1 (i1, i2);
  74. }
  75. return evaluate_error ("bad range");
  76. }
  77. int i1= max (0, as_int (t2));
  78. int i2= min (N(t1->label), as_int (t3));
  79. i2 = max (i1, i2);
  80. return t1->label (i1, i2);
  81. }
  82. /******************************************************************************
  83. * Routines on strings
  84. ******************************************************************************/
  85. tree
  86. evaluate_number (tree t) {
  87. if (N(t)!=2) return evaluate_error ("bad number");
  88. tree t1= evaluate (t[0]);
  89. tree t2= evaluate (t[1]);
  90. if (is_compound (t1) || is_compound (t2))
  91. return evaluate_error ("bad number");
  92. string s1= t1->label;
  93. string s2= t2->label;
  94. int nr= as_int (s1);
  95. if (s2 == "roman") return roman_nr (nr);
  96. if (s2 == "Roman") return Roman_nr (nr);
  97. if (s2 == "alpha") return alpha_nr (nr);
  98. if (s2 == "Alpha") return Alpha_nr (nr);
  99. if (s2 == "fnsymbol")
  100. return tree (WITH, MODE, "math", tree (RIGID, fnsymbol_nr (nr)));
  101. return evaluate_error ("bad number");
  102. }
  103. tree
  104. evaluate_date (tree t) {
  105. if (N(t)>2) return evaluate_error ("bad date");
  106. string lan= as_string (std_env [LANGUAGE]);
  107. if (N(t) == 2) {
  108. tree u= evaluate (t[1]);
  109. if (is_compound (u)) return evaluate_error ("bad date");
  110. lan= u->label;
  111. }
  112. string fm= "";
  113. if (N(t) != 0) {
  114. tree u= evaluate (t[0]);
  115. if (is_compound (u)) return evaluate_error ("bad date");
  116. fm= u->label;
  117. }
  118. return get_date (lan, fm);
  119. }
  120. tree
  121. evaluate_translate (tree t) {
  122. if (N(t)!=3) return evaluate_error ("bad translate");
  123. tree t1= evaluate (t[0]);
  124. tree t2= evaluate (t[1]);
  125. tree t3= evaluate (t[2]);
  126. if (is_compound (t1) || is_compound (t2) || is_compound (t3))
  127. return evaluate_error ("bad translate");
  128. return translate (t1->label, t2->label, t3->label);
  129. }
  130. tree
  131. evaluate_change_case (tree t, tree nc, bool evaluate_flag, bool first) {
  132. if (is_atomic (t)) {
  133. string s= t->label;
  134. tree r= copy (s);
  135. int i, n= N(s);
  136. bool all= true;
  137. bool up = false;
  138. bool lo = false;
  139. if (nc == "Upcase") { all= false; up= true; }
  140. else if (nc == "UPCASE") { up= true; }
  141. else if (nc == "locase") { lo= true; }
  142. for (i=0; i<n; tm_char_forwards (s, i))
  143. if (is_iso_alpha (s[i]) && (all || (first && (i==0)))) {
  144. if (up && is_locase (s[i])) r->label[i]= upcase (s[i]);
  145. if (lo && is_upcase (s[i])) r->label[i]= locase (s[i]);
  146. }
  147. r->obs= list_observer (ip_observer (obtain_ip (t)), r->obs);
  148. return r;
  149. }
  150. else if (is_concat (t)) {
  151. int i, n= N(t);
  152. tree r (t, n);
  153. for (i=0; i<n; i++)
  154. r[i]= evaluate_change_case (t[i], nc, evaluate_flag, first && (i==0));
  155. r->obs= list_observer (ip_observer (obtain_ip (t)), r->obs);
  156. return r;
  157. }
  158. else {
  159. if (evaluate_flag) return t;
  160. else return evaluate_change_case (evaluate (t), nc, true, first);
  161. }
  162. }
  163. tree
  164. evaluate_change_case (tree t) {
  165. if (N(t) < 2) return evaluate_error ("bad change case");
  166. return evaluate_change_case (t[0], evaluate (t[1]), false, true);
  167. }
  168. tree
  169. evaluate_find_file (tree t) {
  170. int i, n=N(t);
  171. array<tree> r (n);
  172. for (i=0; i<n; i++) {
  173. r[i]= evaluate (t[i]);
  174. if (is_compound (r[i]))
  175. return evaluate_error ("bad find file");
  176. }
  177. for (i=0; i<(n-1); i++) {
  178. url u= resolve (url (r[i]->label, r[n-1]->label));
  179. if (!is_none (u)) {
  180. if (is_rooted (u, "default")) u= reroot (u, "file");
  181. return as_string (u);
  182. }
  183. }
  184. url base_file_name (as_string (std_env["base-file-name"]));
  185. url u= resolve (base_file_name * url_parent () * r[n-1]->label);
  186. if (!is_none (u)) {
  187. if (is_rooted (u, "default")) u= reroot (u, "file");
  188. return as_string (u);
  189. }
  190. return "false";
  191. }
  192. /******************************************************************************
  193. * Routines on tuples
  194. ******************************************************************************/
  195. tree
  196. evaluate_is_tuple (tree t) {
  197. if (N(t)!=1) return evaluate_error ("bad tuple query");
  198. return as_string_bool(is_tuple (evaluate (t[0])));
  199. }
  200. tree
  201. evaluate_lookup (tree t) {
  202. if (N(t)!=2) return evaluate_error ("bad look up");
  203. tree t1= evaluate (t[0]);
  204. tree t2= evaluate (t[1]);
  205. if (!(is_compound (t1) && is_int (t2)))
  206. return evaluate_error ("bad look up");
  207. int i= as_int (t2);
  208. if (i < 0 || i >= N(t1))
  209. return evaluate_error ("index out of range in look up");
  210. return t1[i];
  211. }