basix_doc 0.1
|
00001 00002 /****************************************************************************** 00003 * MODULE : cpp_printer.cpp 00004 * DESCRIPTION: C++ tree printer 00005 * COPYRIGHT : (C) 2000 Joris van der Hoeven, 2007 Gregoire Lecerf 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/basix-config.hpp> 00014 #if defined (BASIX_HAVE_CXXABI_H) 00015 #include <cxxabi.h> 00016 #endif 00017 #include <basix/cpp_syntax.hpp> 00018 #include <basix/list.hpp> 00019 #include <basix/table.hpp> 00020 #include <basix/literal.hpp> 00021 #include <basix/compound.hpp> 00022 00023 namespace mmx { 00024 00025 generic CPP_APPLY (".()"); 00026 generic CPP_ACCESS (".[]"); 00027 generic CPP_ALIAS_TYPE ("Alias"); 00028 generic CPP_AND ("and"); 00029 generic CPP_ARRAY_TYPE ("Array"); 00030 generic CPP_ARROW ("->"); 00031 generic CPP_ASSIGN (":="); 00032 generic CPP_BEGIN ("begin"); 00033 generic CPP_BITWISE_AND ("/\\"); 00034 generic CPP_BITWISE_OR ("\\/"); 00035 generic CPP_BITWISE_XOR ("xor"); 00036 generic CPP_BOOL_TYPE ("Boolean"); 00037 generic CPP_BRACKETS ("()"); 00038 generic CPP_BREAK ("break"); 00039 generic CPP_CAST (":>"); 00040 generic CPP_CATCH ("catch"); 00041 generic CPP_CHAR_TYPE ("Char"); 00042 generic CPP_CLASS_TYPE ("Type"); 00043 generic CPP_COMMA (","); 00044 generic CPP_COMPLEMENT ("~"); 00045 generic CPP_CONST ("const"); 00046 generic CPP_CONST_METHOD ("const_method"); 00047 generic CPP_CONSTRUCT ("construct"); 00048 generic CPP_CONSTRUCTOR ("constructor"); 00049 generic CPP_CONTINUE ("continue"); 00050 generic CPP_DEFINE ("=="); 00051 generic CPP_DELETE ("delete"); 00052 generic CPP_DESTRUCTOR ("destructor"); 00053 generic CPP_DO ("do"); 00054 generic CPP_DOT ("."); 00055 generic CPP_ELSE ("else"); 00056 generic CPP_EQUAL ("="); 00057 generic CPP_EXIT ("exit"); 00058 generic CPP_EXTERN ("extern"); 00059 generic CPP_EXTERN_C ("extern_C"); 00060 generic CPP_FOR ("for"); 00061 generic CPP_FRIEND ("friend"); 00062 generic CPP_FUNCTION_TYPE ("Function"); 00063 generic CPP_GTR (">"); 00064 generic CPP_GTREQ (">="); 00065 generic CPP_GTRGTR (">>"); 00066 generic CPP_GTRGTREQ (">>="); 00067 generic CPP_IF ("if"); 00068 generic CPP_INHERIT ("inherit"); 00069 generic CPP_INITIALIZE ("initialize"); 00070 generic CPP_INLINE ("inline"); 00071 generic CPP_INT_TYPE ("Int"); 00072 generic CPP_LESS ("<"); 00073 generic CPP_LESSEQ ("<="); 00074 generic CPP_LESSLESS ("<<"); 00075 generic CPP_LESSLESSEQ ("<<="); 00076 generic CPP_MACRO ("cpp_macro"); 00077 generic CPP_MINUS ("-"); 00078 generic CPP_MINUS_ASSIGN ("-="); 00079 generic CPP_MMX_APPLICATION_TYPE ("Mmx_application"); 00080 generic CPP_MOD ("%"); 00081 generic CPP_MOD_ASSIGN ("%="); 00082 generic CPP_NAMESPACE ("namespace"); 00083 generic CPP_NEW ("new"); 00084 generic CPP_NOT ("!"); 00085 generic CPP_OR ("or"); 00086 generic CPP_OVER ("/"); 00087 generic CPP_OVER_ASSIGN ("/="); 00088 generic CPP_PLUS ("+"); 00089 generic CPP_PLUS_ASSIGN ("+="); 00090 generic CPP_POINTER_TYPE ("Pointer"); 00091 generic CPP_POSTDEC (".--"); 00092 generic CPP_POSTINC (".++"); 00093 generic CPP_POWER ("^"); 00094 generic CPP_PREDEC ("--."); 00095 generic CPP_PREINC ("++."); 00096 generic CPP_PUBLIC ("public"); 00097 generic CPP_RETURN ("return"); 00098 generic CPP_SCOPE ("::"); 00099 generic CPP_SEMICOLON (";"); 00100 generic CPP_SPECIALIZE ("specialize"); 00101 generic CPP_STATIC ("static"); 00102 generic CPP_STRING_TYPE ("String"); 00103 generic CPP_STRUCT ("struct"); 00104 generic CPP_SWITCH ("switch"); 00105 generic CPP_TEMPLATE ("template"); 00106 generic CPP_THROW ("raise"); 00107 generic CPP_TIMES ("*"); 00108 generic CPP_TIMES_ASSIGN ("*="); 00109 generic CPP_TRY ("try"); 00110 generic CPP_TYPE (":"); 00111 generic CPP_TYPEDEF ("typedef"); 00112 generic CPP_TYPE_CONSTRUCTOR ("type_constructor"); 00113 generic CPP_UNALIAS ("unalias"); 00114 generic CPP_UNEQUAL ("!="); 00115 generic CPP_UNFUNCTION ("unfunction"); 00116 generic CPP_UNPOINTER ("unpointer"); 00117 generic CPP_USING ("using"); 00118 generic CPP_VERBATIM ("verbatim"); 00119 generic CPP_VIRTUAL ("virtual"); 00120 generic CPP_VOID_TYPE ("Void"); 00121 generic CPP_WHILE ("while"); 00122 generic CPP_XOR ("^^"); 00123 00124 /****************************************************************************** 00125 * Useful symbols and subroutines 00126 ******************************************************************************/ 00127 00128 inline generic 00129 cAr (const vector<generic>& a) { 00130 if (N(a) == 0) 00131 return generic (); 00132 return a[N(a)-1]; 00133 } 00134 00135 inline vector<generic> 00136 cDr (const vector<generic>& a) { 00137 if (N(a) == 0) 00138 return a; 00139 return range (a,0,N(a)-1); 00140 } 00141 00142 #define SET_OPNAME(var, val) \ 00143 t [literal_to_string (var)] = val; \ 00144 t [string ("operator ") * val] = val; 00145 00146 static table<string, string> 00147 opname_table () { 00148 table<string, string> t; 00149 SET_OPNAME (CPP_PLUS, "+") 00150 SET_OPNAME (CPP_MINUS, "-"); 00151 SET_OPNAME (CPP_TIMES, "*"); 00152 SET_OPNAME (CPP_OVER, "/"); 00153 SET_OPNAME (CPP_MOD, "%"); 00154 SET_OPNAME (CPP_AND, "&&"); 00155 SET_OPNAME (CPP_OR, "||"); 00156 SET_OPNAME (CPP_NOT, "!"); 00157 SET_OPNAME (CPP_BITWISE_AND, "&"); 00158 SET_OPNAME (CPP_BITWISE_OR, "|"); 00159 SET_OPNAME (CPP_BITWISE_XOR, "^"); 00160 SET_OPNAME (CPP_ASSIGN, "="); 00161 SET_OPNAME (CPP_LESS, "<"); 00162 SET_OPNAME (CPP_GTR, ">"); 00163 SET_OPNAME (CPP_PLUS_ASSIGN, "+="); 00164 SET_OPNAME (CPP_MINUS_ASSIGN, "-="); 00165 SET_OPNAME (CPP_TIMES_ASSIGN, "*="); 00166 SET_OPNAME (CPP_OVER_ASSIGN, "/="); 00167 SET_OPNAME (CPP_MOD_ASSIGN, "%="); 00168 SET_OPNAME (CPP_LESSLESS, "<<"); 00169 SET_OPNAME (CPP_LESSLESSEQ, "<<="); 00170 SET_OPNAME (CPP_GTRGTR, ">>"); 00171 SET_OPNAME (CPP_GTRGTREQ, ">>="); 00172 SET_OPNAME (CPP_EQUAL, "=="); 00173 SET_OPNAME (CPP_UNEQUAL, "!="); 00174 SET_OPNAME (CPP_LESSEQ, "<="); 00175 SET_OPNAME (CPP_GTREQ, ">="); 00176 SET_OPNAME (CPP_PREINC, "++"); 00177 SET_OPNAME (CPP_PREDEC, "--"); 00178 SET_OPNAME (CPP_ACCESS, "[]"); 00179 SET_OPNAME (CPP_COMPLEMENT, "~"); 00180 SET_OPNAME (CPP_ARROW, "->"); 00181 return t; 00182 } 00183 00184 /****************************************************************************** 00185 * Printing to strings 00186 ******************************************************************************/ 00187 00188 enum print_controls { LF, INDENT, UNINDENT }; 00189 00190 static nat indentation_level= 0; 00191 00192 static string& 00193 operator << (string& out, print_controls pc) { 00194 switch (pc) { 00195 case LF: 00196 out << "\n"; 00197 for (nat i=0; i<indentation_level; i++) out << " "; 00198 break; 00199 case INDENT: 00200 indentation_level++; 00201 out << " "; 00202 break; 00203 case UNINDENT: 00204 indentation_level--; 00205 if (N(out) >= 2 && out[N(out)-2] == ' ' && out[N(out)-1] == ' ') 00206 inside (out) -> resize (N(out) - 2); 00207 break; 00208 } 00209 return out; 00210 } 00211 00212 static string& 00213 operator << (string& out, const char* s) { 00214 return out << string (s); 00215 } 00216 00217 static string& 00218 operator << (string& out, const generic& g) { 00219 if (is<string> (g)) return out << as<string> (g); 00220 if (is<literal> (g)) return out << (*(as<literal> (g))); 00221 mmerr << g << ": " << type_name (g) << "\n"; 00222 assert (false); 00223 return out; 00224 } 00225 00226 /****************************************************************************** 00227 * The cpp printer class 00228 ******************************************************************************/ 00229 00230 class cpp_printer { 00231 private: 00232 string out; 00233 list<generic> sl; 00234 bool lf_flag; 00235 bool lf_done; 00236 00237 private: 00238 void pp_begin (const generic& g); 00239 void pp_instr (const generic& g); 00240 void pp_init (const generic& g); 00241 00242 void pp_decl (const generic& var, bool large= true); 00243 void pp_decl (const generic& var, const generic& type, bool large); 00244 void pp_type (const generic& g); 00245 void pp_funarg (const generic& g); 00246 void pp_funargs (const generic& g); 00247 00248 void pp_expr (const generic& g); 00249 void pp_exprs (const generic& g); 00250 void pp_comma (const generic& g); 00251 void pp_assign (const generic& g); 00252 00253 void pp_cond (const generic& g); 00254 void pp_seqor (const generic& g); 00255 void pp_seqand (const generic& g); 00256 void pp_or (const generic& g); 00257 void pp_xor (const generic& g); 00258 void pp_and (const generic& g); 00259 void pp_eq (const generic& g); 00260 void pp_rel (const generic& g); 00261 00262 void pp_shift (const generic& g); 00263 void pp_lshift (const generic& g); 00264 void pp_rshift (const generic& g); 00265 void pp_add (const generic& g); 00266 void pp_mult (const generic& g); 00267 00268 void pp_unary (const generic& g); 00269 void pp_postfix (const generic& g); 00270 void pp_primary (const generic& g); 00271 00272 public: 00273 inline cpp_printer (): out ("") { indentation_level= 0; } 00274 inline ~cpp_printer () {} 00275 00276 void pp (const generic& g); 00277 friend string as_cpp (const generic& g); 00278 }; 00279 00280 /****************************************************************************** 00281 * Required routines for generic structures 00282 ******************************************************************************/ 00283 00284 inline syntactic 00285 flatten (const cpp_printer& p) { 00286 return "#cpp_printer<>"; 00287 } 00288 00289 inline nat 00290 hash (const cpp_printer& p) { 00291 return 0; 00292 } 00293 00294 /****************************************************************************** 00295 * ABI support for name unmangling 00296 ******************************************************************************/ 00297 00298 #if defined (BASIX_HAVE_CXXABI_H) 00299 00300 string cpp_demangle(const char* name) { 00301 size_t size= 4096; 00302 char* buf= (char*) malloc (size); 00303 int status; 00304 char* res= abi::__cxa_demangle (name, buf, &size, &status); 00305 string ans (res); free ((void*) res); 00306 ASSERT (status==0, "invalid C++ type name"); 00307 return ans; 00308 } 00309 00310 #else 00311 00312 string cpp_demangle(const char* name) { 00313 static bool first= true; 00314 if (first) { 00315 mmerr << "Warning: C++ name unmangling is not available\n"; 00316 first= false; 00317 } 00318 return string (name); 00319 } 00320 00321 #endif 00322 00323 /****************************************************************************** 00324 * Instructions 00325 ******************************************************************************/ 00326 00327 void 00328 cpp_printer::pp_instr (const generic& g) { 00329 if (is_func (g, CPP_VERBATIM, 1) && is<string> (g[1])) { 00330 string s = as<string> (g[1]); 00331 int i, n = N(s); 00332 for (i=0; i<n; i++) 00333 if (s[i] == '\n') out << LF; 00334 else out << s[i]; 00335 } 00336 else if (is_func (g, CPP_NAMESPACE, 2)) { 00337 out << "namespace " << g[1] << " {" << LF << INDENT; 00338 pp_begin (g[2]); 00339 out << UNINDENT << "}" << LF; 00340 } 00341 else if (is_func (g, CPP_INITIALIZE)) { 00342 pp_init (g); 00343 generic last= cAr (compound_to_vector (g)); 00344 if (is_func (last, CPP_BEGIN)) pp_instr (last); 00345 else pp_instr (gen (CPP_BEGIN, last)); 00346 } 00347 else if (is_func (g, CPP_BEGIN)) { 00348 out << "{" << LF << INDENT; 00349 pp_begin (g); 00350 out << UNINDENT << "}" << LF; 00351 } 00352 else if (is_func (g, CPP_IF, 2)) { 00353 out << "if ("; 00354 pp_expr (g[1]); 00355 out << ") "; 00356 if (is_func (g[2], CPP_IF)) pp_instr (gen (CPP_BEGIN, g[2])); 00357 else pp_instr (g[2]); 00358 } 00359 else if (is_func (g, CPP_IF, 3)) { 00360 out << "if ("; 00361 pp_expr (g[1]); 00362 out << ") "; 00363 if (is_func (g[2], CPP_IF, 2)) pp_instr (gen (CPP_BEGIN, g[2])); 00364 else pp_instr (g[2]); 00365 out << "else "; 00366 pp_instr (g[3]); 00367 } 00368 else if (is_func (g, CPP_WHILE, 2)) { 00369 out << "while ("; 00370 pp_expr (g[1]); 00371 out << ") "; 00372 pp_instr (g[2]); 00373 } 00374 else if (is_func (g, CPP_DO, 2)) { 00375 out << "do "; 00376 pp_instr (g[1]); 00377 out << "while ("; 00378 pp_expr (g[2]); 00379 out << ");"; 00380 } 00381 else if (is_func (g, CPP_FOR, 4)) { 00382 out << "for ("; 00383 pp_expr (g[1]); 00384 out << "; "; 00385 pp_expr (g[2]); 00386 out << "; "; 00387 pp_expr (g[3]); 00388 out << ") "; 00389 pp_instr (g[4]); 00390 } 00391 else if (is_func (g, CPP_BREAK, 0)) 00392 out << "break;" << LF; 00393 else if (is_func (g, CPP_CONTINUE, 0)) 00394 out << "continue;" << LF; 00395 else if (is_func (g, CPP_RETURN, 0)) 00396 out << "return;" << LF; 00397 else if (is_func (g, CPP_RETURN, 1)) { 00398 out << "return "; 00399 pp_expr (g[1]); 00400 out << ";" << LF; 00401 } 00402 else if (is_func (g, CPP_THROW, 1)) { 00403 out << "throw "; 00404 pp_expr (g[1]); 00405 out << ";" << LF; 00406 } 00407 else if (is_func (g, CPP_TRY) && N(g) >= 2) { 00408 out << "try "; 00409 pp_instr (is_func (g[1], CPP_BEGIN)? g[1]: gen (CPP_BEGIN, g[1])); 00410 for (nat i=2; i<N(g); i++) pp_instr (g[i]); 00411 } 00412 else if (is_func (g, CPP_CATCH, 2)) { 00413 out << "catch ("; 00414 pp_decl (g[1], false); 00415 out << ") "; 00416 pp_instr (g[2]); 00417 } 00418 else if (is_func (g, CPP_EXTERN_C, 1)) { 00419 out << "extern \"C\" "; 00420 pp (g[1]); 00421 } 00422 else pp_decl (g); 00423 } 00424 00425 void 00426 cpp_printer::pp_init (const generic& g) { 00427 vector<generic> l= cDr (cdr (compound_to_vector (g))); 00428 iterator<generic> i = iterate (l); 00429 bool first= true; 00430 for ( ; busy (i); ++i) { 00431 if (first) out << ": "; 00432 else out << ", "; 00433 pp_expr (*i); 00434 first= false; 00435 } 00436 } 00437 00438 void 00439 cpp_printer::pp_begin (const generic& g) { 00440 if (is_func (g, CPP_BEGIN) || is_func (g, CPP_STRUCT)) { 00441 lf_flag= false; 00442 lf_done= true; 00443 for (nat i=1; i<N(g); i++) { 00444 if (lf_flag) { out << LF; lf_flag= false; lf_done= true; } 00445 pp_instr (g[i]); 00446 lf_done= false; 00447 } 00448 } 00449 else pp_instr (g); 00450 } 00451 00452 /****************************************************************************** 00453 * Declarations 00454 ******************************************************************************/ 00455 00456 void 00457 cpp_printer::pp_decl (const generic& var, const generic& type, bool large) { 00458 // prefixes 00459 if (is_func (type, CPP_CONST, 1)) { 00460 out << "const "; 00461 pp_decl (var, type[1], large); 00462 } 00463 else if (is_func (type, CPP_CONST_METHOD, 1)) { 00464 pp_decl (var, type[1], large); 00465 out << " const"; 00466 } 00467 else if (is_func (type, CPP_EXTERN, 1)) { 00468 out << "extern "; 00469 pp_decl (var, type[1], large); 00470 } 00471 else if (is_func (type, CPP_EXTERN, 2)) { 00472 out << "extern " << type[1] << " "; 00473 pp_decl (var, type[2], large); 00474 } 00475 else if (is_func (type, CPP_INLINE, 1)) { 00476 out << "inline "; 00477 pp_decl (var, type[1], large); 00478 } 00479 else if (is_func (type, CPP_FRIEND, 1)) { 00480 out << "friend "; 00481 pp_decl (var, type[1], large); 00482 } 00483 else if (is_func (type, CPP_STATIC, 1)) { 00484 out << "static "; 00485 pp_decl (var, type[1], large); 00486 } 00487 else if (is_func (type, CPP_VIRTUAL, 1)) { 00488 out << "virtual "; 00489 pp_decl (var, type[1], large); 00490 } 00491 else if (is_func (type, CPP_TEMPLATE)) { 00492 vector<generic> x= cDr (cdr (compound_to_vector (type))); 00493 out << "template<"; 00494 bool first = true; 00495 iterator<generic> i; 00496 for (i = iterate (x); busy(i); ++i) { 00497 if (!first) out << ", "; 00498 pp_funarg (*i); 00499 first = false; 00500 } 00501 out << "> "; 00502 pp_decl (var, cAr (compound_to_vector (type)), large); 00503 } 00504 00505 // rewriting into C++ form 00506 else if (is_func (type, CPP_ALIAS_TYPE, 1)) 00507 pp_decl (gen (CPP_UNALIAS, var), type[1], large); 00508 else if (is_func (type, CPP_POINTER_TYPE, 1)) 00509 pp_decl (gen (CPP_UNPOINTER, var), type[1], large); 00510 else if (is_func (type, CPP_ARRAY_TYPE)) { 00511 vector<generic> unfun= vec<generic> (CPP_ACCESS, var); 00512 vector<generic> args = cdr (cdr (compound_to_vector (type))); 00513 pp_decl (vector_to_compound (append (unfun, args)), type[1], large); 00514 } 00515 else if (is_func (type, CPP_FUNCTION_TYPE)) { 00516 vector<generic> unfun= vec<generic> (CPP_UNFUNCTION, var); 00517 vector<generic> args = cdr (cdr (compound_to_vector (type))); 00518 pp_decl (vector_to_compound (append (unfun, args)), type[1], large); 00519 } 00520 else if (is_func (type, CPP_CONSTRUCTOR)) { 00521 vector<generic> unfun= vec<generic> (CPP_UNFUNCTION, var); 00522 vector<generic> args = cdr (compound_to_vector (type)); 00523 pp_decl (vector_to_compound (append (unfun, args)), "", large); 00524 } 00525 else if (is_func (type, CPP_DESTRUCTOR, 0)) 00526 pp_decl (gen (CPP_UNFUNCTION, var), "~", large); 00527 else if (is_func (type, CPP_INHERIT)) { 00528 out << "struct " << var << ": "; 00529 iterator<generic> i; 00530 bool first = true; 00531 for (i = iterate (cdr (compound_to_vector (type))); busy(i); ++i) { 00532 if (!first) out << ", "; 00533 pp_type (*i); 00534 first = false; 00535 } 00536 } 00537 00538 // normal declarations 00539 else if (type == "~") { 00540 if (is_func (var, CPP_UNFUNCTION, 1) && is_func (var[1], CPP_SCOPE, 2)) { 00541 generic v= var[1]; 00542 ASSERT (!is_func (v[2], CPP_SCOPE, 2), "unimplemented nested scope"); 00543 pp_type (v[1]); 00544 out << "::~"; 00545 pp_type (v[2]); 00546 out << " ()"; 00547 } 00548 else { 00549 out << "~"; 00550 pp_expr (var); 00551 } 00552 } 00553 else { 00554 pp_type (type); 00555 if (type == ""); 00556 else if (large && (type != CPP_CLASS_TYPE)) out << LF; 00557 else out << " "; 00558 pp_expr (var); 00559 } 00560 } 00561 00562 static bool 00563 is_function_type (const generic& g) { 00564 return 00565 is_func (g, CPP_FUNCTION_TYPE) || 00566 (is_func (g, CPP_INLINE, 1) && is_function_type (g[1])) || 00567 (is_func (g, CPP_STATIC, 1) && is_function_type (g[1])); 00568 } 00569 00570 void 00571 cpp_printer::pp_decl (const generic& g, bool large) { 00572 if (is_func (g, CPP_TYPEDEF, 2)) { 00573 out << "typedef "; 00574 pp_decl (gen (CPP_TYPE, g[1], g[2])); 00575 } 00576 else if (is_func (g, CPP_DEFINE, 2) || is_func (g, CPP_ASSIGN, 2)) { 00577 bool large2= false; 00578 bool emptyb= false; 00579 if (is_func (g[1], CPP_TYPE, 2)) { 00580 // fix functions bodies which are not of the kind CPP_BEGIN 00581 if (is_function_type (g[1][2]) && !is_func (g[2], CPP_BEGIN)) { 00582 pp_decl (gen (g[0], g[1], gen (CPP_BEGIN, g[2])), large); 00583 return; 00584 } 00585 00586 large2= is_func (g[2], CPP_INITIALIZE); 00587 large2 |= is_func (g[2], CPP_BEGIN); 00588 large2 |= is_func (g[2], CPP_STRUCT); 00589 emptyb |= is_func (g[2], CPP_BEGIN, 0); 00590 emptyb |= is_func (g[2], CPP_INITIALIZE) && 00591 is_func (g[2][N(g[2])-1], CPP_BEGIN, 0); 00592 if (large && large2 && (!lf_done) && (!emptyb)) out << LF; 00593 if (is_func (g[2], CPP_CONSTRUCT)) { 00594 vector<generic> var= 00595 cons (g[1][1], cdr (compound_to_vector (g[2]))); 00596 if (is_func (g, CPP_DEFINE, 2)) 00597 pp_decl (vector_to_compound (var), gen (CPP_CONST, g[1][2]), large2); 00598 else pp_decl (vector_to_compound (var), g[1][2], large2); 00599 } 00600 else { 00601 if (is_func (g, CPP_DEFINE, 2) && (!large2)) 00602 pp_decl (g[1][1], gen (CPP_CONST, g[1][2]), large2); 00603 else pp_decl (g[1][1], g[1][2], large2); 00604 } 00605 } 00606 else pp_cond (g[1]); 00607 if (large && large2) { 00608 generic h= g[2]; 00609 if (is_func (h, CPP_INITIALIZE)) { 00610 pp_init (h); 00611 generic last= cAr (compound_to_vector (h)); 00612 if (is_func (last, CPP_BEGIN)) h= last; 00613 else h= gen (CPP_BEGIN, last); 00614 } 00615 if (emptyb) { 00616 out << " {"; 00617 pp_begin (h); 00618 out << "}"; 00619 out << LF; 00620 lf_flag= false; 00621 } 00622 else { 00623 out << " {" << LF << INDENT; 00624 pp_begin (h); 00625 out << UNINDENT << "}"; 00626 if (is_func (h, CPP_STRUCT)) out << ";"; 00627 out << LF; 00628 lf_flag= true; 00629 } 00630 } 00631 else { 00632 if (!is_func (g[2], CPP_CONSTRUCT)) { 00633 out << " = "; 00634 pp_expr (g[2]); 00635 } 00636 if (large) out << ";" << LF; 00637 } 00638 } 00639 else if (is_func (g, CPP_TYPE, 2)) { 00640 pp_decl (g[1], g[2], false); 00641 if (large) out << ";" << LF; 00642 } 00643 else if (is_func (g, CPP_USING, 1)) { 00644 out << "using "; 00645 pp_expr (g[1]); 00646 out << ";" << LF; 00647 } 00648 else { 00649 pp_expr (g); 00650 out << ";" << LF; 00651 } 00652 } 00653 00654 /****************************************************************************** 00655 * Function arguments in function declarations 00656 ******************************************************************************/ 00657 00658 void 00659 cpp_printer::pp_type (const generic& g) { 00660 if (is_func (g, CPP_ALIAS_TYPE, 1)) { 00661 pp_type (g[1]); 00662 out << "&"; 00663 } 00664 else if (is_func (g, CPP_POINTER_TYPE, 1)) { 00665 pp_type (g[1]); 00666 out << "*"; 00667 } 00668 else if (is_func (g, CPP_SCOPE, 2)) { 00669 pp_type (g[1]); 00670 out << "::"; 00671 pp_type (g[2]); 00672 } 00673 else if (is_func (g, CPP_CONST, 1)) { 00674 out << "const "; 00675 pp_type (g[1]); 00676 } 00677 else if (is_func (g, CPP_CONST_METHOD, 1)) { 00678 pp_type (g[1]); 00679 out << " const"; 00680 } 00681 else if (is_func (g, CPP_PUBLIC, 1)) { 00682 out << "public "; 00683 pp_type (g[1]); 00684 } 00685 else if (is_func (g, CPP_SPECIALIZE)) { 00686 generic fun= g[1]; 00687 bool macro_flag= is_func (fun, CPP_MACRO, 1); 00688 if (macro_flag) fun= fun[1]; 00689 pp_postfix (fun); 00690 if (macro_flag) out << "("; 00691 else out << "<"; 00692 pp_funargs (cdr (cdr (g))); 00693 if (N(g) > 2) out << " "; 00694 if (macro_flag) out << ")"; 00695 else out << ">"; 00696 } 00697 else if (is<compound> (g)) { 00698 vector<generic> l= compound_to_vector (g); 00699 generic fun= car (l); 00700 bool macro_flag= is_func (fun, CPP_MACRO, 1); 00701 if (macro_flag) fun= fun[1]; 00702 pp_type (fun); 00703 l= cdr (l); 00704 if (macro_flag) out << "("; 00705 else out << "<"; 00706 while (N (l) != 0) { 00707 pp_type (car (l)); 00708 if (N(cdr (l)) !=0 && is<compound> (car (l))) 00709 out << " "; 00710 if (N (l) != 1) out << ", "; 00711 else if (is<compound> (l[0])) out << " "; 00712 l= cdr (l); 00713 } 00714 if (macro_flag) out << ")"; 00715 else out << ">"; 00716 } 00717 else if (g == CPP_CLASS_TYPE) out << "struct"; 00718 else if (g == CPP_VOID_TYPE) out << "void"; 00719 else if (g == CPP_BOOL_TYPE) out << "bool"; 00720 else if (g == CPP_CHAR_TYPE) out << "char"; 00721 else if (g == CPP_INT_TYPE) out << "int"; 00722 else if (g == CPP_STRING_TYPE) out << "string"; 00723 else out << g; 00724 } 00725 00726 void 00727 cpp_printer::pp_funarg (const generic& g) { 00728 if (is_func (g, CPP_TYPE, 2) && (g[2] == CPP_CLASS_TYPE)) 00729 pp_decl (g[1], CPP_CLASS_TYPE, false); 00730 else if (is_func (g, CPP_TYPE, 2)) 00731 pp_decl (g[1], g[2], false); 00732 else if (is_func (g, CPP_DEFINE, 2) || is_func (g, CPP_ASSIGN, 2)) 00733 pp_decl (g, false); 00734 else pp_type (g); 00735 } 00736 00737 void 00738 cpp_printer::pp_funargs (const generic& g) { 00739 if (N(g) == 1) pp_funarg (car (g)); 00740 if (N(g) <= 1) return; 00741 pp_funarg (car (g)); 00742 out << ", "; 00743 pp_funargs (cdr (g)); 00744 } 00745 00746 /****************************************************************************** 00747 * Expressions 00748 ******************************************************************************/ 00749 00750 void 00751 cpp_printer::pp_expr (const generic& g) { 00752 if (is_func (g, "$text", 1) || is_func (g, "$math", 1)) 00753 pp_expr (g[1]); 00754 else pp_comma (g); 00755 } 00756 00757 void 00758 cpp_printer::pp_exprs (const generic& g) { 00759 if (N(g) == 1) pp_expr (car (g)); 00760 if (N(g) <= 1) return; 00761 pp_expr (car (g)); 00762 out << ", "; 00763 pp_exprs (cdr (g)); 00764 } 00765 00766 void 00767 cpp_printer::pp_comma (const generic& g) { 00768 if (is_func (g, CPP_BEGIN)) { 00769 if (N(g) == 1); 00770 else if (N(g) == 2) pp_comma (g[1]); 00771 else for (nat i=1; i<N(g); i++) { 00772 if (i>1) out << ", "; 00773 pp_comma (g[i]); 00774 } 00775 } 00776 else pp_assign (g); 00777 } 00778 00779 /****************************************************************************** 00780 * Assignments 00781 ******************************************************************************/ 00782 00783 void 00784 cpp_printer::pp_assign (const generic& g) { 00785 if (is_func (g, CPP_ASSIGN, 2)) { 00786 pp_cond (g[1]); 00787 out << " = "; 00788 pp_assign (g[2]); 00789 } 00790 else if (is_func (g, CPP_PLUS_ASSIGN, 2)) { 00791 pp_cond (g[1]); 00792 out << " += "; 00793 pp_assign (g[2]); 00794 } 00795 else if (is_func (g, CPP_MINUS_ASSIGN, 2)) { 00796 pp_cond (g[1]); 00797 out << " -= "; 00798 pp_assign (g[2]); 00799 } 00800 else if (is_func (g, CPP_TIMES_ASSIGN, 2)) { 00801 pp_cond (g[1]); 00802 out << " *= "; 00803 pp_assign (g[2]); 00804 } 00805 else if (is_func (g, CPP_OVER_ASSIGN, 2)) { 00806 pp_cond (g[1]); 00807 out << " /= "; 00808 pp_assign (g[2]); 00809 } 00810 else if (is_func (g, CPP_MOD_ASSIGN, 2)) { 00811 pp_cond (g[1]); 00812 out << " %= "; 00813 pp_assign (g[2]); 00814 } 00815 else if (is_func (g, CPP_LESSLESSEQ, 2)) { 00816 pp_cond (g[1]); 00817 out << " <<= "; 00818 pp_assign (g[2]); 00819 } 00820 else if (is_func (g, CPP_GTRGTREQ, 2)) { 00821 pp_cond (g[1]); 00822 out << " >>= "; 00823 pp_assign (g[2]); 00824 } 00825 else pp_cond (g); 00826 } 00827 00828 /****************************************************************************** 00829 * Conditional expressions 00830 ******************************************************************************/ 00831 00832 void 00833 cpp_printer::pp_cond (const generic& g) { 00834 if (is_func (g, CPP_IF, 3)) { 00835 pp_seqor (g[1]); 00836 out << " ? "; 00837 pp_seqor (g[2]); 00838 out << " : "; 00839 pp_seqor (g[3]); 00840 } 00841 else pp_seqor (g); 00842 } 00843 00844 /****************************************************************************** 00845 * Logical expressions 00846 ******************************************************************************/ 00847 00848 void 00849 cpp_printer::pp_seqor (const generic& g) { 00850 if (is_func (g, CPP_OR, 2)) { 00851 pp_seqor (g[1]); 00852 out << " || "; 00853 pp_seqor (g[2]); 00854 } 00855 else pp_seqand (g); 00856 } 00857 00858 void 00859 cpp_printer::pp_seqand (const generic& g) { 00860 if (is_func (g, CPP_AND, 2)) { 00861 pp_seqand (g[1]); 00862 out << " && "; 00863 pp_seqand (g[2]); 00864 } 00865 else pp_or (g); 00866 } 00867 00868 void 00869 cpp_printer::pp_or (const generic& g) { 00870 if (is_func (g, CPP_BITWISE_OR, 2)) { 00871 pp_or (g[1]); 00872 out << " | "; 00873 pp_or (g[2]); 00874 } 00875 else pp_xor (g); 00876 } 00877 00878 void 00879 cpp_printer::pp_xor (const generic& g) { 00880 if (is_func (g, CPP_BITWISE_XOR, 2)) { 00881 pp_xor (g[1]); 00882 out << " ^ "; 00883 pp_xor (g[2]); 00884 } 00885 else pp_and (g); 00886 } 00887 00888 void 00889 cpp_printer::pp_and (const generic& g) { 00890 if (is_func (g, CPP_BITWISE_AND, 2)) { 00891 pp_and (g[1]); 00892 out << " & "; 00893 pp_and (g[2]); 00894 } 00895 else pp_eq (g); 00896 } 00897 00898 /****************************************************************************** 00899 * Relational expressions 00900 ******************************************************************************/ 00901 00902 void 00903 cpp_printer::pp_eq (const generic& g) { 00904 if (is_func (g, CPP_EQUAL, 2)) { 00905 pp_rel (g[1]); 00906 out << " == "; 00907 pp_rel (g[2]); 00908 } 00909 else if (is_func (g, CPP_UNEQUAL, 2)) { 00910 pp_rel (g[1]); 00911 out << " != "; 00912 pp_rel (g[2]); 00913 } 00914 else pp_rel (g); 00915 } 00916 00917 void 00918 cpp_printer::pp_rel (const generic& g) { 00919 if (is_func (g, CPP_LESS, 2)) { 00920 pp_shift (g[1]); 00921 out << " < "; 00922 pp_shift (g[2]); 00923 } 00924 else if (is_func (g, CPP_LESSEQ, 2)) { 00925 pp_shift (g[1]); 00926 out << " <= "; 00927 pp_shift (g[2]); 00928 } 00929 else if (is_func (g, CPP_GTR, 2)) { 00930 pp_shift (g[1]); 00931 out << " > "; 00932 pp_shift (g[2]); 00933 } 00934 else if (is_func (g, CPP_GTREQ, 2)) { 00935 pp_shift (g[1]); 00936 out << " >= "; 00937 pp_shift (g[2]); 00938 } 00939 else pp_shift (g); 00940 } 00941 00942 /****************************************************************************** 00943 * Arithmetic expressions 00944 ******************************************************************************/ 00945 00946 void 00947 cpp_printer::pp_shift (const generic& g) { 00948 if (is_func (g, CPP_LESSLESS, 2)) { 00949 pp_lshift (g[1]); 00950 out << " << "; 00951 pp_add (g[2]); 00952 } 00953 else if (is_func (g, CPP_GTRGTR, 2)) { 00954 pp_add (g[1]); 00955 out << " >> "; 00956 pp_rshift (g[2]); 00957 } 00958 else pp_add (g); 00959 } 00960 00961 void 00962 cpp_printer::pp_lshift (const generic& g) { 00963 if (is_func (g, CPP_LESSLESS, 2)) { 00964 pp_lshift (g[1]); 00965 out << " << "; 00966 pp_add (g[2]); 00967 } 00968 else pp_add (g); 00969 } 00970 00971 void 00972 cpp_printer::pp_rshift (const generic& g) { 00973 if (is_func (g, CPP_GTRGTR, 2)) { 00974 pp_add (g[1]); 00975 out << " >> "; 00976 pp_rshift (g[2]); 00977 } 00978 else pp_add (g); 00979 } 00980 00981 void 00982 cpp_printer::pp_add (const generic& g) { 00983 if (is_func (g, CPP_PLUS, 2)) { 00984 pp_add (g[1]); 00985 out << " + "; 00986 pp_add (g[2]); 00987 } 00988 else if (is_func (g, CPP_MINUS, 2)) { 00989 pp_add (g[1]); 00990 out << " - "; 00991 pp_mult (g[2]); 00992 } 00993 else pp_mult (g); 00994 } 00995 00996 void 00997 cpp_printer::pp_mult (const generic& g) { 00998 if (is_func (g, CPP_TIMES, 2)) { 00999 pp_mult (g[1]); 01000 out << " * "; 01001 pp_mult (g[2]); 01002 } 01003 else if (is_func (g, CPP_OVER, 2)) { 01004 pp_mult (g[1]); 01005 out << " / "; 01006 pp_unary (g[2]); 01007 } 01008 else if (is_func (g, CPP_MOD, 2)) { 01009 pp_mult (g[1]); 01010 out << " % "; 01011 pp_unary (g[2]); 01012 } 01013 else pp_unary (g); 01014 } 01015 01016 /****************************************************************************** 01017 * Unary, postfix and primary expressions 01018 ******************************************************************************/ 01019 01020 void 01021 cpp_printer::pp_unary (const generic& g) { 01022 if (is_func (g, CPP_PREINC, 1)) { 01023 out << "++"; 01024 pp_unary (g[1]); 01025 } 01026 else if (is_func (g, CPP_PREDEC, 1)) { 01027 out << "--"; 01028 pp_unary (g[1]); 01029 } 01030 else if (is_func (g, CPP_TIMES, 1) || is_func (g, CPP_UNPOINTER, 1)) { 01031 out << "*"; 01032 pp_unary (g[1]); 01033 } 01034 else if (is_func (g, CPP_UNALIAS, 1)) { 01035 out << "&"; 01036 pp_unary (g[1]); 01037 } 01038 else if (is_func (g, CPP_PLUS, 1)) { 01039 out << "+"; 01040 pp_unary (g[1]); 01041 } 01042 else if (is_func (g, CPP_MINUS, 1)) { 01043 out << "-"; 01044 pp_unary (g[1]); 01045 } 01046 else if (is_func (g, CPP_NOT, 1)) { 01047 out << "!"; 01048 pp_unary (g[1]); 01049 } 01050 else if (is_func (g, CPP_COMPLEMENT, 1)) { 01051 out << "~"; 01052 pp_unary (g[1]); 01053 } 01054 else if (is_func (g, CPP_DELETE, 1)) { 01055 out << "delete "; 01056 pp_expr (g[1]); 01057 } 01058 else if (is_func (g, CPP_NEW)) { 01059 out << "new "; 01060 pp_type (g[1]); 01061 out << " ("; 01062 pp_exprs (cdr (cdr (g))); 01063 out << ")"; 01064 } 01065 else if (is_func (g, CPP_CAST)) { 01066 out << "(("; 01067 pp_type (g[2]); 01068 out << ") "; 01069 pp_expr (g[1]); 01070 out << ")"; 01071 } 01072 else pp_postfix (g); 01073 } 01074 01075 /****************************************************************************** 01076 * Postfix expressions 01077 ******************************************************************************/ 01078 01079 static bool 01080 is_applicable (const generic& g) { 01081 if (is<literal> (g)) { 01082 string s= *as<literal> (g); 01083 if (N(s) == 0) return false; 01084 nat i; 01085 for (i=0; i<N(s); i++) 01086 if (((s[i]<'0') || (s[i]>'9')) && 01087 ((s[i]<'a') || (s[i]>'z')) && 01088 ((s[i]<'A') || (s[i]>'Z')) && 01089 ((s[i]<'_') || (s[i]>'_'))) 01090 return false; 01091 return 01092 s != CPP_IF && s != CPP_AND && s != CPP_OR && s != CPP_XOR && 01093 s != CPP_UNALIAS && s != CPP_UNPOINTER; 01094 } 01095 else if (is_func (g, CPP_SPECIALIZE) && N(g)>=2 && is_applicable (g[1])) 01096 return true; 01097 else if (is_func (g, CPP_TYPE_CONSTRUCTOR, 1)) 01098 return true; 01099 else return false; 01100 } 01101 01102 void 01103 cpp_printer::pp_postfix (const generic& g) { 01104 if (is_func (g, CPP_SCOPE, 2)) { 01105 pp_type (g[1]); 01106 out << "::"; 01107 pp_postfix (g[2]); 01108 } 01109 else if (is_func (g, CPP_DOT, 2)) { 01110 pp_postfix (g[1]); 01111 out << "."; 01112 pp_primary (g[2]); 01113 } 01114 else if (is_func (g, CPP_ARROW, 2)) { 01115 pp_postfix (g[1]); 01116 out << "->"; 01117 pp_primary (g[2]); 01118 } 01119 else if (is_func (g, CPP_POSTINC, 1)) { 01120 pp_postfix (g[1]); 01121 out << "++"; 01122 } 01123 else if (is_func (g, CPP_POSTDEC, 1)) { 01124 pp_postfix (g[1]); 01125 out << "--"; 01126 } 01127 else if (is_func (g, CPP_APPLY)) { 01128 pp_postfix (g[1]); 01129 out << " ("; 01130 pp_exprs (cdr (cdr (g))); 01131 out << ")"; 01132 } 01133 else if (is_func (g, CPP_UNFUNCTION)) { 01134 pp_postfix (g[1]); 01135 out << " ("; 01136 pp_funargs (cdr (cdr (g))); 01137 out << ")"; 01138 } 01139 else if (is_func (g, CPP_SPECIALIZE)) { 01140 generic fun= g[1]; 01141 bool macro_flag= is_func (fun, CPP_MACRO, 1); 01142 if (macro_flag) fun= fun[1]; 01143 pp_postfix (fun); 01144 if (macro_flag) out << "("; 01145 else out << "<"; 01146 pp_funargs (cdr (cdr (g))); 01147 if (N(g) > 2) out << " "; 01148 if (macro_flag) out << ")"; 01149 else out << ">"; 01150 } 01151 else if (is_func (g, CPP_TYPE_CONSTRUCTOR, 1)) { 01152 generic tp= g[1]; 01153 pp_type (tp); 01154 } 01155 else if (is_func (g, CPP_ACCESS)) { 01156 pp_postfix (g[1]); 01157 out << "["; 01158 pp_exprs (cdr (cdr (g))); 01159 out << "]"; 01160 } 01161 else if (is_func (g, CPP_POWER, 2)) { 01162 out << "pow ("; 01163 pp_exprs (cdr (g)); 01164 out << ")"; 01165 } 01166 else if (((N(g) > 0) && is_applicable (g[0])) || 01167 ((!is_nil (sl)) && (car (sl) == g))) { 01168 pp_postfix (car (g)); 01169 out << " ("; 01170 pp_exprs (cdr (g)); 01171 out << ")"; 01172 } 01173 else pp_primary (g); 01174 } 01175 01176 /****************************************************************************** 01177 * Primary expressions 01178 ******************************************************************************/ 01179 01180 void 01181 cpp_printer::pp_primary (const generic& g) { 01182 static table<string, string> t (opname_table ()); 01183 01184 if (is<string> (g)) { ERROR ("invalid primary symbol"); } 01185 //else if (is<string> (g) && (t->contains (as<string> (g)))) 01186 //out << string ("operator ") * t [as<string> (g)]; 01187 else if (g == CPP_POWER) out << "pow"; 01188 else if (is<literal> (g)) { 01189 string s= *as<literal> (g); 01190 if (t->contains (s)) out << (string ("operator ") * t [s]); 01191 else out << s; 01192 } 01193 else if (N(g) == 0) out << g; 01194 else if (is_func (g, CPP_BRACKETS, 1)) { 01195 out << "("; 01196 pp_expr (g[1]); 01197 out << ")"; 01198 } 01199 else { 01200 out << "("; 01201 sl= cons (g, sl); 01202 pp_expr (g); 01203 sl= cdr (sl); 01204 out << ")"; 01205 } 01206 } 01207 01208 /****************************************************************************** 01209 * Interface 01210 ******************************************************************************/ 01211 01212 void 01213 cpp_printer::pp (const generic& g) { 01214 pp_begin (g); 01215 } 01216 01217 string 01218 as_cpp (const generic& g) { 01219 cpp_printer pp; 01220 pp.pp (g); 01221 while (N (pp.out) > 0 && pp.out [N (pp.out) - 1] == '\n') 01222 inside (pp.out) -> resize (N (pp.out) - 1); 01223 return pp.out; 01224 } 01225 01226 string 01227 flatten_as_cpp (const generic& g) { 01228 generic f= as_generic (flatten (g)); 01229 return as_cpp (f); 01230 } 01231 01232 } // namespace mmx