NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
built-in.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
20#include "built-in.hpp"
21#include "../kernel.hpp"
22#include "io/fileops.hpp"
24#include "commandfunctions.hpp"
25
26
43{
44 // Get the command functions as static maps
45 static map<string,CommandFunc> mCommandsWithReturnValue = getCommandFunctionsWithReturnValues();
46 static map<string,CommandFunc> mCommands = getCommandFunctions();
47
48 StripSpaces(sCmd);
49 sCmd += " ";
50 string sCommand = findCommand(sCmd).sString;
51
52 // Keyword search and application documentation
53 // are most important and will evaluated first
54 if (sCommand == "find" || sCommand == "search")
55 return cmd_find(sCmd);
56 else if (sCommand == "help" || sCommand == "man" || sCommand == "doc")
57 return cmd_help(sCmd);
58
59 // Try to find any of the commands with a
60 // return value. These have to be searched
61 // in the command string, because they are
62 // most probably not the first command
63 // candidate.
64 for (auto iter = mCommandsWithReturnValue.begin(); iter != mCommandsWithReturnValue.end(); ++iter)
65 {
66 if (findCommand(sCmd, iter->first).sString == iter->first)
67 return iter->second(sCmd);
68 }
69
70 // Search the command in the list of usual
71 // commands
72 auto iter = mCommands.find(sCommand);
73
74 if (iter != mCommands.end())
75 return iter->second(sCmd);
76
77 // Now chek for the too generic "get"
78 if (findCommand(sCmd, "get").sString == "get")
79 return cmd_get(sCmd);
80
81 // No command found
82 return NO_COMMAND;
83}
84
85
98bool extractFirstParameterStringValue(const string& sCmd, string& sArgument)
99{
100 // Don't do anything, if no string is found in this expression
101 if (!NumeReKernel::getInstance()->getStringParser().isStringExpression(sCmd))
102 return false;
103
107
108 string sTemp = sCmd;
109
110 // Get the contents of the contained data tables
111 if (_data.containsTablesOrClusters(sTemp))
112 getDataElements(sTemp, _parser, _data, _option);
113
114 //
115 for (unsigned int i = 0; i < sTemp.length(); i++)
116 {
117 // Jump over this parenthesis, if its contents don't contain
118 // strings or string variables
119 if (sTemp[i] == '('
120 && !NumeReKernel::getInstance()->getStringParser().isStringExpression(sTemp.substr(i, getMatchingParenthesis(sTemp.substr(i))))
122 i += getMatchingParenthesis(sTemp.substr(i));
123
124 // Evaluate parameter starts, i.e. the minus sign of the command line
125 if (sTemp[i] == '-' && !NumeReKernel::getInstance()->getStringParser().isStringExpression(sTemp.substr(0, i)))
126 {
127 // No string left of the minus sign, erase this part
128 // and break the loop
129 sTemp.erase(0, i);
130 break;
131 }
132 else if (sTemp[i] == '-' && NumeReKernel::getInstance()->getStringParser().isStringExpression(sTemp.substr(0, i)))
133 {
134 // There are strings left of the minus sign
135 // Find now the last string element in this part of the expression
136 for (int j = (int)i; j >= 0; j--)
137 {
138 // Find the start of this function or data element, which
139 // ends at this character
140 if (sTemp[j] == '(' && j && (isalnum(sTemp[j - 1]) || sTemp[j - 1] == '_'))
141 {
142 while (j && (isalnum(sTemp[j - 1]) || sTemp[j - 1] == '_'))
143 j--;
144 }
145
146 // This is now the location, where all string-related stuff is
147 // to the right and everything else is to the left
148 if (!NumeReKernel::getInstance()->getStringParser().isStringExpression(sTemp.substr(0, j)) && NumeReKernel::getInstance()->getStringParser().isStringExpression(sTemp.substr(j, i - j)))
149 {
150 // Erase the left part and break the loop
151 sTemp.erase(0, j);
152 break;
153 }
154 }
155
156 break;
157 }
158 }
159
160 // If there are no strings, sTemp will be empty
161 if (!sTemp.length())
162 return false;
163
164 // Get the string variable values
165 if (NumeReKernel::getInstance()->getStringParser().containsStringVars(sTemp))
167
168 // Get now the string argument, which may contain pure
169 // strings, string functions and concatenations
170 if (!getStringArgument(sTemp, sArgument))
171 return false;
172
173 // If there are path tokens in the string part, ensure that
174 // they are valid. Additionally, replace the "<this>" path token
175 if (sArgument.find('<') != string::npos && sArgument.find('>', sArgument.find('<')) != string::npos)
176 {
177 for (unsigned int i = 0; i < sArgument.length(); i++)
178 {
179 if (sArgument.find('<', i) == string::npos)
180 break;
181
182 if (sArgument[i] == '<' && sArgument.find('>', i) != string::npos)
183 {
184 string sToken = sArgument.substr(i, sArgument.find('>', i) + 1 - i);
185
186 if (sToken == "<this>")
187 sToken = _option.getExePath();
188
189 if (sToken.find('/') == string::npos)
190 {
191 // Is the token valid?
192 if (_option.getTokenPaths().find(sToken) == string::npos)
193 throw SyntaxError(SyntaxError::UNKNOWN_PATH_TOKEN, sCmd, sToken, sToken);
194 }
195
196 i = sArgument.find('>', i);
197 }
198 }
199 }
200
201 // Clear the temporary variable
202 sTemp.clear();
203
204 // Parse the string expression
205 NumeReKernel::getInstance()->getStringParser().evalAndFormat(sArgument, sTemp, true);
206 sArgument = sArgument.substr(1, sArgument.length() - 2);
207 return true;
208}
209
210
221string evaluateParameterValues(const string& sCmd)
222{
227
228 string sReturn = sCmd;
229 string sTemp = "";
230 string sDummy = "";
231 unsigned int nPos = 0;
232 unsigned int nLength = 0;
233 vector<double> vInterval;
234
235 // Add a whitespace character at the end
236 if (sReturn.back() != ' ')
237 sReturn += " ";
238
239 // Try to detect the interval syntax
240 if (sReturn.find('-') != string::npos
241 && (sReturn.find('[') != string::npos
242 || findParameter(sReturn, "x", '=')
243 || findParameter(sReturn, "y", '=')
244 || findParameter(sReturn, "z", '=')))
245 {
246 // Get the parameter part of the string and remove
247 // the parameter string part from the original expression
248 if (sReturn.find("-set") != string::npos)
249 {
250 sTemp = sReturn.substr(sReturn.find("-set"));
251 sReturn.erase(sReturn.find("-set"));
252 }
253 else if (sReturn.find("--") != string::npos)
254 {
255 sTemp = sReturn.substr(sReturn.find("--"));
256 sReturn.erase(sReturn.find("--"));
257 }
258 else
259 {
260 sTemp = sReturn.substr(sReturn.find('-'));
261 sReturn.erase(sReturn.find("-"));
262 }
263
264 // Parse the interval syntax
265 vInterval = readAndParseIntervals(sTemp, _parser, _data, _functions, _option, true);
266
267 // Append the remaining part of the parameter string to the expression
268 sReturn += sTemp;
269 }
270
271 // Get the string var values, if any
272 if (NumeReKernel::getInstance()->getStringParser().containsStringVars(sReturn))
274
275 // Repeat as long as an equal sign is found after
276 // the current position in the command line
277 while (sReturn.find('=', nPos) != string::npos)
278 {
279 // Get the position after the equal sign
280 nPos = sReturn.find('=', nPos) + 1;
281
282 // Ignore equal signs in strings
283 if (isInQuotes(sReturn, nPos))
284 {
285 nPos++;
286 continue;
287 }
288
289 // jump over whitespaces
290 while (nPos < sReturn.length() - 1 && sReturn[nPos] == ' ')
291 nPos++;
292
293 // Parse the parameter values into evaluated values for the commands
294 if (NumeReKernel::getInstance()->getStringParser().isStringExpression(sReturn.substr(nPos, sReturn.find(' ', nPos) - nPos)))
295 {
296 // This is a string value
297 if (!getStringArgument(sReturn.substr(nPos - 1), sTemp)) // mit "=" uebergeben => fixes getStringArgument issues
298 return "";
299
300 // Get the current length of the string
301 nLength = sTemp.length();
302 sTemp += " -kmq";
303
304 // Parse the string
306
307 // Replace the parsed string
308 sReturn.replace(nPos, nLength, sTemp);
309 }
310 else if ((nPos > 5 && sReturn.substr(nPos - 5, 5) == "save=")
311 || (nPos > 7 && sReturn.substr(nPos - 7, 7) == "export="))
312 {
313 // This is a path value without quotation marks
314 // (otherwise it would be catched by the previous block)
315 sTemp = sReturn.substr(nPos, sReturn.find(' ', nPos) - nPos);
316 nLength = sTemp.length();
317
318 // Add quotation marks and replace the prvious path definition
319 sTemp = "\"" + sTemp + "\"";
320 sReturn.replace(nPos, nLength, sTemp);
321 }
322 else if ((nPos > 8 && sReturn.substr(nPos - 8, 8) == "tocache=")
323 || (nPos > 8 && sReturn.substr(nPos - 8, 8) == "totable=")
324 || (nPos > 5 && sReturn.substr(nPos - 5, 5) == "type=")
325 || (nPos > 5 && sReturn.substr(nPos - 5, 5) == "icon=")
326 || (nPos > 7 && sReturn.substr(nPos - 7, 7) == "method=")
327 || (nPos > 7 && sReturn.substr(nPos - 7, 7) == "target=")
328 || (nPos > 8 && sReturn.substr(nPos - 8, 8) == "buttons="))
329 {
330 // do nothing here
331 nPos++;
332 }
333 else
334 {
335 // All other cases, i.e. numerical values
336 // evaluate the value correspondingly
337
338 // Get the value and its length
339 sTemp = sReturn.substr(nPos, sReturn.find(' ', nPos) - nPos);
340 nLength = sTemp.length();
341
342 // Call functions
343 if (!_functions.call(sTemp))
344 return "";
345
346 // Get data elements
347 if (_data.containsTablesOrClusters(sTemp))
348 getDataElements(sTemp, _parser, _data, _option);
349
350 int nResult = 0;
351 mu::value_type* v = nullptr;
352
353 // If the string contains a colon operator,
354 // replace it with a comma
355 if (sTemp.find(':') != string::npos)
356 {
357 string sTemp_2 = sTemp;
358 sTemp = getNextIndex(sTemp_2, true);
359 sTemp += ", " + sTemp_2;
360 }
361
362 // Set the expression and evaluate it numerically
363 _parser.SetExpr(sTemp);
364 v = _parser.Eval(nResult);
365
366 // Clear the temporary variable
367 sTemp.clear();
368
369 // convert the doubles into strings and remove the trailing comma
370 for (int i = 0; i < nResult; i++)
371 sTemp += toString(v[i], _option.getPrecision()) + ":";
372
373 sTemp.pop_back();
374
375 // Replace the string
376 sReturn.replace(nPos, nLength, sTemp);
377 }
378
379 }
380
381 // Convert the calculated intervals into their string definitions
382 if (vInterval.size())
383 {
384 // x interval
385 if (vInterval.size() >= 2)
386 {
387 if (!isnan(vInterval[0]) && !isnan(vInterval[1]))
388 sReturn += " -x=" + toCmdString(vInterval[0]) + ":" + toCmdString(vInterval[1]);
389 }
390
391 // y interval
392 if (vInterval.size() >= 4)
393 {
394 if (!isnan(vInterval[2]) && !isnan(vInterval[3]))
395 sReturn += " -y=" + toCmdString(vInterval[2]) + ":" + toCmdString(vInterval[3]);
396 }
397
398 // z interval
399 if (vInterval.size() >= 6)
400 {
401 if (!isnan(vInterval[4]) && !isnan(vInterval[5]))
402 sReturn += " -z=" + toCmdString(vInterval[4]) + ":" + toCmdString(vInterval[5]);
403 }
404 }
405
406 return sReturn;
407}
408
409
422bool parseCmdArg(const string& sCmd, size_t nPos, Parser& _parser, size_t& nArgument)
423{
424 if (!sCmd.length() || !nPos)
425 return false;
426
427 while (nPos < sCmd.length() - 1 && sCmd[nPos] == ' ')
428 nPos++;
429
430 if (sCmd[nPos] == ' ' || nPos >= sCmd.length() - 1)
431 return false;
432
433 string sArg = sCmd.substr(nPos);
434
435 if (sArg[0] == '(')
436 sArg = sArg.substr(1, getMatchingParenthesis(sArg) - 1);
437 else
438 sArg = sArg.substr(0, sArg.find(' '));
439
440 _parser.SetExpr(sArg);
441
442 if (isnan(_parser.Eval().real()) || isinf(_parser.Eval().real()))
443 return false;
444
445 nArgument = abs(intCast(_parser.Eval()));
446 return true;
447}
448
bool extractFirstParameterStringValue(const string &sCmd, string &sArgument)
This function returns the string argument for a single parameter in the command line.
Definition: built-in.cpp:98
bool parseCmdArg(const string &sCmd, size_t nPos, Parser &_parser, size_t &nArgument)
This function finds the numerical argument to the selected command line parameter and evaluates it.
Definition: built-in.cpp:422
string evaluateParameterValues(const string &sCmd)
This function evaluates a passed parameter string, so that the values of the parameters are only valu...
Definition: built-in.cpp:221
CommandReturnValues commandHandler(string &sCmd)
This function is the main command handling function.
Definition: built-in.cpp:42
CommandReturnValues
Definition: built-in.hpp:50
@ NO_COMMAND
Definition: built-in.hpp:52
This class implements the function definition managing instance.
Definition: define.hpp:74
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
This class represents the central memory managing instance. It will handle all tables and clusters,...
bool containsTablesOrClusters(const std::string &sCmdLine)
This member function evaluates, whether the passed command line contains tables or clusters.
virtual bool isStringExpression(const std::string &sExpression) override
Returns true, if the passed expression is an expression containing strings, string variables or strin...
StringParserRetVal evalAndFormat(std::string &sLine, std::string &sCache, bool bSilent=false, bool bCheckAssertions=false)
This public member function evaluates the passed string expression and formats the results for the co...
void getStringValues(std::string &sLine)
This public member function resolves all string variable occurences and replaces them with their valu...
static NumeReKernel * getInstance()
This static member function returns a a pointer to the singleton instance of the kernel.
Definition: kernel.hpp:221
NumeRe::StringParser & getStringParser()
Definition: kernel.hpp:286
mu::Parser & getParser()
Definition: kernel.hpp:281
MemoryManager & getMemoryManager()
Definition: kernel.hpp:263
FunctionDefinitionManager & getDefinitions()
Definition: kernel.hpp:291
Settings & getSettings()
Definition: kernel.hpp:296
This class manages the setting values of the internal (kernel) settings of this application.
Definition: settings.hpp:663
size_t getPrecision() const
Returns the precision for displaying floating numbers in the terminal. This value determines the numb...
Definition: settings.hpp:1000
std::string getTokenPaths() const
Returns a semicolon-separated list of the current defined path placeholders and their values.
Definition: settings.hpp:1122
std::string getExePath() const
Returns the current application root folder path.
Definition: settings.hpp:1010
Common exception class for all exceptions thrown in NumeRe.
Definition: error.hpp:32
@ UNKNOWN_PATH_TOKEN
INSERT HERE.
Definition: error.hpp:223
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.
Mathematical expressions parser.
Definition: muParser.h:51
static std::map< std::string, CommandFunc > getCommandFunctionsWithReturnValues()
This static function returns a map of commands with return values linked to their function implementa...
static CommandReturnValues cmd_find(string &sCmd)
This static function implements the "find" command.
static CommandReturnValues cmd_help(string &sCmd)
This static function implements the "help" command.
static std::map< std::string, CommandFunc > getCommandFunctions()
This static function returns a map of commands linked to their function implementation.
static CommandReturnValues cmd_get(string &sCmd)
This static function implements the "get" command.
string getDataElements(string &sLine, Parser &_parser, MemoryManager &_data, const Settings &_option, int options)
Searches the passed string for calls to any table or cluster and replaces them with internal vectors ...
Definition: dataaccess.cpp:276
unsigned int getMatchingParenthesis(const StringView &)
Returns the position of the closing parenthesis.
Definition: tools.cpp:414
CONSTCD11 std::chrono::duration< Rep, Period > abs(std::chrono::duration< Rep, Period > d)
Definition: date.h:1317
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:251
bool isnan(const value_type &v)
Definition: muParserDef.h:379
bool isinf(const value_type &v)
Definition: muParserDef.h:374
vector< double > readAndParseIntervals(string &sExpr, Parser &_parser, MemoryManager &_data, FunctionDefinitionManager &_functions, const Settings &_option, bool bEraseInterval)
This function will read the interval syntax in commands and return their values in a single vector.
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 toCmdString(double dNumber)
Converts a numerical value into a "full" precision string.
std::string sString
long long int intCast(const std::complex< double > &)
Casts the real part of the complex number to an integer and avoids rounding errors.
Definition: tools.cpp:1824
std::string toString(int)
Converts an integer to a string without the Settings bloat.
Match findCommand(StringView sCmd, const std::string &sCommand)
This function is very important for the command handler.
Definition: tools.cpp:1275
bool getStringArgument(const string &sCmd, string &sArgument)
This function searches for the first string value in the passed expression and writes that into sArgu...
Definition: tools.cpp:250
string getNextIndex(string &sArgList, bool bCut)
Definition: tools.cpp:2305
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