NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
commandlineparser.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2021 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 "commandlineparser.hpp"
20#include "../kernel.hpp"
21#include "utils/tools.hpp" // For findCommand, extractCommandString and getMatchingParenthesis
22#include "maths/parser_functions.hpp" // For evaluateTargetOptionInCommand
23
24// Prototype needed for file name conversion
25std::string removeQuotationMarks(const std::string& sString);
26
27
28
39CommandLineParser::CommandLineParser(const std::string& sCommandLine, CommandLineParser::CommandSignature signature) : m_commandLine(sCommandLine)
40{
41 // Try to find any command
42 Match _mMatch = findCommand(sCommandLine);
43
44 // Parse the command line, if a command was found
45 if (_mMatch.sString.length())
46 {
47 m_cmd = _mMatch.sString;
48 m_returnValueStatement = sCommandLine.substr(0, _mMatch.nPos);
49
50 parse(extractCommandString(sCommandLine, _mMatch), signature);
51 }
52}
53
54
68CommandLineParser::CommandLineParser(const std::string& sCommandLine, const std::string& sCommand, CommandLineParser::CommandSignature signature) : m_commandLine(sCommandLine)
69{
70 // Try to find the specified command
71 Match _mMatch = findCommand(sCommandLine, sCommand);
72
73 // Parse the command line, if the command was found
74 if (_mMatch.sString.length())
75 {
76 m_cmd = _mMatch.sString;
77 m_returnValueStatement = sCommandLine.substr(0, _mMatch.nPos);
78
79 parse(extractCommandString(sCommandLine, _mMatch), signature);
80 }
81}
82
83
94void CommandLineParser::parse(const std::string& sCommandString, CommandLineParser::CommandSignature signature)
95{
96 switch (signature)
97 {
98 // Command-parameter sequence
99 case CMD_PAR:
100 m_parlist = sCommandString.substr(sCommandString.find('-'));
101 break;
102
103 // Command-dataobject-parameter sequence
104 case CMD_DAT_PAR:
105 {
106 m_expr = sCommandString.substr(m_cmd.length()+1);
108
109 size_t nQuotes = 0;
110
111 for (size_t i = 0; i < m_expr.length(); i++)
112 {
113 if (m_expr[i] == '"' && (!i || m_expr[i-1] != '\\'))
114 {
115 nQuotes++;
116 continue;
117 }
118
119 if (!(nQuotes % 2))
120 {
121 // Handle parentheses
122 if (m_expr[i] == '(' || m_expr[i] == '{')
123 i += getMatchingParenthesis(m_expr.substr(i));
124
125 // Handle lists (will jump to the minus sign or
126 // a possible following expression part, if no list)
127 if ((m_expr[i] == ',' || m_expr[i] == ' ' || m_expr[i] == '+') && m_expr.find_first_not_of(",+ ", i) != std::string::npos)
128 i = m_expr.find_first_not_of(",+ ", i);
129
130 // If this is a quotation mark, increment the
131 // counter and continue
132 if (m_expr[i] == '"')
133 {
134 nQuotes++;
135 continue;
136 }
137
138 // Extract params
139 if (m_expr[i] == ' ' || m_expr[i] == '-')
140 {
141 m_parlist = m_expr.substr(m_expr.find('-', i));
142 m_expr.erase(i);
143 break;
144 }
145 }
146 }
147
148 break;
149 }
150 // Command-expression-set-parameter sequence
151 case CMD_EXPR_set_PAR:
152 {
153 m_expr = sCommandString.substr(m_cmd.length()+1);
155
156 size_t nQuotes = 0;
157
158 for (size_t i = 0; i < m_expr.length(); i++)
159 {
160 if (m_expr[i] == '"' && (!i || m_expr[i-1] != '\\'))
161 nQuotes++;
162
163 // Are we not in a string literal?
164 if (!(nQuotes % 2))
165 {
166 if (m_expr[i] == '(' || m_expr[i] == '{')
167 i += getMatchingParenthesis(m_expr.substr(i));
168
169 // Is this the start of the parameter list?
170 if (m_expr.substr(i, 2) == "--" || m_expr.substr(i, 5) == "-set ")
171 {
172 m_parlist = m_expr.substr(i);
173 m_expr.erase(i);
174
175 break;
176 }
177 }
178 }
179 }
180 }
181
182 // Strip obsolete spaces
185}
186
187
198std::string CommandLineParser::parseFileName(std::string& sFileName, std::string& sFileExt, const std::string& sBasePath) const
199{
200 FileSystem _fSys;
201 _fSys.initializeFromKernel();
202
203 if (sBasePath.length()
204 && sFileName.find("\\\\") == std::string::npos
205 && sFileName.find("//") == std::string::npos
206 && sFileName.find(':') == std::string::npos
207 && sFileName.find('<') == std::string::npos)
208 sFileName.insert(0, sBasePath + "/");
209
210 // If the filename contains a extension, extract it here and declare it as a valid file type
211 if (sFileName.find('.') != std::string::npos)
212 {
213 size_t nPos = sFileName.find_last_of("/\\");
214
215 if (sFileName.find('.', nPos) != std::string::npos)
216 sFileExt = sFileName.substr(sFileName.rfind('.'));
217 }
218
219 // There are some protected ones
220 if (sFileExt == ".exe" || sFileExt == ".dll" || sFileExt == ".sys")
221 {
223 }
224
225 if (!sFileExt.length())
226 return _fSys.ValidFolderName(sFileName);
227
228 // Declare the extension
229 _fSys.declareFileType(sFileExt);
230
231 // Get a valid file name
232 return _fSys.ValidFileName(sFileName, sFileExt);
233}
234
235
245void CommandLineParser::setReturnValue(const std::vector<mu::value_type>& vRetVal)
246{
248}
249
250
260void CommandLineParser::setReturnValue(const std::vector<std::string>& vRetVal)
261{
263}
264
265
274{
276}
277
278
290std::string CommandLineParser::getExprAsFileName(std::string sFileExt, const std::string& sBasePath) const
291{
292 // Make a copy
293 std::string sFileName = m_expr;
294
295 // Call functions first
296 if (!NumeReKernel::getInstance()->getDefinitions().call(sFileName))
298
299 if (NumeReKernel::getInstance()->getStringParser().containsStringVars(sFileName))
301
302 if (NumeReKernel::getInstance()->getMemoryManager().containsTablesOrClusters(sFileName))
303 getDataElements(sFileName, NumeReKernel::getInstance()->getParser(), NumeReKernel::getInstance()->getMemoryManager(), NumeReKernel::getInstance()->getSettings());
304
305 // Strip the spaces and ensure that there's something left
306 StripSpaces(sFileName);
307
308 if (!sFileName.length())
309 return "";
310
311 // If there's a string in the file name, parse it here
312 if (NumeReKernel::getInstance()->getStringParser().isStringExpression(sFileName))
313 {
314 std::string sDummy;
315 NumeReKernel::getInstance()->getStringParser().evalAndFormat(sFileName, sDummy, true);
316 }
317
318 sFileName = removeQuotationMarks(sFileName);
319
320 // Parse the prepared file path
321 return parseFileName(sFileName, sFileExt, sBasePath);
322}
323
324
335{
336 std::string sExpr = m_expr;
337
338 // Call functions first
339 if (!NumeReKernel::getInstance()->getDefinitions().call(sExpr))
341
342 if (sExpr.find("??") != std::string::npos)
343 sExpr = promptForUserInput(sExpr);
344
345 return DataAccessParser(sExpr);
346}
347
348
359std::string CommandLineParser::getExprAsMathExpression(bool parseDataObjects) const
360{
362 // Make a copy
363 std::string sExpr = m_expr;
364
365 // Call functions first
366 if (!instance->getDefinitions().call(sExpr))
368
369 if (sExpr.find("??") != std::string::npos)
370 sExpr = promptForUserInput(sExpr);
371
372 if (parseDataObjects && instance->getMemoryManager().containsTablesOrClusters(sExpr))
373 getDataElements(sExpr, instance->getParser(), instance->getMemoryManager(), instance->getSettings());
374
375 if (!instance->getMemoryManager().containsTablesOrClusters(sExpr) && sExpr.find('{') != std::string::npos)
376 convertVectorToExpression(sExpr, instance->getSettings());
377
378 StripSpaces(sExpr);
379
380 return sExpr;
381}
382
383
393{
395 // Make a copy
396 std::string sExpr = m_expr;
397
398 // Call functions first
399 if (!instance->getDefinitions().call(sExpr))
401
402 StripSpaces(sExpr);
403
404 if (sExpr.find("??") != std::string::npos)
405 sExpr = promptForUserInput(sExpr);
406
407 if (NumeReKernel::getInstance()->getStringParser().isStringExpression(sExpr))
408 {
409 sExpr += " -nq";
410 std::string sDummy;
412 return toInternalString(sExpr);
413 }
414
415 return sExpr;
416}
417
418
426std::vector<mu::value_type> CommandLineParser::parseExprAsNumericalValues() const
427{
429 // Make a copy
430 std::string sValue = m_expr;
431
432 // Call functions first
433 if (!instance->getDefinitions().call(sValue))
435
436 // Parse strings (if any)
437 if (instance->getStringParser().isStringExpression(sValue))
438 {
439 std::string sDummy = "";
440 instance->getStringParser().evalAndFormat(sValue, sDummy, true);
441 }
442
443 // Resolve table accesses
444 if (instance->getMemoryManager().containsTablesOrClusters(sValue))
445 getDataElements(sValue, instance->getParser(), instance->getMemoryManager(), instance->getSettings());
446
447 instance->getParser().SetExpr(sValue);
448 int nRes;
450
451 v = instance->getParser().Eval(nRes);
452
453 std::vector<mu::value_type> vVals(v, v+nRes);
454
455 return vVals;
456}
457
458
470{
471 return IntervalSet(m_parlist);
472}
473
474
486std::string CommandLineParser::getTargetTable(Indices& _targetIndices, const std::string& sDefaultTableName)
487{
489 return evaluateTargetOptionInCommand(m_parlist, sDefaultTableName, _targetIndices, instance->getParser(), instance->getMemoryManager(), instance->getSettings());
490}
491
492
502std::vector<std::string> CommandLineParser::getAllParametersWithValues() const
503{
504 size_t pos = 0;
505 std::vector<std::string> vParams;
506
507 while ((pos = m_parlist.find('=', pos)) != std::string::npos)
508 {
509 if (!isInQuotes(m_parlist, pos))
510 {
511 size_t lastChar = m_parlist.find_last_not_of(" =", pos);
512
513 if (lastChar)
514 {
515 size_t firstChar = m_parlist.find_last_of(" -", lastChar) + 1;
516 vParams.push_back(m_parlist.substr(firstChar, lastChar + 1 - firstChar));
517 }
518 }
519
520 pos++;
521 }
522
523 return vParams;
524}
525
526
536std::string CommandLineParser::getParameterValue(const std::string& sParameter) const
537{
538 int nParPos = findParameter(m_parlist, sParameter, '=');
539
540 if (!nParPos)
541 return "";
542
543 return getArgAtPos(m_parlist, nParPos+sParameter.length(), ARGEXTRACT_NONE);
544}
545
546
558std::string CommandLineParser::getFileParameterValue(std::string sFileExt, const std::string& sBaseFolder, const std::string& sDefaultName) const
559{
560 FileSystem _fSys;
561 _fSys.initializeFromKernel();
562
563 std::string sParams = m_parlist;
564
565 // Call functions first
566 if (!NumeReKernel::getInstance()->getDefinitions().call(sParams))
568
569 if (NumeReKernel::getInstance()->getStringParser().containsStringVars(sParams))
571
572 if (NumeReKernel::getInstance()->getMemoryManager().containsTablesOrClusters(sParams))
573 getDataElements(sParams, NumeReKernel::getInstance()->getParser(), NumeReKernel::getInstance()->getMemoryManager(), NumeReKernel::getInstance()->getSettings());
574
575 int nParPos = findParameter(sParams, "file", '=');
576
577 if (!nParPos && sDefaultName.length())
578 return _fSys.ValidFileName(removeQuotationMarks(sDefaultName), sFileExt);
579 else if (!nParPos)
580 return "";
581
582 std::string sFileName = getArgAtPos(sParams, nParPos+4, ARGEXTRACT_NONE);
584
585 // String evaluation
586 if (instance->getStringParser().isStringExpression(sFileName))
587 {
588 std::string dummy;
589 instance->getStringParser().evalAndFormat(sFileName, dummy, true);
590 }
591
592 sFileName = removeQuotationMarks(sFileName);
593
594 // If a filename had been found, parse it here
595 if (sFileName.length())
596 return parseFileName(sFileName, sFileExt, sBaseFolder);
597 else if (sDefaultName.length())
598 return _fSys.ValidFileName(removeQuotationMarks(sDefaultName), sFileExt);
599
600 return "";
601}
602
603
616std::string CommandLineParser::getFileParameterValueForSaving(std::string sFileExt, const std::string& sBaseFolder, const std::string& sDefaultName) const
617{
618 FileSystem _fSys;
619 _fSys.initializeFromKernel();
620
621 return _fSys.ValidizeAndPrepareName(getFileParameterValue(sFileExt, sBaseFolder, sDefaultName), sFileExt);
622}
623
624
637std::string CommandLineParser::getParameterValueAsString(const std::string& sParameter, const std::string& sDefaultValue, bool stripAlways, bool onlyStringEvaluation) const
638{
639 int nParPos = findParameter(m_parlist, sParameter, '=');
640
641 if (!nParPos)
642 return sDefaultValue;
643
644 std::string arg = getArgAtPos(m_parlist,
645 nParPos+sParameter.length(),
646 ARGEXTRACT_PARSED | (onlyStringEvaluation ? ARGEXTRACT_ASSTRING : ARGEXTRACT_NONE));
647 StripSpaces(arg);
648
649 if (!stripAlways && arg.find(",") != std::string::npos && arg.find("\"") != std::string::npos)
650 return arg;
651 else if (arg.front() == '"' && arg.back() == '"')
652 return removeQuotationMarks(arg);
653
654 return arg;
655}
656
657
668std::vector<mu::value_type> CommandLineParser::getParameterValueAsNumericalValue(const std::string& sParameter) const
669{
670 int nParPos = findParameter(m_parlist, sParameter, '=');
671
672 if (!nParPos)
673 return std::vector<mu::value_type>();
674
675 std::string arg = getArgAtPos(m_parlist, nParPos+sParameter.length(), ARGEXTRACT_PARSED | ARGEXTRACT_STRIPPED);
676 std::vector<mu::value_type> vArgs;
677
678 while (arg.length())
679 {
680 vArgs.push_back(StrToDb(getNextArgument(arg, true)));
681 }
682
683 return vArgs;
684}
685
686
695bool CommandLineParser::hasParam(const std::string& sParameter) const
696{
697 return findParameter(m_parlist, sParameter) != 0;
698}
699
700
701
std::vector< mu::value_type > parseExprAsNumericalValues() const
Parses the expression into numerical values, returned as a vector of doubles.
void parse(const std::string &sCommandString, CommandSignature signature)
Private helper member function used for parsing the command line as specified by the command line sig...
std::string m_returnValueStatement
DataAccessParser getExprAsDataObject() const
Parses the expression to a DataAccessParser, which will extract the needed information for the curren...
std::string getFileParameterValue(std::string sFileExt, const std::string &sBaseFolder="", const std::string &sDefaultName="") const
Parses the value of the common "file" command line parameter and returns a valid filename.
std::string getExprAsMathExpression(bool parseDataObjects=false) const
Prepares the expression by calling custom function definitions and resolving vector braces so that th...
std::vector< mu::value_type > getParameterValueAsNumericalValue(const std::string &sParameter) const
Parses the selected parameter as (one or more) numerical value(s) and returns them as a vector of dou...
std::string getParameterValueAsString(const std::string &sParameter, const std::string &sDefaultValue, bool stripAlways=false, bool onlyStringEvaluation=false) const
Parses the selected parameter value as a string and returns it. If the parameter is not found,...
std::string getFileParameterValueForSaving(std::string sFileExt, const std::string &sBaseFolder="", const std::string &sDefaultName="") const
Parses the value of the common "file" command line parameter and returns a valid filename....
std::string getTargetTable(Indices &_targetIndices, const std::string &sDefaultTableName)
Evaluates any target=TABLE() statements in the parameter list and returns the needed information....
void setReturnValue(const std::string &sRetVal)
Sets the return value of the current command by simply appending it to the return value statement.
std::string parseExprAsString() const
Prepares the expression by handling all string operations and removing the surrounding quotation mark...
std::string getParameterValue(const std::string &sParameter) const
Simply returns the parameter value or an empty string. Does not do any parsing steps.
@ CMD_PAR
Command-parameter sequence.
@ CMD_DAT_PAR
Command-dataobject-parameter sequence (e.g. fit)
@ CMD_EXPR_set_PAR
Command-expression-set-parameter sequence.
std::vector< std::string > getAllParametersWithValues() const
Returns a vector containing all parameters with values in the current parameter list....
CommandLineParser(const std::string &sCommandLine, CommandSignature signature)
CommandLineParser constructor from a command line and the command signature. Will use the standard fi...
std::string parseFileName(std::string &sFileName, std::string &sFileExt, const std::string &sBasePath) const
Common method to convert a prepared string into a valid file or folder name.
std::string getExprAsFileName(std::string sFileExt, const std::string &sBasePath="") const
Converts the expression to a file name and removes the surrounding quotation marks,...
bool exprContainsDataObjects() const
Simply returns, whether the expression contains any data objects.
IntervalSet parseIntervals(bool bErase=false)
Parses intervals in the parameter list and returns them as a vector. The interval may be deleted,...
bool hasParam(const std::string &sParameter) const
Simple wrapper around findParameter(), if used as a boolean flag.
This class is defined to abstrahize the determination of the correct data object and the calculation ...
Definition: dataaccess.hpp:38
This class implements the basic input/ output file system and provides functionalities to work with f...
Definition: filesystem.hpp:92
std::string ValidFolderName(std::string _sFileName, bool doCleanPath=true, bool appendTrailingSeparator=true) const
This member function evaluates, whether the passed foldername is a valid foldername.
Definition: filesystem.cpp:369
std::string ValidizeAndPrepareName(const std::string &_sFileName, const std::string &sExtension=".dat") const
This member function validizes the passed file name and creates the needed folders on-the-fly.
Definition: filesystem.cpp:424
void initializeFromKernel()
Member function to remote-initialize the class from the kernel. Cannot be used during kernel start-up...
Definition: filesystem.cpp:750
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
void declareFileType(const std::string &sFileType)
Definition: filesystem.hpp:132
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
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...
std::string createTempStringVectorVar(const std::vector< std::string > &vStringVector)
This member function is used to create a temporary string vector variable.
This class provides the interface to the core of NumeRe. It provides all functionalities,...
Definition: kernel.hpp:97
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
Common exception class for all exceptions thrown in NumeRe.
Definition: error.hpp:32
@ FUNCTION_ERROR
Definition: error.hpp:110
@ FILETYPE_MAY_NOT_BE_WRITTEN
Definition: error.hpp:103
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.
string_type CreateTempVectorVar(const std::vector< mu::value_type > &vVar)
This member function copies the passed vector into the internal storage referencing it with a auto-ge...
std::string removeQuotationMarks(const std::string &sString)
This function simply removes the surrounding quotation marks.
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
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:251
string promptForUserInput(const string &__sCommand)
This function is invoked, if a prompt operator ("??") was found in a string.
string evaluateTargetOptionInCommand(string &sCmd, const string &sDefaultTarget, Indices &_idx, Parser &_parser, MemoryManager &_data, const Settings &_option)
This function evaluates the "target=TABLE()" expression and creates the target table,...
void convertVectorToExpression(string &sLine, const Settings &_option)
This function replaces vector expressions with their corresponding multi- expression equation.
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 toInternalString(std::string sStr)
Converts a string literal to the internal representation in tables and clusters.
double StrToDb(const std::string &sString)
Converts a string into a double.
std::string getNextArgument(std::string &sArgList, bool bCut)
Definition: tools.cpp:2294
This structure is central for managing the indices of a table or cluster read or write data access....
This class represents a set of intervals used together for calculations and simulations.
Definition: interval.hpp:84
Structure for the findCommand function.
unsigned int nPos
std::string sString
Match findCommand(StringView sCmd, const std::string &sCommand)
This function is very important for the command handler.
Definition: tools.cpp:1275
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
string extractCommandString(const string &sCmd, const Match &_mMatch)
Extracts the whole command string from a command line (which might contain more than one).
Definition: tools.cpp:1325
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
@ ARGEXTRACT_STRIPPED
Definition: tools.hpp:56
@ ARGEXTRACT_PARSED
Definition: tools.hpp:57
@ ARGEXTRACT_ASSTRING
Definition: tools.hpp:59
@ ARGEXTRACT_NONE
Definition: tools.hpp:55