X-Git-Url: https://scm.cri.ensmp.fr/git/Faustine.git/blobdiff_plain/1059e1cc0c2ecfa237406949aa26155b6a5b9154..66f23d4fabf89ad09adbd4dfc15ac6b5b2b7da83:/interpreter/preprocessor/faust-0.9.47mr3/compiler/documentator/lateq.cpp diff --git a/interpreter/preprocessor/faust-0.9.47mr3/compiler/documentator/lateq.cpp b/interpreter/preprocessor/faust-0.9.47mr3/compiler/documentator/lateq.cpp new file mode 100644 index 0000000..d7b0a75 --- /dev/null +++ b/interpreter/preprocessor/faust-0.9.47mr3/compiler/documentator/lateq.cpp @@ -0,0 +1,546 @@ +/************************************************************************ + ************************************************************************ + FAUST compiler + Copyright (C) 2003-2004 GRAME, Centre National de Creation Musicale + --------------------------------------------------------------------- + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + ************************************************************************ + ************************************************************************/ + + + + /********************************************************************** + - lateq.cpp : the Lateq methods definition (FAUST project) - + - for automatic generation of documentation - + - "lateq" stands for "LaTeX equations" - + - The crucial method here is println - + + Historique : + ----------- + 17-10-2001 : (klass.cpp) implementation initiale (yo) + 18-10-2001 : (klass.cpp) Ajout de getFreshID (yo) + 02-11-2001 : (klass.cpp) Ajout de sous classes (yo) + 06-11-2001 : (klass.cpp) modif impression des classes (yo) + 16-08-2009 : (lateq.cpp) Creation de lateq depuis klass.cpp (kb) + 2009-11-21 : (lateq.cpp) Remodelage et documentation doxygen (kb) + +***********************************************************************/ + +#include +#include +#include +#include +#include + +#include "lateq.hh" +#include "Text.hh" + + +map gDocMathStringMap; +set gDocMathKeySet; + +static int getLateqIndex(const string& s); +static bool compLateqIndexes(const string& s1, const string& s2); +static void initDocMathKeySet(); + + +template +inline std::string to_string (const T& t) +{ + std::stringstream ss; + ss << t; + return ss.str(); +} + + +/**************************************************************** + Top-level "println" method (public). + *****************************************************************/ + + +/** + * @brief + * Top-level method to print a whole set of compiled LaTeX formulas, + * corresponding to an faustdoc tag. + * + * @remark + * These formulas must have been previously compiled, + * via the DocCompile class, + * and stored in Lateq fields as LaTeX strings. + */ +void Lateq::println(ostream& docout) +{ + /* 1. Make titles of sub-sets of formulas. */ + string suchthat = gDocMathStringMap["suchthat"]; + + string sInputs = makeItemTitle(fInputSigsFormulas.size(), "inputsigtitle") + makeSignamesList(fInputSigsFormulas, ""); + string sOutputs = makeItemTitle(fOutputSigsFormulas.size(), "outputsigtitle") + makeSignamesList(fOutputSigsFormulas, suchthat); + string sConstants = makeItemTitle(fConstSigsFormulas.size(), "constsigtitle") + makeSignamesList(fConstSigsFormulas, suchthat); + + vector > UISignamesVector = makeUISignamesVector(fUISigsFormulas); + string sUIElements = makeItemTitle(fUISigsFormulas.size(), "uisigtitle") + makeSignamesList(UISignamesVector, suchthat); + + unsigned int internalSigsCount = fParamSigsFormulas.size() + fStoreSigsFormulas.size() + fRecurSigsFormulas.size() + fRDTblSigsFormulas.size() + fRWTblSigsFormulas.size() + fSelectSigsFormulas.size() + fPrefixSigsFormulas.size(); + + vector > internalSigsFormulasList; + if( ! fParamSigsFormulas.empty() ) internalSigsFormulasList.push_back(fParamSigsFormulas); + if( ! fStoreSigsFormulas.empty() ) internalSigsFormulasList.push_back(fStoreSigsFormulas); + if( ! fRecurSigsFormulas.empty() ) internalSigsFormulasList.push_back(fRecurSigsFormulas); + if( ! fRDTblSigsFormulas.empty() ) internalSigsFormulasList.push_back(fRDTblSigsFormulas); + if( ! fRWTblSigsFormulas.empty() ) internalSigsFormulasList.push_back(fRWTblSigsFormulas); + if( ! fSelectSigsFormulas.empty() ) internalSigsFormulasList.push_back(fSelectSigsFormulas); + if( ! fPrefixSigsFormulas.empty() ) internalSigsFormulasList.push_back(fPrefixSigsFormulas); + + string sInternals = makeItemTitle(internalSigsCount, "intermedsigtitle") + makeSignamesList(internalSigsFormulasList, suchthat); + + /* 2. Successively print each Lateq field containing LaTeX formulas, with a title. */ + + docout << endl << gDocMathStringMap["lateqcomment"] << endl; + docout << "\\begin{enumerate}" << endl << endl; + + printDGroup (sOutputs, fOutputSigsFormulas, docout); + printOneLine (sInputs, docout); + const string outputsTitle = "\\item " + sOutputs + "\\ $y_i$\\ " + gDocMathStringMap["for"] + " $i \\in [1," + to_string(fOutputSigsFormulas.size()) + "]$: "; + printHierarchy (sUIElements, fUISigsFormulas, docout); + + /* The "Internal signals" item gather several fields, like a "super-item"... */ + if( internalSigsCount > 0 ) { + docout << sInternals; + } + fStoreSigsFormulas.sort(compLateqIndexes); + printDGroup ("", fParamSigsFormulas, docout); + printDGroup ("", fStoreSigsFormulas, docout); + printDGroup ("", fRecurSigsFormulas, docout); + printDGroup ("", fRDTblSigsFormulas, docout); + printMath ("", fRWTblSigsFormulas, docout); + printMath ("", fSelectSigsFormulas, docout); + printMath ("", fPrefixSigsFormulas, docout); + + printDGroup (sConstants, fConstSigsFormulas, docout); + + docout << "\\end{enumerate}" << endl << endl; +} + + + +/**************************************************************** + Item title making functions (public). + *****************************************************************/ + + +string Lateq::makeItemTitle(const unsigned int formulasListSize, const string& titleName) +{ + string item = "\\item "; + + /* Plural handling for titles of sub-sets of formulas. */ + string title = formulasListSize > 1 ? gDocMathStringMap[titleName + "2"] : gDocMathStringMap[titleName + "1"]; + + return item + title; +} + + +string Lateq::makeSigDomain(const list& formulasList) +{ + string signame = ""; + string sigDomain = ""; + + if (formulasList.size() > 0) { + string firstEq = *(formulasList.begin()); + signame = getSigName(firstEq); + + if(formulasList.size() > 1) { + sigDomain = " $" + signame + "_i$ " + gDocMathStringMap["for"] + " $i \\in [1," + to_string(formulasList.size()) + "]$"; + } else { + if(signame == "x" || signame == "y") { + sigDomain = " $" + signame + "$"; ///< No indices for single input neither single output. + } else { + sigDomain = " $" + signame + "_1$"; ///< Indices "1" for all other single signal. + } + } + } else { + sigDomain = gDocMathStringMap["emptyformulafield"]; + } + return sigDomain; +} + + +string Lateq::makeSignamesList(const list& formulasList, const string& ending) +{ + if (formulasList.size() > 0) { + return makeSigDomain(formulasList) + " " + ending; + } else { + return " (" + gDocMathStringMap["emptyformulafield"] + ")"; + } +} + + +string Lateq::makeSignamesList(const vector >& formulasListsVector, const string& ending) +{ + if (formulasListsVector.size() > 0) { + vector >::const_iterator it; + string signames = ""; + string sep = " "; + for (it = formulasListsVector.begin(); it != formulasListsVector.end(); ++it) { + signames += sep + makeSigDomain(*it); + (it != (formulasListsVector.end() - 2)) ? sep = ", " : sep = " " + gDocMathStringMap["and"] + " "; + } + return signames + " " + ending; + } else { + return " (" + gDocMathStringMap["emptyformulafield"] + ")"; + } +} + + +string Lateq::getSigName(const string& s) +{ + size_t found; + string signame; + + found = s.find(" ="); + if (found != string::npos) { ///< Looking for a left member. + signame = s.substr (0, found); + } + found = s.find("(t)"); + if (found != string::npos) { ///< Strip "(t)" argument if exists. + signame = s.substr (0, found); + } + found = signame.find("[t]"); + if (found != string::npos) { ///< Strip "[t]" argument if exists (for tables). + signame = s.substr (0, found); + } + found = signame.find_last_of("_"); + if (found != string::npos) { ///< Strip indice if exists. + signame = signame.substr (0, found); + } + + return signame; +} + + +vector > Lateq::makeUISignamesVector(const multimap& field) +{ + map uiTypesMap; + vector > uiSignamesVector; + unsigned int vIndex = 0; + + multimap::const_iterator it; + + for (it = field.begin(); it != field.end(); ++it) { + char type = getUISigType(it->second); + string signame = getUISigName(it->second); + + map::iterator uiTypesIt; + uiTypesIt = uiTypesMap.find(type); + if( uiTypesIt != uiTypesMap.end()) { + uiSignamesVector[uiTypesMap[uiTypesIt->second]].push_back(signame); + } else { + ++vIndex; + uiTypesMap.insert(pair(type, vIndex)); + list* tmpList = new(list); + tmpList->push_back(signame); + uiSignamesVector.push_back(*tmpList); + } + } + + return uiSignamesVector; +} + + +string Lateq::getUISigName(const string& s) +{ + size_t found; + string signame; + + found = s.find("${u_"); + if (found != string::npos) { ///< Looking for a UI signal name "{u_?}_{i}(t)". + signame = s.substr (found+1, 12); + } + + return signame; +} + + +char Lateq::getUISigType(const string& s) +{ + size_t found; + char sigtype = '0'; + + found = s.find("${u_"); + if (found != string::npos) { ///< Looking for a UI signal name "{u_?}_{i}". + sigtype = s.at (found+4); + } + + return sigtype; +} + + + +/**************************************************************** + Secondary printing methods (private). + *****************************************************************/ + + +/** + * Print a sorted list of input signals names ("x_i"), + * on a single line, separated by commas. + * + * @param[in] section The title to print for these formulas. + * @param[out] docout The LaTeX output file to print into. + */ +void Lateq::printOneLine(const string& section, ostream& docout) +{ + docout << section << endl << endl; +} + + +/** + * @brief Print a dgroup environment to auto-break long formulas. + * + * @remark + * The "dgroup" and "dmath" environments belong to the "breqn" LaTeX package. + * The stared variants "dgroup*" and "dmath*" force unnumbered equations. + * + * @param[in] section The title to print for these formulas. + * @param[in] field The list of LaTeX formulas. + * @param[out] docout The LaTeX output file to print into. + */ +void Lateq::printDGroup(const string& section, list& field, ostream& docout) +{ + if (field.size() > 0) { + docout << section << endl; + tab(1,docout); docout << "\\begin{dgroup*}" << endl; + list::const_iterator s; + for (s = field.begin(); s != field.end(); ++s) { + tab(2,docout); docout << "\\begin{" << "dmath*" << "}" << endl; + tab(3,docout); docout << "\t" << *s << endl; + tab(2,docout); docout << "\\end{" << "dmath*" << "}" << endl; + } + tab(1,docout); docout << "\\end{dgroup*}" << endl; + docout << endl; + } +} + + +/** + * @brief Print formulas for user interface signals. + * + * @param[in] section The title to print for these formulas. + * @param[in] field This multimap contains pairs : + * 1. the path_string is printed as a sub-title item, when new; + * 2. each latex_string is printed as a preformated row of the + * supertabular environment (needed to handle long tables). + * @param[out] docout The LaTeX output file to print into. + * + * @remark + * To decide when one should avoid to print an itemize environment, + * a "global" strategy is applied : in the particular case where + * ONLY empty paths were detected in the WHOLE container (all UIs + * are at the top level). + * In this particular case, UI strings are directly printed, + * and their (empty!) path is ignored... + * In the other case, we have to print an itemize environment + * and manage paths printing (empty AND non-empty paths) as items. + * + * @see DocCompiler::prepareIntervallicUI + * @see DocCompiler::prepareBinaryUI + */ +void Lateq::printHierarchy(const string& section, multimap& field, ostream& docout) +{ + if (field.size() > 0) { + docout << section << endl; + + bool hasSomePaths = hasNotOnlyEmptyKeys(field); ///< Manage itemize printing for pathnames. + unsigned int n; ///< Manage latex indentation offset. + + if (hasSomePaths) { + tab(0,docout); docout << "\\begin{itemize}" << endl; + n = 1; + } else { + n = 0; + } + + multimap::iterator it; + string uidir = "improbable_starting_dirname"; + bool startFlag = true; + + for (it = field.begin(); it != field.end(); ++it) { + /* Manage supertabular environment bounds and pathname printing. */ + if (it->first != uidir) { + if (!startFlag) { + tab(n+2,docout); docout << "\\end{supertabular}" << endl; + tab(n+1,docout); docout << "\\end{center}" << endl; + } else { + startFlag = false; + } + if (hasSomePaths) { + /* Print the current pathname if new and if pathnames requested. */ + if (it->first != "") { + tab(n+0,docout); docout << "\\item \\textsf{" << it->first << "}" << endl; + } else { + tab(n+0,docout); docout << "\\item \\emph{" << gDocMathStringMap["rootlevel"] << "}" << endl; + } + } + tab(n+1,docout); docout << "\\begin{center}" << endl; + tab(n+2,docout); docout << "\\begin{supertabular}{lll}" << endl; + } + /* Print the current formula. */ + tab(n+3,docout); docout << it->second << endl; + uidir = it->first; + } + tab(n+2,docout); docout << "\\end{supertabular}" << endl; + tab(n+1,docout); docout << "\\end{center}" << endl; + if (hasSomePaths) { + tab(n+0,docout); docout << "\\end{itemize}" << endl; + } + docout << endl; + } +} + + +/** + * @brief Print formulas for select2, select3 and prefix signals. + * + * @param[in] section The title to print for these formulas. + * @param[in] field The list of LaTeX arrays (for braces with two lines). + * @param[out] docout The LaTeX output file to print into. + * + * @see DocCompiler::generateSelect2 + * @see DocCompiler::generateSelect3 + * @see DocCompiler::generatePrefix + */ +void Lateq::printMath(const string& section, list& field, ostream& docout) +{ + if (field.size() > 0) { + docout << section; + docout << "\\begin{displaymath}" << endl; + list::iterator s; + for (s = field.begin(); s != field.end(); ++s) { + docout << *s << endl; + } + docout << "\\end{displaymath}" << endl; + docout << endl; + } +} + + +/** Simple handling of indentation. */ +void Lateq::tab (int n, ostream& docout) const +{ + while (n--) docout << '\t'; +} + + +/** + * @brief Find out whether all keys of the multimap are empty or not. + * + * In other words : + * Check that some UIs have a path (non empty). + * + * In other other words : + * Check that all UIs are not at top-level. + */ +bool Lateq::hasNotOnlyEmptyKeys(multimap& mm) +{ + typedef multimap::iterator MMIT; + pair range; + range = mm.equal_range(""); ///< Look for pairs with empty keys. + bool hasOnlyEmptyPaths = (range.first == mm.begin()) && (range.second == mm.end()); + return !hasOnlyEmptyPaths; +} + + + +/** + * Dispatch initialization of autodoc container. + */ +void initDocMath() +{ + initDocMathKeySet(); +} + + +/**************************************************************** + Internal static functions. + *****************************************************************/ + + +/** + * Compare indexes of two LaTeX strings, + * for the sort() method applied on list fields. + */ +static bool compLateqIndexes(const string& s1, const string& s2) +{ + return getLateqIndex(s1) < getLateqIndex(s2); +} + + +/** + * Find out the index of signals in LaTeX signal definition strings, + * between the first "_{" and "}" patterns. + * + * @param[in] s A LaTeX string to parse. + * @return The index found, as an integer. + */ +static int getLateqIndex(const string& s) +{ + size_t p1; + size_t p2; + string sIndex; + + p1 = s.find("_{"); + if (p1==string::npos) { + cerr << "Error : getLateqIndex found no \"{_\" substring.\n"; + exit(1); } + p1 += 2; + + p2 = s.find("}", p1); + if (p2==string::npos) { + cerr << "Error : getLateqIndex found no \"}\" substring\n."; + exit(1); } + p2 -= 3; + + sIndex = s.substr (p1, p2); + + return atoi(sIndex.c_str()); +} + + +/** + * Initialize gDocMathKeySet, a set containing all the keywords. + */ +static void initDocMathKeySet() +{ + gDocMathKeySet.insert("inputsigtitle1"); + gDocMathKeySet.insert("inputsigtitle2"); + gDocMathKeySet.insert("outputsigtitle1"); + gDocMathKeySet.insert("outputsigtitle2"); + gDocMathKeySet.insert("constsigtitle1"); + gDocMathKeySet.insert("constsigtitle2"); + gDocMathKeySet.insert("uisigtitle1"); + gDocMathKeySet.insert("uisigtitle2"); + gDocMathKeySet.insert("intermedsigtitle1"); + gDocMathKeySet.insert("intermedsigtitle2"); + gDocMathKeySet.insert("lateqcomment"); + gDocMathKeySet.insert("emptyformulafield"); + gDocMathKeySet.insert("defaultvalue"); + gDocMathKeySet.insert("suchthat"); + gDocMathKeySet.insert("and"); + gDocMathKeySet.insert("for"); + gDocMathKeySet.insert("rootlevel"); + + gDocMathKeySet.insert("dgmcaption"); +} + +