basix_doc 0.1
|
00001 00002 /****************************************************************************** 00003 * MODULE : mmx_printer.cpp 00004 * DESCRIPTION: Printing as mathemagix expressions 00005 * COPYRIGHT : (C) 2000 Joris van der Hoeven 00006 ******************************************************************************* 00007 * This software falls under the GNU general public license and comes WITHOUT 00008 * ANY WARRANTY WHATSOEVER. See the file $TEXMACS_PATH/LICENSE for more details. 00009 * If you don't have this file, write to the Free Software Foundation, Inc., 00010 * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 00011 ******************************************************************************/ 00012 00013 #include <basix/list.hpp> 00014 #include <basix/literal.hpp> 00015 #include <basix/compound.hpp> 00016 #include <basix/mmx_syntax.hpp> 00017 #include <basix/math_syntax.hpp> 00018 namespace mmx { 00019 00020 #define DATA_BEGIN ((char) 2) 00021 #define DATA_END ((char) 5) 00022 00023 bool mmx_abbreviate_coerce= true; 00024 00025 /****************************************************************************** 00026 * The mmx_printer class 00027 ******************************************************************************/ 00028 00029 class mmx_printer { 00030 MMX_ALLOCATORS 00031 private: 00032 list<generic> gl; 00033 00034 private: 00035 generic pp_verb (const string& s); 00036 generic pp_spc (); 00037 generic pp_lf (); 00038 generic pp_sep (bool large); 00039 00040 generic pp_C0 (const generic& g, bool large= false); 00041 generic pp_Conds (const generic& conds); 00042 00043 generic pp_where (const generic& g); 00044 generic pp_E0s (const generic& g, nat start); 00045 00046 generic pp_E1 (const generic& g); 00047 generic pp_E2 (const generic& g); 00048 generic pp_Lflux (const generic& g); 00049 generic pp_Rflux (const generic& g); 00050 00051 generic pp_F0 (const generic& g); 00052 generic pp_Seqors (const generic& g); 00053 generic pp_Ors (const generic& g); 00054 generic pp_Xors (const generic& g); 00055 generic pp_F1 (const generic& g); 00056 generic pp_Seqands (const generic& g); 00057 generic pp_Ands (const generic& g); 00058 generic pp_F2 (const generic& g); 00059 generic pp_F3 (const generic& g); 00060 00061 generic pp_T0 (const generic& g); 00062 generic pp_T1 (const generic& g); 00063 generic pp_T2 (const generic& g); 00064 generic pp_T3 (const generic& g); 00065 generic pp_T4 (const generic& g); 00066 generic pp_T5 (const generic& g); 00067 00068 generic pp_R0 (const generic& g); 00069 generic pp_R1 (const generic& g); 00070 generic pp_R2 (const generic& g); 00071 generic pp_R3 (const generic& g); 00072 00073 public: 00074 inline mmx_printer () {} 00075 inline ~mmx_printer () {} 00076 00077 generic pp_E0 (const generic& g); 00078 friend generic print_mmx (const generic& g); 00079 }; 00080 00081 /****************************************************************************** 00082 * Printing to strings 00083 ******************************************************************************/ 00084 00085 enum print_controls { LF, INDENT, VARINDENT, UNINDENT }; 00086 00087 static nat indentation_level= 0; 00088 00089 static string& 00090 operator << (string& out, print_controls pc) { 00091 switch (pc) { 00092 case LF: 00093 out << "\n"; 00094 for (nat i=0; i<indentation_level; i++) out << " "; 00095 break; 00096 case INDENT: 00097 indentation_level++; 00098 out << " "; 00099 break; 00100 case VARINDENT: 00101 indentation_level++; 00102 break; 00103 case UNINDENT: 00104 indentation_level--; 00105 if (N(out) >= 2 && out[N(out)-2] == ' ' && out[N(out)-1] == ' ') 00106 inside (out) -> resize (N(out) - 2); 00107 break; 00108 } 00109 return out; 00110 } 00111 00112 /****************************************************************************** 00113 * Concatenation 00114 ******************************************************************************/ 00115 00116 inline generic concat (const vector<generic>& v) { 00117 return gen ("$concat", v); } 00118 inline generic concat () { 00119 return gen ("$concat"); } 00120 inline generic concat (const generic& g1, const generic& g2) { 00121 return gen ("$concat", g1, g2); } 00122 inline generic concat (const generic& g1, const generic& g2, 00123 const generic& g3) { 00124 return gen ("$concat", g1, g2, g3); } 00125 inline generic concat (const generic& g1, const generic& g2, 00126 const generic& g3, const generic& g4) { 00127 return gen ("$concat", g1, g2, g3, g4); } 00128 00129 inline generic infix (const generic& g, const generic& op, const generic& h) { 00130 return gen ("$infix", g, op, h); } 00131 inline generic bigop (const generic& op, const vector<generic>& v) { 00132 return gen ("$bigop", cons (op, v)); } 00133 inline generic bracket (const generic& l, const generic& g, const generic& r) { 00134 return gen ("$bracket", l, g, r); } 00135 inline generic postfix (const generic& g, const generic& op) { 00136 return gen ("$postfix", g, op); } 00137 inline generic prefix (const generic& op, const generic& g) { 00138 return gen ("$prefix", op, g); } 00139 inline generic operate (const generic& g, const generic& h) { 00140 return gen ("$operate", g, h); } 00141 inline generic keyword (const generic& g) { 00142 return gen ("$keyword", g); } 00143 inline generic keyword (const generic& op, const generic& g) { 00144 return gen ("$keyword", op, g); } 00145 inline generic hlist (const vector<generic>& v) { 00146 return gen ("$hlist", v); } 00147 inline generic vlist (const vector<generic>& v) { 00148 return gen ("$vlist", v); } 00149 inline generic indented (const vector<generic>& v) { 00150 return gen ("$indent", v); } 00151 00152 static inline void 00153 init (table<generic,generic>& t, const generic& key, const generic& val) { 00154 t[key]= val; 00155 } 00156 00157 static table<generic,generic> 00158 mmx_symbol_table () { 00159 table<generic,generic> t; 00160 init (t, "mathcatalan", "K"); 00161 init (t, "partial", "d"); 00162 init (t, "derivative", "D"); 00163 init (t, "matheuler", "gamma"); 00164 init (t, "mathd", "d"); 00165 init (t, "mathe", "e"); 00166 init (t, "mathi", "i"); 00167 init (t, "mathpi", "pi"); 00168 return t; 00169 } 00170 00171 static void 00172 serialize (string& s, const generic& g) { 00173 if (is<literal> (g)) { 00174 static table<generic,generic> t= mmx_symbol_table (); 00175 if (contains (t, g)) s << literal_to_string (t[g]); 00176 else if (g == "$spc") s << " "; 00177 else if (g == "$lf") s << LF; 00178 else if (g == "$cr"); 00179 else s << literal_to_string (g); 00180 } 00181 else if (is_func (g, "$concat") || 00182 is_func (g, "$bracket") || 00183 is_func (g, "$prefix") || 00184 is_func (g, "$postfix")) 00185 for (nat i=1; i<N(g); i++) 00186 serialize (s, g[i]); 00187 else if (is_func (g, "$infix", 3)) { 00188 serialize (s, g[1]); 00189 if (g[2] != "^" && g[2] != "^^") s << " "; 00190 serialize (s, g[2]); 00191 if (g[2] != "^" && g[2] != "^^") s << " "; 00192 serialize (s, g[3]); 00193 } 00194 else if (is_func (g, "$bigop") && N(g) >= 3) { 00195 if (g[1] == GEN_PLUS && is_func (g[2], GEN_MINUS, 1)) { 00196 s << "-"; 00197 serialize (s, g[2][1]); 00198 } 00199 else serialize (s, g[2]); 00200 for (nat i=3; i<N(g); i++) { 00201 if (g[1] == GEN_PLUS && is_func (g[i], GEN_MINUS, 1)) { 00202 s << " " << "-" << " "; 00203 serialize (s, g[i][1]); 00204 } 00205 else { 00206 s << " "; 00207 serialize (s, g[1]); 00208 s << " "; 00209 serialize (s, g[i]); 00210 } 00211 } 00212 } 00213 else if (is_func (g, "$keyword", 1)) 00214 serialize (s, g[1]); 00215 else if (is_func (g, "$operate", 2) || 00216 is_func (g, "$keyword", 2)) { 00217 serialize (s, g[1]); 00218 s << " "; 00219 serialize (s, g[2]); 00220 } 00221 else if (is_func (g, "$hlist") || 00222 is_func (g, "$vlist")) { 00223 if (N(g) == 1) return; 00224 serialize (s, g[1]); 00225 for (nat i=2; i<N(g); i++) { 00226 if (g[0] == "$hlist") s << ", "; 00227 else s << "; "; 00228 serialize (s, g[i]); 00229 } 00230 } 00231 else if (is_func (g, "$indent")) { 00232 s << INDENT; 00233 for (nat i=1; i<N(g); i++) 00234 serialize (s, g[i]); 00235 s << UNINDENT; 00236 } 00237 else if (is_func (g, "$varindent")) { 00238 serialize (s, g[1]); 00239 s << VARINDENT; 00240 for (nat i=2; i<N(g); i++) 00241 serialize (s, g[i]); 00242 s << UNINDENT; 00243 } 00244 else if (is_func (g, "$text", 1)) 00245 serialize (s, g[1]); 00246 else if (is_func (g, "$math", 1)) 00247 serialize (s, g[1]); 00248 else if (is_func (g, "$dynamic", 2)) { 00249 s << "< "; 00250 serialize (s, g[1]); 00251 s << " | "; 00252 serialize (s, g[2]); 00253 s << " >"; 00254 } 00255 else if (is<compound> (g) && is<literal> (g[0]) && 00256 starts (as_string (as<literal> (g[0])), "tm$")) { 00257 generic h= texmacs_expand (g); 00258 serialize (s, h); 00259 } 00260 else { 00261 serialize (s, g[0]); 00262 s << " ("; 00263 for (nat i=1; i<N(g); i++) { 00264 if (i != 1) s << ", "; 00265 serialize (s, g[i]); 00266 } 00267 s << ")"; 00268 } 00269 } 00270 00271 static string 00272 serialize (const generic& g) { 00273 string s; 00274 serialize (s, g); 00275 return s; 00276 } 00277 00278 /****************************************************************************** 00279 * Helper routines 00280 ******************************************************************************/ 00281 00282 generic 00283 mmx_printer::pp_verb (const string& s) { 00284 return generic (s); 00285 } 00286 00287 generic 00288 mmx_printer::pp_spc () { 00289 return generic ("$spc"); 00290 } 00291 00292 generic 00293 mmx_printer::pp_lf () { 00294 return generic ("$lf"); 00295 } 00296 00297 generic 00298 mmx_printer::pp_sep (bool large) { 00299 if (large) return concat (pp_verb (";"), pp_lf ()); 00300 else return concat (); 00301 } 00302 00303 /****************************************************************************** 00304 * Predicates 00305 ******************************************************************************/ 00306 00307 static bool 00308 is_C0 (const generic& g) { 00309 if (is_func (g, GEN_BEGIN) || 00310 is_func (g, GEN_IF) || 00311 is_func (g, GEN_LOOP) || 00312 is_func (g, GEN_BREAK) || 00313 is_func (g, GEN_CONTINUE) || 00314 is_func (g, GEN_TRY) || 00315 is_func (g, GEN_LAMBDA) || 00316 is_func (g, GEN_MACRO) || 00317 is_func (g, GEN_RETURN) || 00318 is_func (g, GEN_CLASS) || 00319 is_func (g, GEN_MODULE) || 00320 is_func (g, GEN_CATEGORY)) 00321 return true; 00322 if (N(g) == 2 && is_C0 (g[1])) 00323 return 00324 is_func (g, GEN_INTERN) || 00325 is_func (g, GEN_METHOD) || 00326 is_func (g, GEN_EXTERN) || 00327 is_func (g, GEN_MUTABLE) || 00328 is_func (g, GEN_CONSTANT) || 00329 is_func (g, GEN_PUBLIC) || 00330 is_func (g, GEN_PRIVATE); 00331 if (N(g) == 3 && is_C0 (g[2])) 00332 return 00333 is_func (g, GEN_FORALL) || 00334 is_func (g, GEN_EXISTS) || 00335 is_func (g, GEN_ASSUME) || 00336 is_func (g, GEN_PENALTY) || 00337 is_func (g, GEN_DEFINE) || 00338 is_func (g, GEN_ASSIGN) || 00339 is_func (g, GEN_DEFINE_MACRO) || 00340 is_func (g, GEN_ASSIGN_MACRO) || 00341 is_func (g, GEN_PLUS_ASSIGN) || 00342 is_func (g, GEN_MINUS_ASSIGN) || 00343 is_func (g, GEN_TIMES_ASSIGN) || 00344 is_func (g, GEN_OVER_ASSIGN) || 00345 is_func (g, GEN_LESSLESSEQ) || 00346 is_func (g, GEN_GTRGTREQ); 00347 if (N(g) == 4 && is_C0 (g[3])) 00348 return 00349 is_func (g, GEN_FOREIGN); 00350 return false; 00351 } 00352 00353 static bool 00354 is_applicable (const generic& g) { 00355 if (is<literal> (g)) { 00356 const string s= literal_to_string (g); 00357 if (N(s)==0) return false; 00358 for (nat i=0; i<N(s); i++) 00359 if (s[i] == '.') { 00360 if (i != 0 || N(s) == 1) return false; } 00361 else if (((s[i]<'0') || (s[i]>'9')) && 00362 ((s[i]<'a') || (s[i]>'z')) && 00363 ((s[i]<'A') || (s[i]>'Z')) && 00364 ((s[i]!='_') && (s[i]!='?') && (s[i]!='$'))) 00365 return false; 00366 else if (s[i] == '$') return true; 00367 } 00368 return 00369 g != GEN_SEQAND && g != GEN_SEQOR && g != GEN_XOR && 00370 g != GEN_LAMBDA && g != GEN_MACRO && 00371 g != GEN_COERCE && g != GEN_COERCE_TYPE; 00372 } 00373 00374 /****************************************************************************** 00375 * Commands 00376 ******************************************************************************/ 00377 00378 static generic 00379 un_try_catch (const generic& g) { 00380 vector<generic> v; 00381 if (is_func (g[1], GEN_BEGIN)) v << cdr (compound_to_vector (g[1])); 00382 else v << g[1]; 00383 for (nat i=2; i<N(g); i++) v << g[i]; 00384 return gen (g[0], gen (GEN_BEGIN, v)); 00385 } 00386 00387 generic 00388 mmx_printer::pp_C0 (const generic& g, bool large) { 00389 if (is_func (g, GEN_BEGIN)) { 00390 if (N(g) == 1) return concat (pp_verb ("{"), pp_verb ("}")); 00391 vector<generic> v, w; 00392 v << pp_verb ("{") << pp_lf (); 00393 for (nat i=1; i<N(g); i++) 00394 w << pp_C0 (g[i], true); 00395 v << indented (w); 00396 v << pp_verb ("}"); 00397 if (large) v << pp_lf (); 00398 return concat (v); 00399 } 00400 else if (is_func (g, GEN_IF, 2)) { 00401 generic t= g[2]; 00402 if (is_func (g[2], GEN_IF)) t= gen (GEN_BEGIN, g[2]); 00403 return concat (keyword ("if", pp_E0 (g[1])), 00404 pp_spc (), 00405 keyword ("then", pp_C0 (t, large))); 00406 } 00407 else if (is_func (g, GEN_IF, 3)) { 00408 generic t= g[2]; 00409 if (is_func (g[2], GEN_IF)) t= gen (GEN_BEGIN, g[2]); 00410 bool large2= is_C0 (t); 00411 return concat (vec (keyword ("if", pp_E0 (g[1])), 00412 pp_spc (), 00413 keyword ("then", pp_C0 (t, large2)), 00414 large2? concat (): pp_spc (), 00415 keyword ("else", pp_C0 (g[3], large)))); 00416 } 00417 else if (is_func (g, GEN_LOOP)) 00418 return concat (pp_Conds (g), keyword ("loop", pp_C0 (g[N(g)-1], large))); 00419 else if (is_func (g, GEN_TRY)) 00420 return keyword ("try", pp_C0 (un_try_catch (g) [1], large)); 00421 else if (is_func (g, GEN_DEFINE, 2) && is_func (g[1], GEN_CATCH)) 00422 return concat (pp_F0 (g[1]), pp_spc (), pp_C0 (g[2], large)); 00423 else if (is_func (g, GEN_RETURN, 1)) 00424 return keyword ("return", pp_C0 (g[1], large)); 00425 else if (g == GEN_RETURN) 00426 return concat (keyword ("return"), pp_sep (large)); 00427 else if (g == GEN_BREAK) 00428 return concat (keyword ("break"), pp_sep (large)); 00429 else if (g == GEN_CONTINUE) 00430 return concat (keyword ("continue"), pp_sep (large)); 00431 else if (is_func (g, GEN_INTERN, 1) || 00432 is_func (g, GEN_METHOD, 1) || 00433 is_func (g, GEN_EXTERN, 1) || 00434 is_func (g, GEN_CONSTANT, 1) || 00435 is_func (g, GEN_MUTABLE, 1) || 00436 is_func (g, GEN_PUBLIC, 1) || 00437 is_func (g, GEN_PRIVATE, 1)) 00438 return keyword (g[0], pp_C0 (g[1], large)); 00439 else if (is_func (g, GEN_FOREIGN, 3)) 00440 return keyword (g[0], keyword (g[1], keyword (g[2], pp_C0 (g[3], large)))); 00441 else if (is_func (g, GEN_FORALL, 2) || 00442 is_func (g, GEN_EXISTS, 2) || 00443 is_func (g, GEN_ASSUME, 2) || 00444 is_func (g, GEN_PENALTY, 2)) 00445 return operate (keyword (g[0], bracket ("(", pp_E0 (g[1]), ")")), 00446 pp_C0 (g[2], large)); 00447 else if (is_func (g, GEN_CLASS, 1) || 00448 is_func (g, GEN_MODULE, 1) || 00449 is_func (g, GEN_CATEGORY, 1)) 00450 return concat (keyword (g[0], pp_F0 (g[1])), pp_sep (large)); 00451 else if (is_func (g, GEN_CLASS, 2) || 00452 is_func (g, GEN_MODULE, 2) || 00453 is_func (g, GEN_CATEGORY, 2)) 00454 return keyword (g[0], infix (pp_F0 (g[1]), "==", pp_C0 (g[2], large))); 00455 else if (is_func (g, GEN_DEFINE, 2) || 00456 is_func (g, GEN_ASSIGN, 2) || 00457 is_func (g, GEN_DEFINE_MACRO, 2) || 00458 is_func (g, GEN_ASSIGN_MACRO, 2) || 00459 is_func (g, GEN_PLUS_ASSIGN, 2) || 00460 is_func (g, GEN_MINUS_ASSIGN, 2) || 00461 is_func (g, GEN_TIMES_ASSIGN, 2) || 00462 is_func (g, GEN_OVER_ASSIGN, 2) || 00463 is_func (g, GEN_LESSLESSEQ, 2) || 00464 is_func (g, GEN_GTRGTREQ, 2)) 00465 return infix (pp_F0 (g[1]), g[0], pp_C0 (g[2], large)); 00466 else if (is_func (g, GEN_LAMBDA) || is_func (g, GEN_MACRO)) { 00467 if (new_lambda_style) { 00468 vector<generic> v= compound_to_vector (g); 00469 generic t= gen (GEN_TUPLE, range (v, 1, N(v) - 1)); 00470 generic b= g[N(g)-1]; 00471 if (is_func (b, GEN_TYPE, 2)) { t= gen (GEN_TYPE, t, b[2]); b= b[1]; } 00472 return concat (keyword (g[0], pp_E0 (t)), 00473 pp_spc (), 00474 keyword ("do", pp_C0 (b, large))); 00475 } 00476 else { 00477 generic a= pp_E0 (g[1]); 00478 if (N(g) == 4) a= infix (a, ":", pp_E0 (g[3])); 00479 return concat (keyword (g[0], a), 00480 pp_spc (), 00481 keyword ("do", pp_C0 (g[2], large))); 00482 } 00483 } 00484 else return concat (pp_E1 (g), pp_sep (large)); 00485 } 00486 00487 /****************************************************************************** 00488 * Special programming constructs 00489 ******************************************************************************/ 00490 00491 generic 00492 mmx_printer::pp_Conds (const generic& conds) { 00493 vector<generic> v; 00494 for (nat i=1; i<N(conds)-1; i++) { 00495 generic g= conds[i]; 00496 if (is_func (g, GEN_FOR, 1) || 00497 is_func (g, GEN_WHILE, 1) || 00498 is_func (g, GEN_UNTIL, 1) || 00499 is_func (g, GEN_STEP, 1)) 00500 v << keyword (g[0], pp_E0 (g[1])) << pp_spc (); 00501 } 00502 return concat (v); 00503 } 00504 00505 /****************************************************************************** 00506 * Tuples 00507 ******************************************************************************/ 00508 00509 generic 00510 mmx_printer::pp_where (const generic& g) { 00511 return infix (pp_E0 (g[1]), g[0], pp_E0s (g, 2)); 00512 } 00513 00514 generic 00515 mmx_printer::pp_E0s (const generic& g, nat start) { 00516 nat n= N (g); 00517 if (start >= n) return concat (); 00518 else if (is_func (g[start], GEN_WHERE) && start==n-1) 00519 return pp_where (g[start]); 00520 else if (is_func (g[start], GEN_VWHERE) && start==n-1) 00521 return pp_where (g[start]); 00522 else { 00523 bool vertical= false; 00524 for (nat i=start; i<n; i++) 00525 vertical= vertical || is_func (g[i], GEN_ROW); 00526 vector<generic> v; 00527 for (nat i=start; i<n; i++) 00528 v << pp_E0 (g[i]); 00529 if (vertical) return vlist (v); 00530 else return hlist (v); 00531 } 00532 } 00533 00534 /****************************************************************************** 00535 * Expressions 00536 ******************************************************************************/ 00537 00538 generic 00539 mmx_printer::pp_E0 (const generic& g) { 00540 if (is_func (g, GEN_FORALL, 2) || 00541 is_func (g, GEN_EXISTS, 2) || 00542 is_func (g, GEN_ASSUME, 2) || 00543 is_func (g, GEN_PENALTY, 2)) 00544 return operate (keyword (g[0], bracket ("(", pp_E0 (g[1]), ")")), 00545 pp_E0 (g[2])); 00546 else if (is_func (g, GEN_DEFINE, 2) || 00547 is_func (g, GEN_ASSIGN, 2) || 00548 is_func (g, GEN_DEFINE_MACRO, 2) || 00549 is_func (g, GEN_ASSIGN_MACRO, 2) || 00550 is_func (g, GEN_PLUS_ASSIGN, 2) || 00551 is_func (g, GEN_MINUS_ASSIGN, 2) || 00552 is_func (g, GEN_TIMES_ASSIGN, 2) || 00553 is_func (g, GEN_OVER_ASSIGN, 2) || 00554 is_func (g, GEN_LESSLESSEQ, 2) || 00555 is_func (g, GEN_GTRGTREQ, 2)) 00556 return infix (pp_F0 (g[1]), g[0], pp_E0 (g[2])); 00557 else return pp_E1 (g); 00558 } 00559 00560 generic 00561 mmx_printer::pp_E1 (const generic& g) { 00562 if (is_func (g, GEN_LAMBDA) || is_func (g, GEN_MACRO)) { 00563 if (new_lambda_style) { 00564 vector<generic> v= compound_to_vector (g); 00565 generic t= gen (GEN_TUPLE, range (v, 1, N(v) - 1)); 00566 generic b= g[N(g)-1]; 00567 if (is_func (b, GEN_TYPE, 2)) { t= gen (GEN_TYPE, t, b[2]); b= b[1]; } 00568 generic d= (is_C0 (b)? pp_C0 (b): pp_E0 (b)); 00569 return concat (keyword (g[0], pp_E0 (t)), pp_spc (), keyword ("do", d)); 00570 } 00571 else { 00572 generic a= pp_E0 (g[1]); 00573 if (N(g) == 4) a= infix (a, ":", pp_E0 (g[3])); 00574 generic b= (is_C0 (g[2])? pp_C0 (g[2]): pp_E0 (g[2])); 00575 return concat (keyword (g[0], a), pp_spc (), keyword ("do", b)); 00576 } 00577 } 00578 else if (is_func (g, GEN_MAPSTO, 2)) 00579 return infix (pp_E2 (g[1]), g[0], pp_E2 (g[2])); 00580 else return pp_E2 (g); 00581 } 00582 00583 generic 00584 mmx_printer::pp_E2 (const generic& g) { 00585 if (is_func (g, GEN_LESSLESS, 2)) 00586 return infix (pp_Lflux (g[1]), g[0], pp_F0 (g[2])); 00587 else if (is_func (g, GEN_GTRGTR, 2)) 00588 return infix (pp_F0 (g[1]), g[0], pp_Rflux (g[2])); 00589 else return pp_F0 (g); 00590 } 00591 00592 generic 00593 mmx_printer::pp_Lflux (const generic& g) { 00594 if (is_func (g, GEN_LESSLESS, 2)) 00595 return infix (pp_Lflux (g[1]), g[0], pp_F0 (g[2])); 00596 else return pp_F0 (g); 00597 } 00598 00599 generic 00600 mmx_printer::pp_Rflux (const generic& g) { 00601 if (is_func (g, GEN_GTRGTR, 2)) 00602 return infix (pp_F0 (g[1]), g[0], pp_Rflux (g[2])); 00603 else return pp_F0 (g); 00604 } 00605 00606 /****************************************************************************** 00607 * Formulas 00608 ******************************************************************************/ 00609 00610 generic 00611 mmx_printer::pp_F0 (const generic& g) { 00612 if (is_func (g, GEN_IMPLIES, 2) || 00613 is_func (g, GEN_EQUIV, 2)) 00614 return infix (pp_F1 (g[1]), g[0], pp_F1 (g[2])); 00615 else return pp_F1 (g); 00616 } 00617 00618 generic 00619 mmx_printer::pp_F1 (const generic& g) { 00620 if (is_func (g, GEN_SEQOR, 2)) 00621 return infix (pp_Seqors (g[1]), g[0], pp_Seqors (g[2])); 00622 else if (is_func (g, GEN_OR, 2)) 00623 return infix (pp_Ors (g[1]), g[0], pp_Ors (g[2])); 00624 else if (is_func (g, GEN_XOR, 2)) 00625 return infix (pp_Xors (g[1]), g[0], pp_Xors (g[2])); 00626 else return pp_F2 (g); 00627 } 00628 00629 generic 00630 mmx_printer::pp_Seqors (const generic& g) { 00631 if (is_func (g, GEN_SEQOR, 2)) 00632 return infix (pp_Seqors (g[1]), g[0], pp_Seqors (g[2])); 00633 else return pp_F2 (g); 00634 } 00635 00636 generic 00637 mmx_printer::pp_Ors (const generic& g) { 00638 if (is_func (g, GEN_OR, 2)) 00639 return infix (pp_Ors (g[1]), g[0], pp_Ors (g[2])); 00640 else return pp_F2 (g); 00641 } 00642 00643 generic 00644 mmx_printer::pp_Xors (const generic& g) { 00645 if (is_func (g, GEN_XOR, 2)) 00646 return infix (pp_Xors (g[1]), g[0], pp_Xors (g[2])); 00647 else return pp_F2 (g); 00648 } 00649 00650 generic 00651 mmx_printer::pp_F2 (const generic& g) { 00652 if (is_func (g, GEN_AND, 2)) 00653 return infix (pp_Ands (g[1]), g[0], pp_Ands (g[2])); 00654 else if (is_func (g, GEN_SEQAND, 2)) 00655 return infix (pp_Seqands (g[1]), g[0], pp_Seqands (g[2])); 00656 else return pp_F3 (g); 00657 } 00658 00659 generic 00660 mmx_printer::pp_Seqands (const generic& g) { 00661 if (is_func (g, GEN_SEQAND, 2)) 00662 return infix (pp_Seqands (g[1]), g[0], pp_Seqands (g[2])); 00663 else return pp_F3 (g); 00664 } 00665 00666 generic 00667 mmx_printer::pp_Ands (const generic& g) { 00668 if (is_func (g, GEN_AND, 2) || is_func (g, GEN_SEQAND, 2)) 00669 return infix (pp_Ands (g[1]), g[0], pp_Ands (g[2])); 00670 else return pp_F3 (g); 00671 } 00672 00673 generic 00674 mmx_printer::pp_F3 (const generic& g) { 00675 if (is_func (g, GEN_EQUAL, 2) || 00676 is_func (g, GEN_UNEQUAL, 2) || 00677 is_func (g, GEN_LESS, 2) || 00678 is_func (g, GEN_LESSEQ, 2) || 00679 is_func (g, GEN_GTR, 2) || 00680 is_func (g, GEN_GTREQ, 2)) 00681 return infix (pp_T0 (g[1]), g[0], pp_T0 (g[2])); 00682 else if (is_func (g, GEN_TYPE, 2)) 00683 return infix (pp_T0 (g[1]), g[0], pp_T0 (g[2])); 00684 else if (is_func (g, GEN_IN, 2) && is_func (g[1], GEN_TYPE, 2)) 00685 return infix (pp_F3 (g[1]), g[0], pp_T0 (g[2])); 00686 else if (is_func (g, GEN_IN, 2)) 00687 return infix (pp_T0 (g[1]), g[0], pp_T0 (g[2])); 00688 else return pp_T0 (g); 00689 } 00690 00691 /****************************************************************************** 00692 * Terms 00693 ******************************************************************************/ 00694 00695 generic 00696 mmx_printer::pp_T0 (const generic& g) { 00697 if (is_func (g, GEN_TRANSTYPE, 2) || 00698 is_func (g, GEN_CONVERTS, 2)) 00699 return infix (pp_T0 (g[1]), g[0], pp_T1 (g[2])); 00700 else if ((is_func (g, GEN_COERCE, 2) || 00701 (is_func (g, GEN_COERCE_TYPE) && N(g) > 2)) && 00702 mmx_abbreviate_coerce) { 00703 // FIXME: this temporary hack avoids us to print huge type names 00704 generic op= GEN_TRANSTYPE; 00705 if (is_func (g, GEN_COERCE_TYPE)) op= "::>"; 00706 if (is_func (g, GEN_COERCE_TYPE, 3)) op= ":+>"; 00707 return infix (pp_T0 (g[1]), op, pp_T1 (g[2])); 00708 } 00709 else return pp_T1 (g); 00710 } 00711 00712 generic 00713 mmx_printer::pp_T1 (const generic& g) { 00714 if (is_func (g, GEN_INTO, 2) || 00715 is_func (g, GEN_MAPSTO, 2)) 00716 return infix (pp_T2 (g[1]), g[0], pp_T2 (g[2])); 00717 else return pp_T2 (g); 00718 } 00719 00720 generic 00721 mmx_printer::pp_T2 (const generic& g) { 00722 if (is_func (g, GEN_RANGE, 2) || 00723 is_func (g, GEN_SCOPE, 2)) 00724 return infix (pp_T3 (g[1]), g[0], pp_T3 (g[2])); 00725 else if (is_func (g, GEN_TO, 2)) 00726 return infix (pp_T3 (g[1]), g[0], pp_T3 (g[2])); 00727 else if (is_func (g, GEN_DOWNTO, 2)) 00728 return infix (pp_T3 (g[1]), g[0], pp_T3 (g[2])); 00729 else return pp_T3 (g); 00730 } 00731 00732 static void 00733 collect (vector<generic>& v, const generic& g, nat depth) { 00734 if (depth >= 16384) v << g; 00735 else if (is_func (g, GEN_PLUS, 2)) { 00736 collect (v, g[1], depth+1); 00737 collect (v, g[2], depth+1); 00738 } 00739 else if (is_func (g, GEN_MINUS, 2)) { 00740 collect (v, g[1], depth+1); 00741 v << gen (GEN_MINUS, g[2]); 00742 } 00743 else v << g; 00744 } 00745 00746 static vector<generic> 00747 collect (const generic& g) { 00748 vector<generic> v; 00749 collect (v, g, 0); 00750 vector<generic> w; 00751 for (nat i=0; i<N(v); i++) 00752 if (is_func (v[i], GEN_PLUS, 2) || is_func (v[i], GEN_MINUS, 2)) 00753 w << collect (v[i]); 00754 else w << v[i]; 00755 return w; 00756 } 00757 00758 generic 00759 mmx_printer::pp_T3 (const generic& g) { 00760 if (is_func (g, GEN_PLUS, 2) || is_func (g, GEN_MINUS, 2)) { 00761 vector<generic> v= collect (g); 00762 for (nat i=0; i<N(v); i++) 00763 if (is_func (v[i], GEN_MINUS, 1)) 00764 v[i]= gen (GEN_MINUS, pp_T4 (v[i][1])); 00765 else v[i]= pp_T3 (v[i]); 00766 return bigop (GEN_PLUS, v); 00767 } 00768 else return pp_T4 (g); 00769 } 00770 00771 generic 00772 mmx_printer::pp_T4 (const generic& g) { 00773 if (is_func (g, GEN_TIMES, 2) || 00774 is_func (g, GEN_COMPOSE, 2) || 00775 is_func (g, GEN_APPEND, 2)) 00776 return infix (pp_T4 (g[1]), g[0], pp_T4 (g[2])); 00777 else if (is_func (g, GEN_OVER, 2) || 00778 is_func (g, GEN_SIZE, 2) || 00779 is_func (g, "%", 2) || 00780 is_func (g, "&", 2)) 00781 return infix (pp_T4 (g[1]), g[0], pp_T5 (g[2])); 00782 else if (is_func (g, GEN_DIV, 2)) 00783 return infix (pp_T4 (g[1]), "div", pp_T5 (g[2])); 00784 else if (is_func (g, GEN_QUO, 2)) 00785 return infix (pp_T4 (g[1]), "quo", pp_T5 (g[2])); 00786 else if (is_func (g, GEN_REM, 2)) 00787 return infix (pp_T4 (g[1]), "rem", pp_T5 (g[2])); 00788 else if (is_func (g, GEN_MOD, 2)) 00789 return infix (pp_T4 (g[1]), "mod", pp_T5 (g[2])); 00790 else return pp_T5 (g); 00791 } 00792 00793 generic 00794 mmx_printer::pp_T5 (const generic& g) { 00795 if (is_func (g, GEN_MINUS, 1)) 00796 return prefix (g[0], pp_R0 (g[1])); 00797 else if (is_func (g, GEN_EXPLODE, 1) || 00798 is_func (g, GEN_SIZE, 1) || 00799 is_func (g, "%", 1) || 00800 is_func (g, "&", 1) || 00801 is_func (g, GEN_NOT, 1)) 00802 return prefix (g[0], pp_T5 (g[1])); 00803 else if (is<literal> (g) && g != GEN_MINUS && 00804 starts (literal_to_string (g), "-")) 00805 return pp_verb (literal_to_string (g)); 00806 else return pp_R0 (g); 00807 } 00808 00809 /****************************************************************************** 00810 * Radicals 00811 ******************************************************************************/ 00812 00813 generic 00814 mmx_printer::pp_R0 (const generic& g) { 00815 return pp_R1 (g); 00816 } 00817 00818 generic 00819 mmx_printer::pp_R1 (const generic& g) { 00820 if (is_func (g, GEN_POWER, 2) || is_func (g, GEN_FILL, 2)) 00821 return infix (pp_R2 (g[1]), g[0], pp_R2 (g[2])); 00822 else return pp_R2 (g); 00823 } 00824 00825 generic 00826 mmx_printer::pp_R2 (const generic& g) { 00827 if (is_func (g, GEN_FACTORIAL, 1)) 00828 return postfix (pp_R2 (g[1]), "!"); 00829 else if (is_func (g, GEN_PRIME, 1)) 00830 return postfix (pp_R2 (g[1]), "'"); 00831 else if (is_func (g, GEN_BACKPRIME, 1)) 00832 return postfix (pp_R2 (g[1]), "`"); 00833 else if (is_func (g, GEN_STAR, 1)) 00834 return postfix (pp_R2 (g[1]), "*"); 00835 else if (is_func (g, GEN_HAT, 1)) 00836 return postfix (pp_R2 (g[1]), "^"); 00837 else if (is_func (g, GEN_TILDA, 1)) 00838 return postfix (pp_R2 (g[1]), "~"); 00839 else if (is_func (g, GEN_QUOTE, 1) || is_func (g, GEN_BACKQUOTE, 1)) { 00840 if (is<literal> (g[1])) // this test should be further improved 00841 return prefix (g[0], pp_verb (literal_to_string (g[1]))); 00842 else if (is_func (g[1], GEN_QUOTE, 1) || is_func (g[1], GEN_BACKQUOTE, 1)) 00843 return prefix (g[0], pp_E0 (g[1])); 00844 else return prefix (g[0], bracket ("(", pp_E0 (g[1]), ")")); 00845 } 00846 else if (N(g) == 2 && 00847 is<literal> (g[0]) && 00848 starts (literal_to_string (g[0]), ".")) 00849 return concat (pp_R2 (g[1]), pp_verb (literal_to_string (g[0]))); 00850 else if (is_func (g, GEN_ACCESS)) 00851 return operate (pp_R2 (g[1]), bracket ("[", pp_E0s (g, 2), "]")); 00852 else if ((is<compound> (g) && is_applicable (g[0])) || 00853 (!is_nil (gl) && exact_eq (read_car (gl), g))) { 00854 if (is<literal> (g)) return pp_verb (literal_to_string (g)); 00855 else if (is<literal> (g[0])) { 00856 string op= literal_to_string (g[0]); 00857 if (starts (op, "$") || starts (op, "tm$")) { 00858 vector<generic> v= vec<generic> (g[0]); 00859 for (nat i=1; i<N(g); i++) v << pp_E0 (g[i]); 00860 return vector_to_compound (v); 00861 } 00862 } 00863 return operate (pp_R2 (g[0]), bracket ("(", pp_E0s (g, 1), ")")); 00864 } 00865 else return pp_R3 (g); 00866 } 00867 00868 generic 00869 mmx_printer::pp_R3 (const generic& g) { 00870 if (is<literal> (g) && !starts (literal_to_string (g), "-")) 00871 return pp_verb (literal_to_string (g)); 00872 else if (is_func (g, GEN_SQTUPLE)) 00873 return bracket ("[", pp_E0s (g, 1), "]"); 00874 else if (is_func (g, GEN_TUPLE)) 00875 return bracket ("(", pp_E0s (g, 1), ")"); 00876 else if (is_func (g, GEN_ROW)) 00877 return pp_E0s (g, 1); 00878 else if (is_func (g, GEN_WHERE) || is_func (g, GEN_VWHERE)) 00879 return bracket ("(", pp_where (g), ")"); 00880 else { 00881 gl= cons (g, gl); 00882 generic r= pp_E0 (g); 00883 gl= read_cdr (gl); 00884 return bracket ("(", r, ")"); 00885 } 00886 } 00887 00888 /****************************************************************************** 00889 * Interface 00890 ******************************************************************************/ 00891 00892 generic 00893 print_mmx (const generic& g) { 00894 vector<generic> v; 00895 mmx_printer pp; 00896 if (is_func (g, GEN_BEGIN)) 00897 for (nat i=1; i<N(g); i++) 00898 v << pp.pp_C0 (g[i], i<N(g)-1); 00899 else if (is_C0 (g)) v << pp.pp_C0 (g); 00900 else v << pp.pp_E0 (g); 00901 return concat (v); 00902 } 00903 00904 string 00905 as_mmx (const generic& g) { 00906 return serialize (print_mmx (g)); 00907 } 00908 00909 string 00910 flatten_as_mmx (const generic& g) { 00911 generic f= as_generic (flatten (g)); 00912 return as_mmx (f); 00913 } 00914 00915 string 00916 output_as_mmx (const generic& g) { 00917 if (math_mode) { 00918 string r; 00919 r << DATA_BEGIN << "scheme:"; 00920 r << flatten_as_texmacs_scheme (g); 00921 r << DATA_END; 00922 return r; 00923 } 00924 else { 00925 generic f= as_generic (flatten (g)); 00926 return as_mmx (f); 00927 } 00928 } 00929 00930 string 00931 string_as_mmx (const string& s) { 00932 //if (math_mode) { ... } 00933 return s; 00934 } 00935 00936 } // namespace mmx