Back to index

texmacs  1.0.7.15
tree_analyze.cpp
Go to the documentation of this file.
00001 
00002 /******************************************************************************
00003 * MODULE     : tree_analyze.cpp
00004 * DESCRIPTION: routines for analyzing trees
00005 * COPYRIGHT  : (C) 2010  Joris van der Hoeven
00006 *******************************************************************************
00007 * This software falls under the GNU general public license version 3 or later.
00008 * It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
00009 * in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
00010 ******************************************************************************/
00011 
00012 #include "tree_analyze.hpp"
00013 #include "convert.hpp"
00014 
00015 drd_info get_style_drd (tree style);
00016 
00017 /******************************************************************************
00018 * Tokenize mathematical concats and recomposition
00019 ******************************************************************************/
00020 
00021 array<tree>
00022 concat_tokenize (tree t) {
00023   static language lan= math_language ("std-math");
00024   array<tree> r;
00025   if (is_atomic (t)) {
00026     int i= 0;
00027     while (i<N(t->label)) {
00028       int start= i;
00029       (void) lan->advance (t, i);
00030       r << tree (t->label (start, i));
00031     }
00032   }
00033   else if (is_concat (t))
00034     for (int i=0; i<N(t); i++)
00035       r << concat_tokenize (t[i]);
00036   else if (is_func (t, BIG, 1) && t[0] == "."); // NOTE: discard old <big|.>
00037   else r << t;
00038   return r;
00039 }
00040 
00041 array<tree>
00042 concat_decompose (tree t) {
00043   array<tree> r;
00044   if (t == "");
00045   else if (is_atomic (t)) r << t;
00046   else if (is_concat (t))
00047     for (int i=0; i<N(t); i++)
00048       r << concat_decompose (t[i]);
00049   else r << t;
00050   return r;
00051 }
00052 
00053 tree
00054 concat_recompose (array<tree> a) {
00055   array<tree> r;
00056   string s;
00057   for (int i=0; i<N(a); i++)
00058     if (is_atomic (a[i])) s << a[i]->label;
00059     else {
00060       if (s != "") r << tree (s);
00061       r << a[i];
00062       s= "";
00063     }
00064   if (s != "") r << tree (s);
00065   if (N(r) == 0) return "";
00066   else if (N(r) == 1) return r[0];
00067   else return tree (CONCAT, r);
00068 }
00069 
00070 /******************************************************************************
00071 * Subroutines for WITH-like macros
00072 ******************************************************************************/
00073 
00074 bool
00075 is_with_like (tree t) {
00076   return the_drd->is_with_like (t);
00077 }
00078 
00079 tree&
00080 with_body (tree w) {
00081   return w[N(w)-1];
00082 }
00083 
00084 bool
00085 with_same_type (tree w1, tree w2) {
00086   ASSERT (is_with_like (w1) && is_with_like (w2), "with-like trees expected");
00087   return w1 (0, N(w1)-1) == w2 (0, N(w2)-1);
00088 }
00089 
00090 bool
00091 with_similar_type (tree w1, tree w2) {
00092   ASSERT (is_with_like (w1) && is_with_like (w2), "with-like trees expected");
00093   if (is_compound (w1, "math") || is_compound (w1, "text"))
00094     return is_compound (w2, "math") || is_compound (w2, "text");
00095   if (!is_func (w1, WITH) || !is_func (w2, WITH))
00096     return with_same_type (w1, w2);
00097   if (N(w1) != N(w2)) return false;
00098   for (int i=0; i<N(w1)-1; i+=2)
00099     if (w1[i] != w2[i]) return false;
00100   return true;
00101 }
00102 
00103 array<tree>
00104 with_decompose (tree w, tree t) {
00105   array<tree> r;
00106   if (t == "");
00107   else if (is_atomic (t)) r << t;
00108   else if (is_concat (t))
00109     for (int i=0; i<N(t); i++)
00110       r << with_decompose (w, t[i]);
00111   else if (is_with_like (t) && with_same_type (w, t))
00112     r << with_decompose (w, with_body (t));
00113   else r << t;
00114   return r;
00115 }
00116 
00117 tree
00118 with_recompose (tree w, array<tree> a) {
00119   tree r= w (0, N(w));
00120   with_body (r)= concat_recompose (a);
00121   return r;
00122 }
00123 
00124 /******************************************************************************
00125 * Determine symbol type
00126 ******************************************************************************/
00127 
00128 int
00129 symbol_type (tree t) {
00130   static language lan= math_language ("std-math");
00131   tree r= the_drd->get_syntax (t);
00132   if (r != UNINIT) {
00133     if (is_compound (t, "text")) return SYMBOL_SKIP;
00134     else if (is_compound (t, "eq-number")) return SYMBOL_SKIP;
00135     else if (is_compound (t, "bl")) return SYMBOL_OPEN;
00136     else if (is_compound (t, "br")) return SYMBOL_CLOSE;
00137     else return symbol_type (r);
00138   }
00139   else if (is_atomic (t)) {
00140     int pos= 0;
00141     text_property prop= lan->advance (t, pos);
00142     switch (prop->op_type) {
00143     case OP_UNKNOWN:
00144     case OP_TEXT:
00145     case OP_SKIP:
00146     case OP_SYMBOL:
00147     case OP_UNARY:
00148     case OP_BINARY:
00149     case OP_N_ARY:
00150       return SYMBOL_BASIC;
00151     case OP_PREFIX:
00152       return SYMBOL_PREFIX;
00153     case OP_POSTFIX:
00154       return SYMBOL_POSTFIX;
00155     case OP_INFIX:
00156       return SYMBOL_INFIX;
00157     case OP_SEPARATOR:
00158       return SYMBOL_SEPARATOR;
00159     case OP_OPENING_BRACKET:
00160       return SYMBOL_PROBABLE_OPEN;
00161     case OP_MIDDLE_BRACKET:
00162       return SYMBOL_PROBABLE_MIDDLE;
00163     case OP_CLOSING_BRACKET:
00164       return SYMBOL_PROBABLE_CLOSE;
00165     default:
00166       return SYMBOL_BASIC;
00167     }
00168   }
00169   else switch (L(t)) {
00170     case HSPACE:
00171     case VAR_VSPACE:
00172     case VSPACE:
00173     case SPACE:
00174     case HTAB:
00175       return SYMBOL_SKIP;
00176 
00177     case LEFT:
00178       return SYMBOL_OPEN;
00179     case MID:
00180       return SYMBOL_MIDDLE;
00181     case RIGHT:
00182       return SYMBOL_CLOSE;
00183     case BIG:
00184       if (is_func (t, BIG, 1) && t[0] == ".") return SYMBOL_CLOSE_BIG;
00185       else return SYMBOL_OPEN_BIG;
00186     case LPRIME:
00187     case RPRIME:
00188     case LSUB:
00189     case LSUP:
00190     case RSUB:
00191     case RSUP:
00192       return SYMBOL_SCRIPT;
00193 
00194     case WITH:
00195     case STYLE_WITH:
00196     case VAR_STYLE_WITH:
00197       return symbol_type (t[N(t)-1]);
00198     case LABEL:
00199       return SYMBOL_SKIP;
00200 
00201     default:
00202       return SYMBOL_BASIC;
00203   }
00204 }
00205 
00206 array<int>
00207 symbol_types (array<tree> a) {
00208   array<int> tp (N(a));
00209   for (int i=0; i<N(a); i++)
00210     tp[i]= symbol_type (a[i]);
00211   return tp;
00212 }
00213 
00214 /******************************************************************************
00215 * Determine symbol priority
00216 ******************************************************************************/
00217 
00218 #define PRIORITY_SEPARATOR          0
00219 #define PRIORITY_ASSIGN             1
00220 #define PRIORITY_FLUX               2
00221 #define PRIORITY_MODELS             3
00222 #define PRIORITY_IMPLY              4
00223 #define PRIORITY_OR                 5
00224 #define PRIORITY_AND                6
00225 #define PRIORITY_RELATION           7
00226 #define PRIORITY_ARROW              8
00227 #define PRIORITY_UNION              9
00228 #define PRIORITY_INTERSECTION      10
00229 #define PRIORITY_PLUS              11
00230 #define PRIORITY_TIMES             12
00231 #define PRIORITY_POWER             13
00232 #define PRIORITY_RADICAL           14
00233 
00234 int
00235 symbol_priority (tree t) {
00236   static language lan= math_language ("std-math");
00237   if (is_atomic (t)) {
00238     string g= lan->get_group (t->label);
00239     if (starts (g, "Separator")) return PRIORITY_SEPARATOR;
00240     if (starts (g, "Ponctuation")) return PRIORITY_SEPARATOR;
00241     if (starts (g, "Assign")) return PRIORITY_ASSIGN;
00242     if (starts (g, "Flux")) return PRIORITY_FLUX;
00243     if (starts (g, "Models")) return PRIORITY_MODELS;
00244     if (starts (g, "Imply")) return PRIORITY_IMPLY;
00245     if (starts (g, "Or")) return PRIORITY_OR;
00246     if (starts (g, "And")) return PRIORITY_AND;
00247     if (starts (g, "Relation")) return PRIORITY_RELATION;
00248     if (starts (g, "Arrow")) return PRIORITY_ARROW;
00249     if (starts (g, "Union")) return PRIORITY_UNION;
00250     if (starts (g, "Exclude")) return PRIORITY_UNION;
00251     if (starts (g, "Intersection")) return PRIORITY_INTERSECTION;
00252     if (starts (g, "Plus")) return PRIORITY_PLUS;
00253     if (starts (g, "Minus")) return PRIORITY_PLUS;
00254     if (starts (g, "Times")) return PRIORITY_TIMES;
00255     if (starts (g, "Over")) return PRIORITY_TIMES;
00256     if (starts (g, "Power")) return PRIORITY_POWER;
00257     return PRIORITY_RADICAL;
00258   }
00259   else if (is_func (t, BIG, 1) && is_atomic (t[0])) {
00260     string s= t[0]->label;
00261     if (s == "parallel") return PRIORITY_SEPARATOR;
00262     if (s == "interleave") return PRIORITY_SEPARATOR;
00263     if (s == "vee") return PRIORITY_OR;
00264     if (s == "curlyvee") return PRIORITY_OR;
00265     if (s == "wedge") return PRIORITY_AND;
00266     if (s == "curlywedge") return PRIORITY_AND;
00267     if (s == "cup") return PRIORITY_UNION;
00268     if (s == "sqcup") return PRIORITY_UNION;
00269     if (s == "amalg") return PRIORITY_UNION;
00270     if (s == "uplus") return PRIORITY_UNION;
00271     if (s == "box") return PRIORITY_UNION;
00272     if (s == "cap") return PRIORITY_INTERSECTION;
00273     if (s == "sqcap") return PRIORITY_INTERSECTION;
00274     if (s == "int") return PRIORITY_PLUS;
00275     if (s == "oint") return PRIORITY_PLUS;
00276     if (s == "intlim") return PRIORITY_PLUS;
00277     if (s == "ointlim") return PRIORITY_PLUS;
00278     if (s == "sum") return PRIORITY_PLUS;
00279     if (s == "oplus") return PRIORITY_PLUS;
00280     if (s == "triangledown") return PRIORITY_PLUS;
00281     if (s == "prod") return PRIORITY_TIMES;
00282     if (s == "otimes") return PRIORITY_TIMES;
00283     if (s == "odot") return PRIORITY_TIMES;
00284     if (s == "triangleup") return PRIORITY_TIMES;
00285     return PRIORITY_RADICAL;
00286   }
00287   else return PRIORITY_RADICAL;
00288 }
00289 
00290 array<int>
00291 symbol_priorities (array<tree> a) {
00292   array<int> tp (N(a));
00293   for (int i=0; i<N(a); i++)
00294     tp[i]= symbol_priority (a[i]);
00295   return tp;
00296 }
00297 
00298 /******************************************************************************
00299 * Further routines
00300 ******************************************************************************/
00301 
00302 bool
00303 is_correctable_child (tree t, int i, bool noaround) {
00304   int type= the_drd->get_type_child (t, i);
00305   if (is_compound (t, "body", 1)) return true;
00306   else if (!is_concat (t)) {
00307     switch (type) {
00308     case TYPE_INVALID:
00309     case TYPE_REGULAR:
00310     case TYPE_GRAPHICAL:
00311     case TYPE_ANIMATION:
00312     case TYPE_UNKNOWN:
00313       return true;
00314     default:
00315       return false;
00316     }
00317   }
00318   else if (is_atomic (t[i]) ||
00319           (noaround && is_func (t[i], AROUND)) ||
00320           (noaround && is_func (t[i], VAR_AROUND)) ||
00321           (noaround && is_func (t[i], BIG_AROUND)) ||
00322           is_func (t[i], LEFT) ||
00323           is_func (t[i], MID) ||
00324           is_func (t[i], RIGHT) ||
00325           is_func (t[i], BIG) ||
00326           is_compound (t[i], "bl") ||
00327           is_compound (t[i], "br"))
00328     return false;
00329   else return true;
00330 }