FAUST compiler  0.9.9.6b8
lateq.cpp
Go to the documentation of this file.
00001 /************************************************************************
00002  ************************************************************************
00003     FAUST compiler
00004     Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale
00005     ---------------------------------------------------------------------
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019  ************************************************************************
00020  ************************************************************************/
00021 
00022 
00023 
00024  /**********************************************************************
00025         - lateq.cpp : the Lateq methods definition (FAUST project) -
00026         - for automatic generation of documentation -
00027         - "lateq" stands for "LaTeX equations" -
00028         - The crucial method here is println -
00029 
00030         Historique :
00031         -----------
00032         17-10-2001 : (klass.cpp) implementation initiale (yo)
00033         18-10-2001 : (klass.cpp) Ajout de getFreshID (yo)
00034         02-11-2001 : (klass.cpp) Ajout de sous classes (yo)
00035         06-11-2001 : (klass.cpp) modif impression des classes (yo)
00036         16-08-2009 : (lateq.cpp) Creation de lateq depuis klass.cpp (kb)
00037         2009-11-21 : (lateq.cpp) Remodelage et documentation doxygen (kb)
00038 
00039 ***********************************************************************/
00040 
00041 #include <stdio.h>
00042 #include <iostream>
00043 #include <cstdlib>
00044 #include <set>
00045 #include <sstream>
00046 
00047 #include "lateq.hh"
00048 #include "Text.hh"
00049 
00050 
00051 map<string, string>     gDocMathStringMap;
00052 set<string>             gDocMathKeySet;
00053 
00054 static int  getLateqIndex(const string& s);
00055 static bool compLateqIndexes(const string& s1, const string& s2);
00056 static void initDocMathKeySet();
00057 
00058 
00059 template <class T>
00060 inline std::string to_string (const T& t)
00061 {
00062     std::stringstream ss;
00063     ss << t;
00064     return ss.str();
00065 }
00066 
00067 
00068 /****************************************************************
00069                 Top-level "println" method (public).
00070  *****************************************************************/
00071 
00072 
00083 void Lateq::println(ostream& docout)
00084 {   
00085     /* 1. Make titles of sub-sets of formulas. */
00086     string suchthat     = gDocMathStringMap["suchthat"];
00087     
00088     string sInputs      = makeItemTitle(fInputSigsFormulas.size(), "inputsigtitle") + makeSignamesList(fInputSigsFormulas, "");
00089     string sOutputs     = makeItemTitle(fOutputSigsFormulas.size(), "outputsigtitle") + makeSignamesList(fOutputSigsFormulas, suchthat);
00090     string sConstants   = makeItemTitle(fConstSigsFormulas.size(), "constsigtitle") + makeSignamesList(fConstSigsFormulas, suchthat);
00091     
00092     vector<list<string> > UISignamesVector = makeUISignamesVector(fUISigsFormulas);
00093     string sUIElements  = makeItemTitle(fUISigsFormulas.size(), "uisigtitle") + makeSignamesList(UISignamesVector, suchthat);
00094 
00095     unsigned int internalSigsCount = fParamSigsFormulas.size() + fStoreSigsFormulas.size() + fRecurSigsFormulas.size() + fRDTblSigsFormulas.size() + fRWTblSigsFormulas.size() + fSelectSigsFormulas.size() + fPrefixSigsFormulas.size();
00096     
00097     vector<list<string> > internalSigsFormulasList;
00098     if( ! fParamSigsFormulas.empty() )  internalSigsFormulasList.push_back(fParamSigsFormulas);
00099     if( ! fStoreSigsFormulas.empty() )  internalSigsFormulasList.push_back(fStoreSigsFormulas);
00100     if( ! fRecurSigsFormulas.empty() )  internalSigsFormulasList.push_back(fRecurSigsFormulas);
00101     if( ! fRDTblSigsFormulas.empty() )  internalSigsFormulasList.push_back(fRDTblSigsFormulas);
00102     if( ! fRWTblSigsFormulas.empty() )  internalSigsFormulasList.push_back(fRWTblSigsFormulas);
00103     if( ! fSelectSigsFormulas.empty() ) internalSigsFormulasList.push_back(fSelectSigsFormulas);
00104     if( ! fPrefixSigsFormulas.empty() ) internalSigsFormulasList.push_back(fPrefixSigsFormulas);
00105     
00106     string sInternals   = makeItemTitle(internalSigsCount, "intermedsigtitle") + makeSignamesList(internalSigsFormulasList, suchthat);
00107     
00108     /* 2. Successively print each Lateq field containing LaTeX formulas, with a title. */
00109     
00110     docout << endl << gDocMathStringMap["lateqcomment"] << endl;
00111     docout << "\\begin{enumerate}" << endl << endl;
00112     
00113     printDGroup     (sOutputs, fOutputSigsFormulas, docout);
00114     printOneLine    (sInputs, docout);
00115     const string outputsTitle = "\\item " + sOutputs + "\\ $y_i$\\ " + gDocMathStringMap["for"] + " $i \\in [1," + to_string(fOutputSigsFormulas.size()) + "]$: ";
00116     printHierarchy  (sUIElements, fUISigsFormulas, docout);
00117     
00118     /* The "Internal signals" item gather several fields, like a "super-item"... */
00119     if( internalSigsCount > 0 ) {
00120         docout << sInternals;
00121     }
00122     fStoreSigsFormulas.sort(compLateqIndexes);
00123     printDGroup     ("", fParamSigsFormulas, docout);
00124     printDGroup     ("", fStoreSigsFormulas, docout);
00125     printDGroup     ("", fRecurSigsFormulas, docout);
00126     printDGroup     ("", fRDTblSigsFormulas, docout);
00127     printMath       ("", fRWTblSigsFormulas, docout);
00128     printMath       ("", fSelectSigsFormulas, docout);
00129     printMath       ("", fPrefixSigsFormulas, docout);
00130 
00131     printDGroup     (sConstants, fConstSigsFormulas, docout);
00132     
00133     docout << "\\end{enumerate}" << endl << endl;
00134 }
00135 
00136 
00137 
00138 /****************************************************************
00139                 Item title making functions (public).
00140  *****************************************************************/
00141 
00142 
00143 string Lateq::makeItemTitle(const unsigned int formulasListSize, const string& titleName)
00144 {
00145     string item     = "\\item ";
00146     
00147     /* Plural handling for titles of sub-sets of formulas. */
00148     string title    = formulasListSize > 1 ? gDocMathStringMap[titleName + "2"] : gDocMathStringMap[titleName + "1"];
00149     
00150     return item + title;
00151 }
00152 
00153 
00154 string Lateq::makeSigDomain(const list<string>& formulasList)
00155 {
00156     string signame = "";
00157     string sigDomain = "";
00158     
00159     if (formulasList.size() > 0) {
00160         string firstEq = *(formulasList.begin());
00161         signame = getSigName(firstEq);
00162         
00163         if(formulasList.size() > 1) {
00164             sigDomain = " $" + signame + "_i$ " + gDocMathStringMap["for"] + " $i \\in [1," + to_string(formulasList.size()) + "]$";
00165         } else {
00166             if(signame == "x" || signame == "y") {
00167                 sigDomain = " $" + signame + "$"; 
00168             } else {
00169                 sigDomain = " $" + signame + "_1$"; 
00170             }
00171         }
00172     } else {
00173         sigDomain = gDocMathStringMap["emptyformulafield"];
00174     }
00175     return sigDomain;
00176 }
00177 
00178 
00179 string Lateq::makeSignamesList(const list<string>& formulasList, const string& ending)
00180 {
00181     if (formulasList.size() > 0) {
00182         return makeSigDomain(formulasList) + " " + ending;
00183     } else {
00184         return " (" + gDocMathStringMap["emptyformulafield"] + ")";
00185     }
00186 }
00187 
00188 
00189 string Lateq::makeSignamesList(const vector<list<string> >& formulasListsVector, const string& ending)
00190 {
00191     if (formulasListsVector.size() > 0) {
00192         vector<list<string> >::const_iterator it;
00193         string signames = "";
00194         string sep = " ";
00195         for (it = formulasListsVector.begin(); it != formulasListsVector.end(); ++it) {
00196             signames += sep + makeSigDomain(*it);
00197             (it != (formulasListsVector.end() - 2)) ? sep = ", " : sep = " " + gDocMathStringMap["and"] + " ";
00198         }
00199         return signames + " " + ending;
00200     } else {
00201         return " (" + gDocMathStringMap["emptyformulafield"] + ")";
00202     }
00203 }
00204 
00205 
00206 string Lateq::getSigName(const string& s)
00207 {
00208     size_t found;
00209     string signame;
00210     
00211     found = s.find(" =");
00212     if (found != string::npos) { 
00213         signame = s.substr (0, found);
00214     }
00215     found = s.find("(t)");
00216     if (found != string::npos) { 
00217         signame = s.substr (0, found);
00218     }
00219     found = signame.find("[t]");
00220     if (found != string::npos) { 
00221         signame = s.substr (0, found);
00222     }
00223     found = signame.find_last_of("_");
00224     if (found != string::npos) { 
00225         signame = signame.substr (0, found);
00226     }
00227     
00228     return signame;
00229 }
00230 
00231 
00232 vector<list<string> > Lateq::makeUISignamesVector(const multimap<string,string>& field)
00233 {
00234     map<char,unsigned int> uiTypesMap;
00235     vector<list<string> > uiSignamesVector;
00236     unsigned int vIndex = 0;
00237     
00238     multimap<string,string>::const_iterator it;
00239     
00240     for (it = field.begin(); it != field.end(); ++it) {
00241         char type       = getUISigType(it->second);
00242         string signame  = getUISigName(it->second);
00243         
00244         map<char,unsigned int>::iterator uiTypesIt;
00245         uiTypesIt = uiTypesMap.find(type);
00246         if( uiTypesIt != uiTypesMap.end()) {
00247             uiSignamesVector[uiTypesMap[uiTypesIt->second]].push_back(signame);
00248         } else {
00249             ++vIndex;
00250             uiTypesMap.insert(pair<char,unsigned int>(type, vIndex));
00251             list<string>* tmpList = new(list<string>);
00252             tmpList->push_back(signame);
00253             uiSignamesVector.push_back(*tmpList);
00254         }
00255     }
00256     
00257     return uiSignamesVector;
00258 }
00259 
00260 
00261 string Lateq::getUISigName(const string& s)
00262 {
00263     size_t found;
00264     string signame;
00265     
00266     found = s.find("${u_");
00267     if (found != string::npos) { 
00268         signame = s.substr (found+1, 12);
00269     }
00270     
00271     return signame;
00272 }
00273 
00274 
00275 char Lateq::getUISigType(const string& s)
00276 {
00277     size_t found;
00278     char sigtype = '0';
00279     
00280     found = s.find("${u_");
00281     if (found != string::npos) { 
00282         sigtype = s.at (found+4);
00283     }
00284     
00285     return sigtype;
00286 }
00287 
00288 
00289 
00290 /****************************************************************
00291                 Secondary printing methods (private).
00292  *****************************************************************/
00293 
00294 
00302 void Lateq::printOneLine(const string& section, ostream& docout)
00303 {
00304     docout << section << endl << endl;
00305 }
00306 
00307 
00319 void Lateq::printDGroup(const string& section, list<string>& field, ostream& docout)
00320 {
00321     if (field.size() > 0) {
00322         docout << section << endl;
00323         tab(1,docout); docout << "\\begin{dgroup*}" << endl;
00324         list<string>::const_iterator s;
00325         for (s = field.begin(); s != field.end(); ++s) {
00326             tab(2,docout); docout << "\\begin{" << "dmath*" << "}" << endl;
00327             tab(3,docout); docout << "\t" << *s << endl;
00328             tab(2,docout); docout << "\\end{" << "dmath*" << "}" << endl;
00329         }
00330         tab(1,docout); docout << "\\end{dgroup*}" << endl;
00331         docout << endl;
00332     }
00333 }
00334 
00335 
00359 void Lateq::printHierarchy(const string& section, multimap<string,string>& field, ostream& docout)
00360 {
00361     if (field.size() > 0) {
00362         docout << section << endl;
00363 
00364         bool hasSomePaths = hasNotOnlyEmptyKeys(field); 
00365         unsigned int n; 
00366                 
00367         if (hasSomePaths) {
00368             tab(0,docout); docout << "\\begin{itemize}" << endl;
00369             n = 1;
00370         } else {
00371             n = 0;
00372         }
00373 
00374         multimap<string,string>::iterator it;
00375         string uidir = "improbable_starting_dirname";
00376         bool startFlag = true;
00377 
00378         for (it = field.begin(); it != field.end(); ++it) {
00379             /* Manage supertabular environment bounds and pathname printing. */
00380             if (it->first != uidir) {
00381                 if (!startFlag) {
00382                     tab(n+2,docout); docout << "\\end{supertabular}" << endl;
00383                     tab(n+1,docout); docout << "\\end{center}" << endl;
00384                 } else { 
00385                     startFlag = false; 
00386                 }
00387                 if (hasSomePaths) {
00388                     /* Print the current pathname if new and if pathnames requested. */
00389                     if (it->first != "") {
00390                         tab(n+0,docout); docout << "\\item \\textsf{" << it->first << "}" << endl;
00391                     } else { 
00392                         tab(n+0,docout); docout << "\\item \\emph{" << gDocMathStringMap["rootlevel"] << "}" << endl;
00393                     }
00394                 }
00395                 tab(n+1,docout); docout << "\\begin{center}" << endl;
00396                 tab(n+2,docout); docout << "\\begin{supertabular}{lll}" << endl;
00397             }
00398             /* Print the current formula. */
00399             tab(n+3,docout); docout << it->second << endl;
00400             uidir = it->first;
00401         }
00402         tab(n+2,docout); docout << "\\end{supertabular}" << endl;
00403         tab(n+1,docout); docout << "\\end{center}" << endl;
00404         if (hasSomePaths) {
00405             tab(n+0,docout); docout << "\\end{itemize}" << endl;
00406         }
00407         docout << endl;
00408     }
00409 }
00410 
00411 
00423 void Lateq::printMath(const string& section, list<string>& field, ostream& docout)
00424 {
00425     if (field.size() > 0) {
00426         docout << section;
00427         docout << "\\begin{displaymath}" << endl;
00428         list<string>::iterator s;
00429         for (s = field.begin(); s != field.end(); ++s) {
00430             docout << *s << endl;       
00431         }
00432         docout << "\\end{displaymath}" << endl;
00433         docout << endl;     
00434     }
00435 }
00436 
00437 
00439 void Lateq::tab (int n, ostream& docout) const
00440 { 
00441     while (n--) docout << '\t'; 
00442 }
00443 
00444 
00454 bool Lateq::hasNotOnlyEmptyKeys(multimap<string,string>& mm) 
00455 {
00456     typedef multimap<string,string>::iterator MMIT;
00457     pair<MMIT,MMIT> range;
00458     range = mm.equal_range(""); 
00459     bool hasOnlyEmptyPaths = (range.first == mm.begin()) && (range.second == mm.end());
00460     return !hasOnlyEmptyPaths;
00461 }
00462 
00463 
00464 
00468 void initDocMath() 
00469 {
00470     initDocMathKeySet();
00471 }
00472 
00473 
00474 /****************************************************************
00475                 Internal static functions.
00476  *****************************************************************/
00477 
00478 
00483 static bool compLateqIndexes(const string& s1, const string& s2)
00484 {
00485     return getLateqIndex(s1) < getLateqIndex(s2);
00486 }
00487 
00488 
00496 static int getLateqIndex(const string& s)
00497 {
00498     size_t p1;
00499     size_t p2;
00500     string sIndex;
00501         
00502     p1 = s.find("_{"); 
00503     if (p1==string::npos) {
00504         cerr << "Error : getLateqIndex found no \"{_\" substring.\n";
00505         exit(1); }
00506     p1 += 2;
00507     
00508     p2 = s.find("}", p1); 
00509     if (p2==string::npos) {
00510         cerr << "Error : getLateqIndex found no \"}\" substring\n.";
00511         exit(1); }
00512     p2 -= 3;
00513     
00514     sIndex = s.substr (p1, p2);
00515 
00516     return atoi(sIndex.c_str());
00517 }
00518 
00519 
00523 static void initDocMathKeySet()
00524 {
00525     gDocMathKeySet.insert("inputsigtitle1");
00526     gDocMathKeySet.insert("inputsigtitle2");
00527     gDocMathKeySet.insert("outputsigtitle1");
00528     gDocMathKeySet.insert("outputsigtitle2");
00529     gDocMathKeySet.insert("constsigtitle1");
00530     gDocMathKeySet.insert("constsigtitle2");
00531     gDocMathKeySet.insert("uisigtitle1");
00532     gDocMathKeySet.insert("uisigtitle2");
00533     gDocMathKeySet.insert("intermedsigtitle1");
00534     gDocMathKeySet.insert("intermedsigtitle2");
00535     gDocMathKeySet.insert("lateqcomment");
00536     gDocMathKeySet.insert("emptyformulafield");
00537     gDocMathKeySet.insert("defaultvalue");
00538     gDocMathKeySet.insert("suchthat");
00539     gDocMathKeySet.insert("and");
00540     gDocMathKeySet.insert("for");
00541     gDocMathKeySet.insert("rootlevel");
00542 
00543     gDocMathKeySet.insert("dgmcaption");
00544 }
00545 
00546