NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
define.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2014 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19#include "define.hpp"
20#include "../../kernel.hpp"
21
22using namespace mu;
23using namespace std;
24
26// CLASS FUNCTIONDEFINITION
28
37FunctionDefinition::FunctionDefinition(const string& _sDefinitionString)
38{
39 sDefinitionString = _sDefinitionString;
40
41 if (sDefinitionString.length())
43}
44
45
55{
58 sName = _def.sName;
60 sComment = _def.sComment;
62
63 return *this;
64}
65
66
77string FunctionDefinition::parse(const string& _sArgList)
78{
79 string sParsedDefinition = sParsedDefinitionString;
80 static const string sOperators = "+-*/^&|!?:{";
81 string sArgs = _sArgList;
82
83 vector<string> vArg;
84
85 // Split the arguments
86 while (sArgs.length())
87 {
88 vArg.push_back(getNextArgument(sArgs, true));
89 }
90
91 // Clear the vector, if the first and single
92 // argument is empty
93 if (vArg.size() == 1 && !vArg[0].length())
94 {
95 vArg.clear();
96 }
97
98 // check, whether the arguments contain operators,
99 // which means, they are expressions and not only
100 // values -> They have to be surrounded by parentheses
101 for (unsigned int j = 0; j < vArg.size(); j++)
102 {
103 StripSpaces(vArg[j]);
104
105 if (!vArg[j].length())
106 vArg[j] = "0";
107
108 // Do nothing, if the argument is already surrounded
109 // with parentheses
110 if (vArg[j].front() == '(' && vArg[j].back() == ')')
111 continue;
112
113 // Search for operators
114 if (vArg[j].find_first_of(sOperators) != string::npos)
115 {
116 vArg[j] = "(" + vArg[j] + ")";
117 }
118 }
119
120 // Replace the variables in the definition with
121 // the passed arguments
122 for (size_t n = 0; n < vArguments.size(); n++)
123 {
124 // If fewer values than required are passed,
125 // append additional zeros
126 if (n >= vArg.size())
127 vArg.push_back("0");
128
129 if (!vArg[n].length())
130 vArg[n] = "0";
131
132 // If the current argument is the dotdotdot
133 // place holder, simply concatenate all following
134 // input arguments
135 if (vArguments[n] == ">>...<<")
136 {
137 if (n+1 < vArg.size())
138 {
139 for (unsigned int k = n+1; k < vArg.size(); k++)
140 vArg[n] += "," + vArg[k];
141
142 vArg.erase(vArg.begin()+n+1, vArg.end());
143 }
144 }
145
146 // Replace each occurence
147 while (sParsedDefinition.find(vArguments[n]) != string::npos)
148 {
149 sParsedDefinition.replace(sParsedDefinition.find(vArguments[n]), vArguments[n].length(), vArg[n]);
150 }
151 }
152
153 // Ensure that the number of passed values is not
154 // larger than the intended number of arguments
155 if (vArg.size() > vArguments.size())
157
158 // Remove obsolete surrounding whitespaces
159 StripSpaces(sParsedDefinition);
160
161 return sParsedDefinition;
162}
163
164
174{
175 string sExport = sName + "; " + sParsedDefinitionString + "; " + sDefinitionString + "; ";
176
177 // Append the single arguments
178 for (size_t i = 0; i < vArguments.size(); i++)
179 sExport += vArguments[i] + "; ";
180
181 return sExport;
182}
183
184
195bool FunctionDefinition::importFunction(const string& _sExportedString)
196{
197 string sImport = _sExportedString;
198 vArguments.clear();
199
200 // Decode function identifier
201 sName = sImport.substr(0, sImport.find(';'));
203 sImport.erase(0, sImport.find(';')+1);
204
205 // Decode parsed expression
206 sParsedDefinitionString = sImport.substr(0, sImport.find(';'));
208 sImport.erase(0, sImport.find(';')+1);
209
210 // Decode the original definition string
211 sDefinitionString = sImport.substr(0, sImport.find(';'));
213 sImport.erase(0, sImport.find(';')+1);
214
215 // Recreate the signature
218
219
220 // Separate the comment
221 if (findParameter(sDefinitionString, "comment", '='))
222 {
224 }
225
226 StripSpaces(sImport);
227
228 // Decode the variable list
229 while (sImport.length())
230 {
231 vArguments.push_back(sImport.substr(0, sImport.find(';')));
232 StripSpaces(vArguments.back());
233 sImport.erase(0, sImport.find(';')+1);
234 StripSpaces(sImport);
235 }
236
237 return true;
238}
239
240
250bool FunctionDefinition::appendComment(const string& _sComment)
251{
252 sComment += _sComment;
253
254 // Replace a previous comment, if there's one available
255 if (findParameter(sDefinitionString, "comment", '='))
256 {
257 size_t pos = findParameter(sDefinitionString, "comment", '=')+7;
258 string sTemp = getArgAtPos(sDefinitionString, pos);
259 pos = sDefinitionString.find(sTemp, pos);
260
261 sDefinitionString.replace(pos, sTemp.length(), sComment);
262 }
263 else
264 sDefinitionString += " -set comment=\"" + sComment + "\"";
265
266 return true;
267}
268
269
279{
280 string sDefinition = sDefinitionString.substr(sDefinitionString.find(":=")+2);
281
282 // Remove trailing parameters
283 if (sDefinition.find("-set") != string::npos)
284 sDefinition.erase(sDefinition.find("-set"));
285 else if (sDefinition.find("--") != string::npos)
286 sDefinition.erase(sDefinition.find("--"));
287
288 StripSpaces(sDefinition);
289
290 return sDefinition;
291}
292
293
303{
304 // Store the function identifier
305 sName = sDefinitionString.substr(0, sDefinitionString.find('('));
307
308 // Store the signature
311
312 // catch errors: numbers at the beginning or usual operators
313 // in the name
314 if (sName[0] >= '0' && sName[0] <= '9')
315 {
317 }
318
319 static std::string sDelim = "+-*/^!=&| ><()?[]{}$%#:.,;";
320
321 if (sName.find_first_of(sDelim) != string::npos)
322 {
324 }
325
326 // Separate the comment
327 if (findParameter(sDefinitionString, "comment", '='))
328 {
330 }
331
332 // Create the initial version of the parsed definition
333 // by extracting the expression from the definition
334 // string
336
337 if (sParsedDefinitionString.find("-set") != string::npos)
339 else if (sParsedDefinitionString.find("--") != string::npos)
341
342 // Surround the definition string with whitespaces for
343 // simplifying the use of "checkDelimiter"
345
346 // Split the argument list and validate its contents
348
349 // This section handles variables, which shall be
350 // stored as values instead variables
352
353 // Replace all occurences in the expression with
354 // new placeholders
356
357 // If the parsed definition string is multivalue
358 // surround it with braces
361
362 return true;
363}
364
365
374{
375 string sDelim = "+-*/^!=&| ><()?[]{}$%§~#:.,;";
376
377 // Get the argument list of the definition
378 string sArguments = sDefinitionString.substr(sDefinitionString.find('('));
379 sArguments.erase(getMatchingParenthesis(sArguments));
380 sArguments.erase(0, 1);
381
382 StripSpaces(sArguments);
383
384 // Split the arguments using "getNextArgument"
385 while (sArguments.length())
386 {
387 vArguments.push_back(getNextArgument(sArguments, true));
388 }
389
390 // Validate the arguments
391 for (size_t i = 0; i < vArguments.size(); i++)
392 {
393 // Ellipsis shall always be the last argument
394 if (vArguments[i] == "..." && i + 1 < vArguments.size())
395 {
397 }
398
399 // All other arguments shall not contain
400 // delimiters
401 if (vArguments[i] != "...")
402 {
403 if (vArguments[i].find_first_of(sDelim) != string::npos)
404 {
406 }
407 }
408 }
409
410 return true;
411}
412
413
423{
424 if (findParameter(sDefinitionString, "asval", '='))
425 {
426 string sAsVal = getArgAtPos(sDefinitionString, findParameter(sDefinitionString, "asval", '=')+5);
427
428 if (sAsVal.front() == '{')
429 sAsVal.erase(0,1);
430
431 if (sAsVal.back() == '}')
432 sAsVal.pop_back();
433
434 // Parse the list numerically
438
439 // Replace each occurence of the parsed variables
440 // with their value
441 for (auto iter = mAsVal.begin(); iter != mAsVal.end(); ++iter)
442 {
443 for (unsigned int i = 0; i < sParsedDefinitionString.length(); i++)
444 {
445 if (sParsedDefinitionString.substr(i, (iter->first).length()) == iter->first && checkDelimiter(sParsedDefinitionString.substr(i-1, (iter->first).length()+2)))
446 {
447 sParsedDefinitionString.replace(i, (iter->first).length(), toString(*iter->second, NumeReKernel::getInstance()->getSettings().getPrecision()));
448 }
449 }
450 }
451 }
452
453 return true;
454}
455
456
466{
467 // Replace all occurences in the expression with
468 // new placeholders
469 for (size_t i = 0; i < vArguments.size(); i++)
470 {
471 // create new position index
472 size_t nPos = 0;
473
474 // Search for the next occurence of the variable
475 while ((nPos = sParsedDefinitionString.find(vArguments[i], nPos)) != string::npos)
476 {
477 // check, whether the found match is an actual variable
478 if (checkDelimiter(sParsedDefinitionString.substr(nPos-1, vArguments[i].length() + 2)))
479 {
480 // replace VAR with >>VAR<< and increment the
481 // position index by the variable length + 4
482 sParsedDefinitionString.replace(nPos, vArguments[i].length(), ">>" + vArguments[i] + "<<");
483 nPos += vArguments[i].length() + 4;
484 }
485 else
486 nPos += vArguments[i].length();
487 }
488
489 // Replace the variable itself with >>VAR<<
490 vArguments[i] = ">>" + vArguments[i] + "<<";
491 }
492
493 return true;
494}
495
496
497
499// CLASS FUNCTIONDEFINITIONMANAGER
501
508{
509 sBuilt_In.clear();
510 sCommands = ",for,if,while,endfor,endwhile,endif,else,elseif,continue,break,explicit,procedure,endprocedure,throw,return,switch,case,endswitch,default,";
511 sFileName = "<>/functions.def";
512 sTables = "";
513 isLocal = _isLocal;
514}
515
516
526{
527 sFileName = _defined.sFileName;
528 sTables = _defined.sTables;
529
530 mFunctionsMap = _defined.mFunctionsMap;
531 isLocal = _defined.isLocal;
532}
533
534
546{
547 // Get the different parts of the definition
548 string sFunctionName = sDefinition.substr(0, sDefinition.find('(')+1);
549 string sFunction = sDefinition.substr(sDefinition.find(":=")+2);
550 string sFuncOccurence;
551
552 // Remove obsolete surrounding whitespaces
553 StripSpaces(sFunction);
554 StripSpaces(sFunctionName);
555
556 // Replace each occurence of this function by its previous
557 // definition
558 for (unsigned int i = 0; i < sFunction.length(); i++)
559 {
560 if (sFunction.substr(i, sFunctionName.length()) == sFunctionName
561 && (!i || !isalnum(sFunction[i-1])))
562 {
563 sFuncOccurence = sFunction.substr(i, sFunction.find(')', i) + 1 - i);
564
565 if (!call(sFuncOccurence))
566 {
567 return "";
568 }
569
570 StripSpaces(sFuncOccurence);
571 sFunction.replace(i, sFunction.find(')', i) + 1 - i, sFuncOccurence);
572 }
573 }
574
575 // Reconstruct the function definition using the
576 // replaced definition string
577 return sDefinition.substr(0, sDefinition.find(":=")) + " := " + sFunction;
578}
579
580
590map<string, FunctionDefinition>::const_iterator FunctionDefinitionManager::findItemById(size_t id) const
591{
592 if (id >= mFunctionsMap.size())
593 return mFunctionsMap.end();
594
595 map<string, FunctionDefinition>::const_iterator iter = mFunctionsMap.begin();
596
597 // As long as the ID is not zero,
598 // we increment the iterator and
599 // decrement the ID
600 while (iter != mFunctionsMap.end())
601 {
602 // Return the current iterator,
603 // if the ID is zero
604 if (!id)
605 return iter;
606
607 ++iter;
608 id--;
609 }
610
611 // Return the end, if the ID does not
612 // correspond to any item
613 return mFunctionsMap.end();
614}
615
616
626{
627 // Only use the function name
628 string sToLocate = sFunc.substr(0,sFunc.find('('));
629 StripSpaces(sToLocate);
630
631 if (mFunctionsMap.find(sToLocate) != mFunctionsMap.end())
632 return true;
633
634 // If it is not already defined by the user, check additionally,
635 // whether the passed function identifier corresponds either to
636 // a built-in function or a protected command
637 if (sBuilt_In.find("," + sToLocate + "(") != string::npos || sCommands.find("," + sToLocate + ",") != string::npos)
638 return true;
639 else
640 return false;
641}
642
643
655bool FunctionDefinitionManager::defineFunc(const string& sExpr, bool bRedefine, bool bFallback)
656{
658 return false;
659
660 // Handle the case that the user simply wanted to append
661 // a comment to the existing definition
662 if (bRedefine && sExpr.find("()") != string::npos && findParameter(sExpr, "comment", '=') && mFunctionsMap.size())
663 {
664 string sComment = getArgAtPos(sExpr, findParameter(sExpr, "comment", '=')+7);
665
666 if (mFunctionsMap.find(sExpr.substr(0, sExpr.find("()"))) != mFunctionsMap.end())
667 {
668 mFunctionsMap[sExpr.substr(0, sExpr.find("()"))].appendComment(sComment);
669
670 return true;
671 }
672
673 return false;
674 }
675
676 // Catch all possible syntax errors at this location
677 if (sExpr.find('(') == string::npos
678 || sExpr.find('(') > sExpr.find(":=")
679 || sBuilt_In.find(","+sExpr.substr(0,sExpr.find('(')+1)) != string::npos
680 || (sTables.length() && sTables.find(";"+sExpr.substr(0,sExpr.find('('))+";") != string::npos)
681 || sCommands.find(","+sExpr.substr(0,sExpr.find('('))+",") != string::npos
682 || sExpr.find(":=") == string::npos)
683 {
684 // Throw the corresponding error messages
685 if (sExpr.find(":=") == string::npos)
687 else if (sExpr.find('(') == string::npos || sExpr.find('(') > sExpr.find(":="))
689 else if (sBuilt_In.find(","+sExpr.substr(0,sExpr.find('(')+1)) != string::npos)
690 throw SyntaxError(SyntaxError::FUNCTION_IS_PREDEFINED, sExpr, SyntaxError::invalid_position, sExpr.substr(0,sExpr.find('(')));
691 else if (sTables.length() && sTables.find(";"+sExpr.substr(0,sExpr.find('('))+";") != string::npos)
692 throw SyntaxError(SyntaxError::CACHE_ALREADY_EXISTS, sExpr, SyntaxError::invalid_position, sExpr.substr(0,sExpr.find('(')));
693 else if (sCommands.find(","+sExpr.substr(0,sExpr.find('('))+",") != string::npos)
694 throw SyntaxError(SyntaxError::FUNCTION_STRING_IS_COMMAND, sExpr, SyntaxError::invalid_position, sExpr.substr(0,sExpr.find('(')));
695 else
697 }
698
699 // Check, whether the passed function is not already defined
700 if (!bRedefine && isDefined(sExpr))
701 throw SyntaxError(SyntaxError::FUNCTION_ALREADY_EXISTS, sExpr, SyntaxError::invalid_position, sExpr.substr(0, sExpr.find('(')));
702
703 string sDefinition = sExpr;
704
705 // Handle recursive redefinitions
706 if (bRedefine && findParameter(sExpr, "recursive"))
707 sDefinition = resolveRecursiveDefinitions(sDefinition);
708
709 // Prepare the function definition and the possible
710 // needed fallback
711 FunctionDefinition definition(sDefinition);
712 FunctionDefinition fallback;
713
714 // Get the function string
715 string sFunctionString = definition.getDefinition().substr(definition.getDefinition().find(":=")+2);
716
717 // check, whether the new function would result in an
718 // endless recursion
719 if (!call(sFunctionString))
720 return false;
721
722 // Store the fallback definition
723 if (bRedefine && isDefined(sDefinition))
724 fallback = mFunctionsMap[definition.sName];
725
726 // "define" the function
727 mFunctionsMap[definition.sName] = definition;
728
729 // Recreate the function string
730 sFunctionString = definition.getDefinition().substr(definition.getDefinition().find(":=")+2);
731
732 // Recheck, if the defined function will result in an
733 // endless loop and revert the definition, if this is
734 // the case
735 try
736 {
737 if (!call(sFunctionString))
738 {
739 if (!bRedefine)
740 mFunctionsMap.erase(definition.sName);
741 else
742 mFunctionsMap[definition.sName] = fallback;
743
744 return false;
745 }
746 }
747 catch (...)
748 {
749 if (!bRedefine)
750 mFunctionsMap.erase(definition.sName);
751 else
752 mFunctionsMap[definition.sName] = fallback;
753
754 throw;
755 }
756
757 if (!isLocal)
759
760 return true;
761}
762
763
773{
774 if (mFunctionsMap.find(sFunc.substr(0, sFunc.find('('))) != mFunctionsMap.end())
775 mFunctionsMap.erase(sFunc.substr(0, sFunc.find('(')));
776
777 if (isLocal)
778 return true;
779
780 // Update the definition file, if the corresponding setting
781 // is active
782 //if (NumeReKernel::getInstance() && NumeReKernel::getInstance()->getSettings().controlDefinitions())
783 // save(NumeReKernel::getInstance()->getSettings());
784
786 return true;
787}
788
789
801bool FunctionDefinitionManager::call(string& sExpr, int nRecursion)
802{
804 return false;
805
806 string sTemp = "";
807 string sImpFunc = "";
808 bool bDoRecursion = false;
809
810 if (!sExpr.length())
811 return true;
812
813 // Check, whether we've a possible candidate for an endless
814 // loop: if the number of recursions is twice the number of
815 // known function definitions, we've probably replaced every
816 // function twice, so we do not expect to terminate it.
817 if ((unsigned)nRecursion == mFunctionsMap.size()*2 + 1)
818 {
820 }
821
822 /* --> Ergaenze ggf. Leerzeichen vor und nach dem Ausdruck, damit die Untersuchung der Zeichen vor und
823 * nach einem Treffer keinen SEG-FAULT wirft <--
824 */
825 if (sExpr[0] != ' ')
826 sExpr = " " + sExpr;
827
828 if (sExpr[sExpr.length()-1] != ' ')
829 sExpr += " ";
830
831 // search through the whole set of definitions for
832 // possible matches
833 for (auto iter = mFunctionsMap.begin(); iter != mFunctionsMap.end(); ++iter)
834 {
835 size_t nPos = 0;
836
837 // Is there a possible match?
838 if (sExpr.find(iter->second.sName + "(") != string::npos)
839 {
840 // Check for each occurence, whether the candidate
841 // is an actual match and replace it with the parsed
842 // definition string
843 do
844 {
845 // Is it an actual match?
846 if (!checkDelimiter(sExpr.substr(sExpr.find(iter->second.sName + "(", nPos)-1, iter->second.sName.length()+2))
847 || isInQuotes(sExpr, sExpr.find(iter->second.sName + "(", nPos), true))
848 {
849 nPos = sExpr.find(iter->second.sName + "(", nPos) + iter->second.sName.length() + 1;
850 continue;
851 }
852
853 // Copy the part in front of the match into a
854 // temporary buffer
855 sTemp = sExpr.substr(0, sExpr.find(iter->second.sName + "(", nPos));
856
857 // save the position of the argument's opening
858 // parenthesis
859 nPos = sExpr.find(iter->second.sName + "(",nPos) + iter->second.sName.length();
860
861 // Copy the calling arguments
862 string sArgs = sExpr.substr(nPos);
863 size_t nPos_2 = getMatchingParenthesis(sArgs);
864
865 // Check, whether the sArgs are terminated
866 // by a parenthesis
867 if (nPos_2 == string::npos)
868 {
870 }
871
872 // Remove the surrounding parentheses
873 sArgs.erase(nPos_2);
874 sArgs.erase(0, 1);
875 nPos += nPos_2 + 1;
876
877 // Parse the function definition using the
878 // passed arguments
879 sImpFunc = iter->second.parse(sArgs);
880 StripSpaces(sImpFunc);
881
882 // Remove obsolete duplicated parenthesis pairs
883 while (sExpr[nPos] == ')' && sExpr[nPos+1] == ')' && sTemp.back() == '(' && sTemp[sTemp.length()-2] == '(')
884 {
885 nPos++;
886 sTemp.pop_back();
887 }
888
889 // Recreate the complete expression
890 if (sImpFunc.front() == '{' && sImpFunc.back() == '}')
891 {
892 if (sExpr[nPos] == ')' && sTemp.back() == '(')
893 {
894 if (sTemp[sTemp.length()-2] != ' ')
895 {
896 static string sDelim = "+-*/^!?:,!&|#";
897
898 if (sDelim.find(sTemp[sTemp.length()-2]) != string::npos)
899 {
900 sTemp.pop_back();
901 nPos++;
902 }
903 }
904 else
905 {
906 sTemp.pop_back();
907 nPos++;
908 }
909 }
910 sExpr = sTemp + sImpFunc + sExpr.substr(nPos);
911 }
912 else if (sTemp.back() == '(' && sExpr[nPos] == ')')
913 {
914 sExpr = sTemp + sImpFunc + sExpr.substr(nPos);
915 }
916 else
917 {
918 sExpr = sTemp + "(" + sImpFunc + ")" + sExpr.substr(nPos);
919 }
920
921 // If at least one replacement was preformed,
922 // is is possible that we introduced another
923 // function. Therefore we set the recursion
924 // boolean to true
925 if (!bDoRecursion)
926 bDoRecursion = true;
927 }
928 while (sExpr.find(iter->second.sName + "(", nPos) != string::npos);
929 }
930 }
931
932 // If necessary, then perform another recursion
933 if (bDoRecursion)
934 {
935 if (!call(sExpr, nRecursion+1))
936 return false;
937 }
938
939 return true;
940}
941
942
951{
952 return mFunctionsMap.size();
953}
954
955
965{
966 auto iter = findItemById(_i);
967
968 if (iter != mFunctionsMap.end())
969 return iter->second.sDefinitionString;
970
971 return "";
972}
973
974
984{
985 auto iter = findItemById(_i);
986
987 if (iter != mFunctionsMap.end())
988 return iter->second.sSignature;
989
990 return "";
991}
992
993
1003{
1004 auto iter = findItemById(_i);
1005
1006 if (iter != mFunctionsMap.end())
1007 return iter->second.getDefinition();
1008
1009 return "";
1010}
1011
1012
1022{
1023 auto iter = findItemById(_i);
1024
1025 if (iter != mFunctionsMap.end())
1026 return iter->second.sComment;
1027
1028 return "";
1029}
1030
1031
1041{
1042 mFunctionsMap.clear();
1043
1044 return true;
1045}
1046
1047
1057{
1059 ofstream ofDefineFile;
1060
1061 // Do not save anything, if the map is empty
1062 if (mFunctionsMap.size())
1063 {
1064 if (_option.systemPrints())
1065 NumeReKernel::printPreFmt("|-> " + toSystemCodePage(_lang.get("DEFINE_SAVING_FUNCTIONS")) + " ... ");
1066
1067 // Open the definition file
1068 ofDefineFile.open(sFileName.c_str(), ios_base::trunc);
1069
1070 // Ensure that the file stream is in a
1071 // valid state
1072 if (ofDefineFile.good())
1073 {
1074 ofDefineFile << "# This file saves the function definitions. Do not edit unless you know, what you're doing!" << endl;
1075
1076 // Save each definition
1077 for (auto iter = mFunctionsMap.begin(); iter != mFunctionsMap.end(); ++iter)
1078 {
1079 ofDefineFile << iter->second.exportFunction() << endl;
1080 }
1081
1082 if (_option.systemPrints())
1083 NumeReKernel::printPreFmt(toSystemCodePage(_lang.get("COMMON_SUCCESS")) + ".\n");
1084
1085 return true;
1086 }
1087
1088 return false;
1089 }
1090
1091 return false;
1092}
1093
1094
1104bool FunctionDefinitionManager::load(const Settings& _option, bool bAutoLoad)
1105{
1107 ifstream ifDefinedFile;
1108 string sInputLine;
1109
1110 // Open the definition file
1111 ifDefinedFile.open(sFileName.c_str());
1112
1113 // Check, whether the file stream is in
1114 // a valid state, aka the file exists
1115 if (ifDefinedFile.good())
1116 {
1117 if (_option.systemPrints() && !bAutoLoad)
1118 NumeReKernel::printPreFmt("|-> " + toSystemCodePage(_lang.get("DEFINE_LOADING_FUNCTIONS")) + " ... ");
1119
1120 // Read every line of the definition file
1121 while (!ifDefinedFile.eof())
1122 {
1123 getline(ifDefinedFile, sInputLine);
1124
1125 // Ignore emoty lines and comments
1126 if (!sInputLine.length() || sInputLine.front() == '#')
1127 continue;
1128
1129 // Create an empty definition object and import
1130 // the read definition
1131 FunctionDefinition definition;
1132 definition.importFunction(sInputLine);
1133 mFunctionsMap[definition.sName] = definition;
1134 }
1135
1136 if (!bAutoLoad && _option.systemPrints())
1137 {
1138 NumeReKernel::printPreFmt(toSystemCodePage(_lang.get("COMMON_SUCCESS")) + ".\n");
1139 NumeReKernel::print(LineBreak(_lang.get("DEFINE_DONE_LOADING", toString(mFunctionsMap.size())), _option));
1140 }
1141
1142 }
1143
1144 return true;
1145}
1146
1147
1159{
1160 sBuilt_In = sPredefined;
1161
1162 if ((sBuilt_In.find(',') == string::npos || sBuilt_In.find("()") == string::npos) && sBuilt_In.find(' ') != string::npos)
1163 {
1164 sBuilt_In.insert(0, ",");
1165 sBuilt_In += "()";
1166
1167 for (size_t i = 0; i < sBuilt_In.length(); i++)
1168 {
1169 if (sBuilt_In[i] == ' ')
1170 {
1171 sBuilt_In.replace(i, 1, "(),");
1172 }
1173 }
1174 }
1175}
1176
1177
1178
1179
1180
1181
This class implements the basic input/ output file system and provides functionalities to work with f...
Definition: filesystem.hpp:92
std::string ValidFileName(std::string _sFileName, const std::string sExtension=".dat", bool checkExtension=true, bool doCleanPath=true) const
This member function evaluates, whether the passed filename is a valid filename. One may supply a pre...
Definition: filesystem.cpp:280
This class implements a single function definition. It is managed by the Define class.
Definition: define.hpp:43
bool splitAndValidateArguments()
This private member function validates the arguments of the function definition.
Definition: define.cpp:373
std::vector< std::string > vArguments
Definition: define.hpp:50
FunctionDefinition(const std::string &_sDefinitionString="")
Constructor of the FunctionDefinition class. Creates a definition from the passed definition string.
Definition: define.cpp:37
bool convertToValues()
This private member function converts the selected of the passed variables into their values.
Definition: define.cpp:422
std::string getDefinition() const
This member function returns the definition of the function without the appended parameters.
Definition: define.cpp:278
bool appendComment(const std::string &_sComment)
This member function appends a comment, which might be set after the definition.
Definition: define.cpp:250
std::string sSignature
Definition: define.hpp:46
std::string sDefinitionString
Definition: define.hpp:47
std::string sName
Definition: define.hpp:45
FunctionDefinition & operator=(const FunctionDefinition &)
Assignment operator overload for the Function definition class.
Definition: define.cpp:54
bool importFunction(const std::string &_sExportedString)
This member function imports a previously exported definition string and distributes its contents alo...
Definition: define.cpp:195
std::string sComment
Definition: define.hpp:49
std::string parse(const std::string &_sArgList)
This member function parses the call to the contained function definition and returns a function defi...
Definition: define.cpp:77
bool decodeDefinition()
This private member function decodes the definition in the private member variable "sDefinitionString...
Definition: define.cpp:302
bool replaceArgumentOccurences()
This private member function replaces all occurences of the passed arguments with the corresponding n...
Definition: define.cpp:465
std::string exportFunction() const
This member function creates the save string used for writing to the definition file.
Definition: define.cpp:173
std::string sParsedDefinitionString
Definition: define.hpp:48
This class implements the function definition managing instance.
Definition: define.hpp:74
std::string getFunctionSignature(size_t _i) const
Returns the function signature of the ith defined custom function.
Definition: define.cpp:983
bool reset()
This member function resets the FunctionDefinitionManager object to a state before any function was d...
Definition: define.cpp:1040
std::string getDefinitionString(size_t _i) const
Returns the definition string of the ith defined custom function.
Definition: define.cpp:964
std::string sCommands
Definition: define.hpp:80
bool defineFunc(const std::string &sExpr, bool bRedefine=false, bool bFallback=false)
This function defines a custom function, by passing it to a new FunctionDefinition class instance.
Definition: define.cpp:655
void setPredefinedFuncs(const std::string &sPredefined)
This member function updates the internal list of predefined functions. If the list is whitespace-sep...
Definition: define.cpp:1158
bool undefineFunc(const std::string &sFunc)
This function removes a previously defined function from the internal memory.
Definition: define.cpp:772
std::string getComment(size_t _i) const
Returns the comment of the ith defined function.
Definition: define.cpp:1021
std::string resolveRecursiveDefinitions(std::string sDefinition)
This private member function resolves recursive definitions, which are handled by replacing the occur...
Definition: define.cpp:545
bool call(std::string &sExpr, int nRecursion=0)
This function searches for known custom definitions in the passed expression and replaces them with t...
Definition: define.cpp:801
std::map< std::string, FunctionDefinition >::const_iterator findItemById(size_t id) const
This private member function returns the iterator to the function pointed by the passed ID.
Definition: define.cpp:590
bool isDefined(const std::string &sFunc)
This method checks, whether the passed function is already defined.
Definition: define.cpp:625
FunctionDefinitionManager(bool _isLocal)
Default constructor of the FunctionDefinitionManager class. Prepares the list of protected command st...
Definition: define.cpp:507
bool load(const Settings &_option, bool bAutoLoad=false)
This function loads previously saved function definitions to memory.
Definition: define.cpp:1104
std::map< std::string, FunctionDefinition > mFunctionsMap
Definition: define.hpp:76
std::string sFileName
Definition: define.hpp:77
bool save(const Settings &_option)
This function saves the function definitions to the definition file.
Definition: define.cpp:1056
std::string sBuilt_In
Definition: define.hpp:79
std::string getImplementation(size_t _i) const
Returns the implementation of the ith defined custom function.
Definition: define.cpp:1002
size_t getDefinedFunctions() const
Returns the number of defined functions.
Definition: define.cpp:950
std::string get(const std::string &sMessage, const std::vector< std::string > &vTokens) const
This member function returns the language string for the passed language identifier and replaces all ...
Definition: language.cpp:292
static NumeReKernel * getInstance()
This static member function returns a a pointer to the singleton instance of the kernel.
Definition: kernel.hpp:221
static void printPreFmt(const std::string &__sLine, bool printingEnabled=true)
This member function appends the pre- formatted string to the buffer and informs the terminal that we...
Definition: kernel.cpp:2683
mu::Parser & getParser()
Definition: kernel.hpp:281
static void print(const std::string &__sLine, bool printingEnabled=true)
This member function appends the passed string as a new output line to the buffer and informs the ter...
Definition: kernel.cpp:2636
void refreshFunctionTree()
This member function informs the GUI to reload the contents of the function tree as soon as possible.
Definition: kernel.cpp:3573
Settings & getSettings()
Definition: kernel.hpp:296
This class manages the setting values of the internal (kernel) settings of this application.
Definition: settings.hpp:663
bool systemPrints() const
Returns, whether system messages shall be printed to the terminal.
Definition: settings.hpp:1140
size_t getPrecision() const
Returns the precision for displaying floating numbers in the terminal. This value determines the numb...
Definition: settings.hpp:1000
Common exception class for all exceptions thrown in NumeRe.
Definition: error.hpp:32
@ CACHE_ALREADY_EXISTS
Definition: error.hpp:45
@ FUNCTION_IS_PREDEFINED
Definition: error.hpp:111
@ NO_NUMBER_AT_POS_1
Definition: error.hpp:176
@ FUNCTION_ALREADY_EXISTS
Definition: error.hpp:107
@ TOO_MANY_FUNCTION_CALLS
Definition: error.hpp:220
@ ELLIPSIS_MUST_BE_LAST_ARG
Definition: error.hpp:97
@ TOO_MANY_ARGS_FOR_DEFINE
Definition: error.hpp:219
@ FUNCTION_NAMES_MUST_NOT_CONTAIN_SIGN
Definition: error.hpp:112
@ FUNCTION_STRING_IS_COMMAND
Definition: error.hpp:113
@ CANNOT_FIND_DEFINE_OPRT
Definition: error.hpp:62
@ FUNCTION_ARGS_MUST_NOT_CONTAIN_SIGN
Definition: error.hpp:108
@ UNMATCHED_PARENTHESIS
Definition: error.hpp:224
@ CANNOT_FIND_FUNCTION_ARGS
Definition: error.hpp:63
static size_t invalid_position
Definition: error.hpp:235
void SetExpr(StringView a_sExpr)
Set the expression. Triggers first time calculation thus the creation of the bytecode and scanning of...
value_type Eval()
Single-value wrapper around the vectorized overload of this member function.
const varmap_type & GetUsedVar()
Return a map containing the used variables only.
Language _lang
Definition: kernel.cpp:39
std::string toSystemCodePage(std::string)
Converts an internal to an external string. Does nothing currently.
unsigned int getMatchingParenthesis(const StringView &)
Returns the position of the closing parenthesis.
Definition: tools.cpp:414
CONSTCD11 std::enable_if<!std::chrono::treat_as_floating_point< T >::value, T >::type trunc(T t) NOEXCEPT
Definition: date.h:1113
Namespace for mathematical applications.
Definition: muParser.cpp:53
std::map< string_type, value_type * > varmap_type
Type used for storing variables.
Definition: muParserDef.h:273
void StripSpaces(std::string &)
Removes leading and trailing white spaces and tabulator characters.
int findParameter(const std::string &sCmd, const std::string &sParam, const char cFollowing)
This function searches the passed parameter in the passed command string. If something is found,...
Definition: tools.cpp:113
std::string getNextArgument(std::string &sArgList, bool bCut)
Definition: tools.cpp:2294
std::string toString(int)
Converts an integer to a string without the Settings bloat.
string getArgAtPos(const string &sCmd, unsigned int nPos, int extraction)
Extracts a options value at the selected position and applies automatic parsing, if necessary.
Definition: tools.cpp:1598
bool isInQuotes(StringView sExpr, unsigned int nPos, bool bIgnoreVarParser)
Checks, whether the position in the passed expression is part of a string literal.
Definition: tools.cpp:1672
std::string LineBreak(std::string sOutput, const Settings &_option, bool bAllowDashBreaks, int nFirstIndent, int nIndent)
This function takes a string, splits it into multiple lines if it is too long and returns the result.
Definition: tools.cpp:2205
bool isMultiValue(const string &sExpr, bool bIgnoreClosingParenthesis)
Determines, if a string contains multiple comma-separated expressions.
Definition: tools.cpp:484
bool checkDelimiter(const string &sString, bool stringdelim)
Checks, whether the first and the last character in the passed string is a delimiter character.
Definition: tools.cpp:1982