NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
stringparser.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2019 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 "stringparser.hpp"
20#include "stringfunctions.hpp"
21#include "stringexpression.hpp"
22#include <algorithm>
23
24#include "../utils/timer.hpp"
25#include "../structures.hpp"
26
27extern value_type vAns;
28
29std::string removeQuotationMarks(const std::string& sString);
30std::string addQuotationMarks(const std::string& sString);
31
32namespace NumeRe
33{
42 StringParser::StringParser(mu::Parser& parser, MemoryManager& data, Settings& option) : StringLogicParser(), StringFuncHandler(), _parser(parser), _data(data), _option(option)
43 {
45
46 m_mStringParams["noquotes"] = NO_QUOTES;
48 m_mStringParams["peek"] = PEEK;
49 m_mStringParams["print"] = NO_QUOTES | PEEK;
52 }
53
54
65 std::string StringParser::getDataForString(std::string sLine, size_t n_pos)
66 {
67 // We disable the caching here, because it is not supported for
68 // recursive evaluations
70
71 // Get the contents of "string()", "data()" and the other caches
72 size_t nEndPosition;
73
74 if (sLine.find_first_of("({") == std::string::npos)
75 return sLine;
76
77 // {str} = string(...)
78 while ((n_pos = findNextFunction("string(", sLine, n_pos, nEndPosition)) != std::string::npos)
79 {
80 // Check for arguments to parse and
81 // get the indices afterwards
82 Indices _idx = getIndices("string(" + parseStringsInIndices(getFunctionArgumentList("string(", sLine, n_pos, nEndPosition).to_string()) + ")", _parser, _data, _option);
83
84 // Pre-process the indices
85 if (_idx.col.isOpenEnd())
87
88 if (_idx.row.isOpenEnd())
89 _idx.row.setRange(0, _data.getStringElements(_idx.col.front())-1);
90
91 if (!_idx.col.isValid())
92 _idx.col.front() = 0;
93
94 // Handle multi-argument functions or return
95 // the stored strings directly
96 if (parser_CheckMultArgFunc(sLine.substr(0, n_pos), sLine.substr(nEndPosition + 1)))
97 {
98 std::string sLeft = sLine.substr(0, n_pos);
99 StripSpaces(sLeft);
100
101 if (sLeft.length() > 3 && sLeft.substr(sLeft.length() - 4) == "num(")
102 sLine = sLeft.substr(0, sLeft.length() - 4) + toString(_idx.row.size()) + sLine.substr(sLine.find(')', nEndPosition + 1) + 1);
103 else if (sLeft.length() > 3 && sLeft.substr(sLeft.length() - 4) == "max(")
104 sLine = sLeft.substr(0, sLeft.length() - 4) + "\"" + _data.maxString(_idx.row, _idx.col) + "\"" + sLine.substr(sLine.find(')', nEndPosition + 1) + 1);
105 else if (sLeft.length() > 3 && sLeft.substr(sLeft.length() - 4) == "min(")
106 sLine = sLeft.substr(0, sLeft.length() - 4) + "\"" + _data.minString(_idx.row, _idx.col) + "\"" + sLine.substr(sLine.find(')', nEndPosition + 1) + 1);
107 else if (sLeft.length() > 3 && sLeft.substr(sLeft.length() - 4) == "sum(")
108 sLine = sLeft.substr(0, sLeft.length() - 4) + "\"" + _data.sumString(_idx.row, _idx.col) + "\"" + sLine.substr(sLine.find(')', nEndPosition + 1) + 1);
109 }
110 else
111 {
112 // Create the string vector
113 if (_data.getStringElements(_idx.col.front()))
114 {
115 std::string sString = "";
116 std::vector<std::string> vStrings;
117
118 for (size_t i = 0; i < _idx.row.size(); i++)
119 {
120 vStrings.push_back("\"" + _data.readString((unsigned int)_idx.row[i], _idx.col.front()) + "\"");
121 }
122
123 sString = createStringVectorVar(vStrings);
124 sLine = sLine.substr(0, n_pos) + sString + sLine.substr(nEndPosition + 1);
125 }
126 else
127 sLine = sLine.substr(0, n_pos) + "\"\"" + sLine.substr(nEndPosition + 1);
128 }
129
130 n_pos++;
131 }
132
133 if (sLine.find_first_of("({") == std::string::npos)
134 return sLine;
135
136 // Replace calls to any table
137 for (auto iter = _data.getTableMap().begin(); iter != _data.getTableMap().end(); ++iter)
138 {
139 if (sLine.find('(') == std::string::npos)
140 break;
141
142 replaceDataOccurence(sLine, iter->first + "(");
143 }
144
145 if (sLine.find('{') == std::string::npos)
146 return sLine;
147
148 // Replace calls to any cluster
149 for (auto iter = _data.getClusterMap().begin(); iter != _data.getClusterMap().end(); ++iter)
150 {
151 if (sLine.find('{') == std::string::npos)
152 break;
153
154 replaceDataOccurence(sLine, iter->first + "{");
155 }
156
157 return sLine;
158 }
159
160
170 std::string StringParser::parseStringsInIndices(std::string sIndexExpression)
171 {
172 // Ensure that this is an expression,
173 // which actually contains strings
174 if (!isStringExpression(sIndexExpression))
175 return sIndexExpression;
176
177 std::string sParsedIndices;
178
179 // As long as the passed index expression
180 // still has a length
181 while (sIndexExpression.length())
182 {
183 // Get the next index pair and evaluate
184 // its strings
185 std::string sIndexPairs = getNextArgument(sIndexExpression, true);
186
187 // If the current set of indices is
188 // only the value parser, then ignore
189 // that it is a string functionality,
190 // because the user tries to access
191 // the headlines of a table
192 if (sIndexPairs == "#")
193 {
194 if (sParsedIndices.length())
195 sParsedIndices += ",#";
196 else
197 sParsedIndices = "#";
198
199 continue;
200 }
201
202 StringResult strRes = eval(sIndexPairs, "", false);
203
204 if (!strRes.vResult.size())
206
207 // Check, if the return values are
208 // only strings
209 if (strRes.bOnlyLogicals && strRes.vResult.size() > 1)
210 {
211 std::vector<mu::value_type> vIndices;
212
213 // Convert the strings to doubles
214 for (size_t i = 0; i < strRes.vResult.size(); i++)
215 vIndices.push_back(StrToDb(strRes.vResult[i].to_string()));
216
217 // Create a temporary vector
218 if (sParsedIndices.length())
219 sParsedIndices += ", " + _parser.CreateTempVectorVar(vIndices);
220 else
221 sParsedIndices = _parser.CreateTempVectorVar(vIndices);
222 }
223 else
224 {
225 if (sParsedIndices.length())
226 sParsedIndices += ", " + strRes.vResult[0].to_string();
227 else
228 sParsedIndices = strRes.vResult[0].to_string();
229 }
230 }
231
232 return sParsedIndices;
233 }
234
235
245 void StringParser::replaceDataOccurence(std::string& sLine, const std::string& sOccurence)
246 {
247 size_t nStartPosition = 0;
248 size_t nEndPosition;
249
250 // Find the next occurence
251 while ((nStartPosition = findNextFunction(sOccurence, sLine, nStartPosition, nEndPosition, true)) != std::string::npos)
252 {
253 size_t nStartPos = nStartPosition;
254 size_t nEndPos = nEndPosition;
255 // Handle multi-argument functions
256 if (parser_CheckMultArgFunc(sLine.substr(0, nStartPosition), sLine.substr(nEndPosition + 1)))
257 {
258 if (nStartPosition > 4 && sLine.substr(sLine.rfind('(', nStartPosition) - 4, 5) == "norm(")
259 nStartPos -= 5;
260 else
261 nStartPos -= 4;
262
263 nEndPos++;
264 }
265
266 std::string sData = sLine.substr(nStartPos, nEndPos - nStartPos + 1);
267
268 // Is the current data access a method?
269 if (sData.find("().") != std::string::npos)
270 {
271 if (containsStringVectorVars(sData))
272 {
273 bool temp;
274 std::vector<std::string> vRes = evaluateStringVectors(sData);
276 sData = vRes.front();
277 }
278
280 REPLACE_NAN | (nStartPos && (sLine[nStartPos-1] == '#' || sLine[nStartPos-1] == '~') ? INSERT_STRINGS : 0));
281 }
282 else
283 {
284 sData.replace(nStartPosition-nStartPos+sOccurence.length(),
285 nEndPosition-nStartPosition-sOccurence.length(),
286 parseStringsInIndices(getFunctionArgumentList(sOccurence, sLine, nStartPosition, nEndPosition).to_string()));
287
288 // Get the data and parse string expressions
289 replaceDataEntities(sData, sOccurence, _data, _parser, _option,
290 REPLACE_NAN | (nStartPos && (sLine[nStartPos-1] == '#' || sLine[nStartPos-1] == '~') ? INSERT_STRINGS : 0));
291 }
292
293 // Strip the spaces, which have been added during the
294 // calls to the data entities
295 StripSpaces(sData);
296
297 // NOTE: Explicit parsing of the result is not necessary any more,
298 // because replaceDataEntities will either return vectors or
299 // plain strings or numerical values!
300 //
301 //StringResult strRes = eval(sData, "");
302 //if (!strRes.vResult.size())
303 // throw SyntaxError(SyntaxError::STRING_ERROR, sLine, SyntaxError::invalid_position);
304 //
308 //if (!strRes.bOnlyLogicals)
309 // sData = createStringVectorVar(strRes.vResult);
310 //else
311 // sData = strRes.vResult.front();
312
313 sLine = sLine.substr(0, nStartPos) + sData + sLine.substr(nEndPos + 1);
314
315 nStartPosition = nStartPos+1;
316 }
317
318 }
319
320
330 std::string StringParser::numToString(const std::string& sLine)
331 {
332 // Do nothing, if there's no #
333 if (sLine.find('#') == std::string::npos)
334 return sLine + " ";
335
336 // Create a copy of the current line
337 std::string sLineToParsed = sLine + " ";
338 std::string sLineToParsedTemp;
339
340 unsigned int nPos = 0;
341 unsigned int n_pos = 0;
342
343 // As long as there are further "#"
344 while (sLineToParsed.find('#', nPos) != std::string::npos)
345 {
346 // Store its position
347 nPos = sLineToParsed.find('#', nPos);
348
349 // Ensure that it is not in a string
350 if (!isInQuotes(sLineToParsed, nPos, true))
351 {
352 std::string sPrefix = "";
353 sLineToParsedTemp += sLineToParsed.substr(0, nPos);
354 sLineToParsed = sLineToParsed.substr(nPos + 1);
355
356 // If the variable starts with a tilde, it's possible that we
357 // need to prepend zeros. Get the prefix here
358 if (sLineToParsed[0] == '~')
359 {
360 for (unsigned int i = 0; i < sLineToParsed.length(); i++)
361 {
362 if (sLineToParsed[i] != '~')
363 {
364 sPrefix = sLineToParsed.substr(0, i);
365 sLineToParsed = sLineToParsed.substr(i);
366 break;
367 }
368 }
369 }
370
371 // Jump over simple signs
372 if (sLineToParsed[0] == '-' || sLineToParsed[0] == '+')
373 n_pos = 1;
374 else
375 n_pos = 0;
376
377 // Handle enclosing characters: parentheses, quotation marks
378 // angle brackets, ...
379 if (sLineToParsed[0] == '(' || sLineToParsed[0] == '{')
380 {
381 // Get the contents of the current parenthesis
382 std::string sExpr = sLineToParsed.substr(1, getMatchingParenthesis(sLineToParsed) - 1);
383
384 // Does it contain strings?
385 if (isStringExpression(sExpr))
386 {
387 StringResult strRes = eval(sExpr, "");
388 if (!strRes.vResult.size())
390
391 // Examine, whether the return value is logical only
392 if (!strRes.bOnlyLogicals)
393 {
394 // This case contains strings. We will cast the whole
395 // result into a string
396 for (size_t i = 0; i < strRes.vResult.size(); i++)
397 {
398 strRes.vResult.convert_to_string(i, sPrefix.length());
399 }
400
401 // Create a vector variable from the return value
402 sExpr = createStringVectorVar(strRes.vResult);
403 sLineToParsedTemp += sExpr;
404
405 // Get the next part of the command line
406 if (getPositionOfFirstDelimiter(sLineToParsed.substr(n_pos)) < sLineToParsed.length())
407 sLineToParsed = sLineToParsed.substr(getPositionOfFirstDelimiter(sLineToParsed.substr(n_pos)));
408 else
409 sLineToParsed.clear();
410
411 nPos = 0;
412 continue;
413 }
414
415 // This code section is reached, if the return value
416 // is logical only. We will construct a multi-value
417 // expression and evaluate it numerically
418 sExpr.clear();
419
420 // Construct the expression and remove the trailing comma
421 for (size_t i = 0; i < strRes.vResult.size(); i++)
422 {
423 sExpr += strRes.vResult[i] + ",";
424 }
425 sExpr.pop_back();
426
427 }
428
429 // Set the expression
430 _parser.SetExpr(sExpr);
431 }
432 else if (sLineToParsed[0] == '"')
433 {
434 // Get the contents of the current string
435 std::string sExpr = sLineToParsed.substr(1, sLineToParsed.find('"', 1) - 1);
436
437 // Add the zeros, if needed
438 while (sExpr.length() < sPrefix.length() + 2)
439 sExpr.insert(0, 1, '0');
440
441 // Store the result and continue
442 sLineToParsedTemp += "\"" + sExpr + "\"";
443 if (sLineToParsed.find('"', 1) < sLineToParsed.length() - 1)
444 sLineToParsed = sLineToParsed.substr(sLineToParsed.find('"', 1) + 1);
445 else
446 sLineToParsed.clear();
447 nPos = 0;
448 continue;
449 }
450 else if (sLineToParsed[0] == '<')
451 {
452 // Does the current object contain a path token?
453 if (sLineToParsed.find("<>") == 0
454 || sLineToParsed.find("<this>") == 0
455 || sLineToParsed.find("<wp>") == 0
456 || sLineToParsed.find("<loadpath>") == 0
457 || sLineToParsed.find("<savepath>") == 0
458 || sLineToParsed.find("<plotpath>") == 0
459 || sLineToParsed.find("<procpath>") == 0
460 || sLineToParsed.find("<scriptpath>") == 0)
461 {
462 // Replace the path tokens
463 if (sLineToParsed.find("<>") == 0 || sLineToParsed.find("<this>") == 0)
464 sLineToParsedTemp += "\"" + replacePathSeparator(_option.getExePath()) + "\"";
465 else if (sLineToParsed.find("<wp>") == 0)
466 sLineToParsedTemp += "\"" + replacePathSeparator(_option.getWorkPath()) + "\"";
467 else if (sLineToParsed.find("<loadpath>") == 0)
468 sLineToParsedTemp += "\"" + replacePathSeparator(_option.getLoadPath()) + "\"";
469 else if (sLineToParsed.find("<savepath>") == 0)
470 sLineToParsedTemp += "\"" + replacePathSeparator(_option.getSavePath()) + "\"";
471 else if (sLineToParsed.find("<plotpath>") == 0)
472 sLineToParsedTemp += "\"" + replacePathSeparator(_option.getPlotPath()) + "\"";
473 else if (sLineToParsed.find("<procpath>") == 0)
474 sLineToParsedTemp += "\"" + replacePathSeparator(_option.getProcPath()) + "\"";
475 else
476 sLineToParsedTemp += "\"" + replacePathSeparator(_option.getScriptPath()) + "\"";
477 sLineToParsed = sLineToParsed.substr(sLineToParsed.find('>') + 1);
478 }
479 else if (sLineToParsed.find('>') != std::string::npos)
480 {
481 // If no path token, only use the part in between of the angle brackets
482 sLineToParsedTemp += "\"" + sLineToParsed.substr(1, sLineToParsed.find('>') - 1) + "\"";
483 sLineToParsed = sLineToParsed.substr(sLineToParsed.find('>') + 1);
484 }
485 else
486 {
487 // Throw an error
489 }
490 nPos = 0;
491 continue;
492 }
493 else if (containsStringVectorVars(sLineToParsed.substr(0, getPositionOfFirstDelimiter(sLineToParsed.substr(n_pos)))))
494 {
495 // Here are string vector variables
496 std::string sExpr = sLineToParsed.substr(0, getPositionOfFirstDelimiter(sLineToParsed.substr(n_pos)));
497
498 // Parse the current line
499 StringResult strRes = eval(sExpr, "");
500
501 // Ensure that the result exists
502 if (!strRes.vResult.size())
504
505 // Add the needed quotation marks
506 for (size_t i = 0; i < strRes.vResult.size(); i++)
507 {
508 strRes.vResult.convert_to_string(i, sPrefix.length());
509 }
510
511 // Create a new string vector var, append it to the string and continue
512 sExpr = createStringVectorVar(strRes.vResult);
513 sLineToParsedTemp += sExpr;
514
515 if (getPositionOfFirstDelimiter(sLineToParsed.substr(n_pos)) < sLineToParsed.length())
516 sLineToParsed = sLineToParsed.substr(getPositionOfFirstDelimiter(sLineToParsed.substr(n_pos)));
517 else
518 sLineToParsed.clear();
519
520 continue;
521 }
522 else // Set the expression
523 _parser.SetExpr(sLineToParsed.substr(0, getPositionOfFirstDelimiter(sLineToParsed.substr(n_pos))));
524
525 int nResults = 0;
526 mu::value_type* v = 0;
527 std::vector<std::string> vResults;
528 std::string sElement = "";
529
530 // Evaluate the parsed expression
531 v = _parser.Eval(nResults);
532
533 // Convert all results into strings
534 for (int n = 0; n < nResults; n++)
535 {
536 sElement = printValue(v[n]);
537
538 while (sElement.length() < sPrefix.length() + 1)
539 sElement.insert(0, 1, '0');
540
541 vResults.push_back(addQuotationMarks(sElement));
542 }
543
544 // Create a string vector var from the results and append it to
545 // the current line
546 sElement = createStringVectorVar(vResults);
547 sLineToParsedTemp += sElement;
548
549 // Search for the next delimiter
550 if (getPositionOfFirstDelimiter(sLineToParsed.substr(n_pos)) < sLineToParsed.length())
551 sLineToParsed = sLineToParsed.substr(getPositionOfFirstDelimiter(sLineToParsed.substr(n_pos)));
552 else
553 sLineToParsed.clear();
554
555 nPos = 0;
556 }
557 else
558 nPos++;
559 }
560
561 // Append the remaining parts of the current expression
562 if (sLineToParsed.length() && sLineToParsedTemp.length())
563 sLineToParsedTemp += sLineToParsed;
564
565 // Handle remaining vector braces
566 if (sLineToParsedTemp.find('{') != std::string::npos)
567 {
568 convertVectorToExpression(sLineToParsedTemp, _option);
569 }
570
571 // Determine the return value
572 if (sLineToParsedTemp.length())
573 sLineToParsed = sLineToParsedTemp;
574 else
575 sLineToParsed = sLine;
576
577 return sLineToParsed;
578 }
579
580
593 void StringParser::storeStringToDataObjects(StringResult& strRes, std::string& sObject, size_t& nCurrentComponent, size_t nStrings)
594 {
595 // Identify the correct table
596 DataAccessParser _accessParser(sObject);
597
598 if (!_accessParser.getDataObject().length())
599 return;
600
601 std::string sTableName = _accessParser.getDataObject();
602 Indices& _idx = _accessParser.getIndices();
603
604 // Is the target a headline or is it a regular index?
605 if (_idx.row.isString())
606 {
607 // If the first element is non-zero but the second is,
608 // we use the number of elements as upper boundary
609 if (_idx.col.isOpenEnd())
610 _idx.col.setRange(0, _idx.col.front() + nStrings - nCurrentComponent - 1);
611
612 for (int n = nCurrentComponent; n < (int)nStrings; n++)
613 {
614 if (!strRes.vResult[n].length()
615 || (_idx.col[n] == VectorIndex::INVALID))
616 break;
617
618 _data.setHeadLineElement(_idx.col[n], sTableName, strRes.vResult[n].to_string());
619 }
620
621 nCurrentComponent = nStrings;
622 }
623 else if (_accessParser.isCluster())
624 {
625 // Write the return values to the cluster with
626 // parsing them
627 mu::value_type* v = nullptr;
628 int nResults = 0;
629 int nthComponent = 0;
630 NumeRe::Cluster& cluster = _data.getCluster(sTableName);
631
632 // Clusters are overwritten, if the last index
633 // is not explictly set
634 if (_idx.row.back() == -2 && _idx.row.front() == 0)
635 cluster.clear();
636
637 for (size_t i = nCurrentComponent; i < strRes.vResult.size(); i++)
638 {
639 // Set expression and evaluate it (not efficient but currently necessary)
640 if (strRes.vResult.is_string(i))
641 {
642 // Special case: only one single value
643 if (_idx.row.size() == 1 && _idx.col.size() == 1)
644 {
645 cluster.setString(_idx.row.front(), strRes.vResult[i].to_string());
646 break;
647 }
648
649 if (_idx.row[nthComponent] == VectorIndex::INVALID)
650 break;
651
652 cluster.setString(_idx.row[nthComponent], strRes.vResult[i].to_string());
653 nthComponent++;
654 }
655 else
656 {
657 _parser.SetExpr(strRes.vResult[i]);
658 v = _parser.Eval(nResults);
659 strRes.vNumericalValues.insert(strRes.vNumericalValues.end(), v, v+nResults);
660
661 // Special case: only one single value
662 if (_idx.row.size() == 1 && _idx.col.size() == 1)
663 {
664 cluster.setDouble(_idx.row.front(), v[0]);
665
666 break;
667 }
668
669 // Write the single values
670 for (int j = 0; j < nResults; j++)
671 {
672 if (_idx.row[nthComponent] == VectorIndex::INVALID)
673 break;
674
675 cluster.setDouble(_idx.row[nthComponent], v[j]);
676
677 nthComponent++;
678 }
679 }
680 }
681
682 nCurrentComponent = nStrings;
683 }
684 else
685 {
686 // Write the return values to the data table with
687 // parsing them
688 mu::value_type* v = nullptr;
689 int nResults = 0;
690 int nthComponent = 0;
691
692 bool rewriteColumn = false;
693
694 if (_idx.row.front() == 0 && _idx.row.isOpenEnd())
695 rewriteColumn = true;
696
697
698
699 for (size_t i = nCurrentComponent; i < strRes.vResult.size(); i++)
700 {
701 // Set expression and evaluate it (not efficient but currently necessary)
702 if (strRes.vResult.is_string(i))
703 {
704 if (_idx.row.size() == 1 && _idx.col.size() >= 1)
705 {
706 if (_idx.col[nthComponent] == VectorIndex::INVALID)
707 break;
708
709 _data.writeToTable(_idx.row.front(), _idx.col[nthComponent], sTableName, strRes.vResult[i].to_string());
710 }
711 else if (_idx.row.size() > 1 && _idx.col.size() == 1)
712 {
713 if (i == nCurrentComponent && rewriteColumn)
715
716 if (_idx.row[nthComponent] == VectorIndex::INVALID)
717 break;
718
719 _data.writeToTable(_idx.row[nthComponent], _idx.col.front(), sTableName, strRes.vResult[i].to_string());
720 }
721
722 nthComponent++;
723 }
724 else
725 {
726 _parser.SetExpr(strRes.vResult[i]);
727 v = _parser.Eval(nResults);
728 strRes.vNumericalValues.insert(strRes.vNumericalValues.end(), v, v+nResults);
729
730 for (int j = 0; j < nResults; j++)
731 {
732 if (_idx.row.size() == 1 && _idx.col.size() >= 1)
733 {
734 if (_idx.col[nthComponent] == VectorIndex::INVALID)
735 break;
736
737 _data.writeToTable(_idx.row.front(), _idx.col[nthComponent], sTableName, v[j]);
738 }
739 else if (_idx.row.size() > 1 && _idx.col.size() == 1)
740 {
741 if (i == nCurrentComponent
742 && rewriteColumn
743 && (_data.getType(_idx.col.subidx(0, 1), sTableName) != TableColumn::TYPE_DATETIME || !mu::isreal(v, nResults)))
745
746 if (_idx.row[nthComponent] == VectorIndex::INVALID)
747 break;
748
749 _data.writeToTable(_idx.row[nthComponent], _idx.col.front(), sTableName, v[j]);
750 }
751
752 nthComponent++;
753 }
754 }
755 }
756
757 nCurrentComponent = nStrings;
758 }
759 }
760
761
774 void StringParser::storeStringToStringObject(const std::vector<std::string>& vFinal, std::string& sObject, size_t& nCurrentComponent, size_t nStrings)
775 {
776 Indices _idx = getIndices(sObject, _parser, _data, _option);
777
778 if (_idx.row.isOpenEnd())
779 _idx.row.setRange(0, _idx.row.front()+nStrings-nCurrentComponent-1);
780
781 if (!_idx.col.isValid())
782 _idx.col.front() = 0;
783
784 for (size_t i = 0; i < _idx.row.size(); i++)
785 {
786 if (nCurrentComponent == nStrings)
787 return;
788
789 _data.writeString(removeQuotationMarks(vFinal[nCurrentComponent]), _idx.row[i], _idx.col.front());
790 nCurrentComponent++;
791 }
792 }
793
794
805 int StringParser::storeStringResults(StringResult& strRes, std::string __sObject)
806 {
807 // Only do something, if the target object is not empty
808 size_t nBracePos;
809
810 if (!__sObject.length() || (nBracePos = __sObject.find_first_not_of(' ')) == std::string::npos)
811 return 1;
812
813 strRes.vNumericalValues.clear();
814
815 // Handle remaining vector braces
816 if (__sObject[nBracePos] == '{')
818
819 std::string sObject;
820 size_t nStrings = strRes.vResult.size();
821 size_t nCurrentComponent = 0;
822
823 // As long as the target object is not empty
824 while (__sObject.length())
825 {
826 // Get-cut the next target
827 sObject = getNextArgument(__sObject, true);
828
829 // Examine the current target
830 if (_data.containsTablesOrClusters(sObject))
831 {
832 // Store the strings into the data object
833 storeStringToDataObjects(strRes, sObject, nCurrentComponent, nStrings);
834 }
835 else if (sObject.find("string(") != std::string::npos)
836 {
837 // Store the strings into the string object
838 storeStringToStringObject(strRes.vResult, sObject, nCurrentComponent, nStrings);
839 }
840 else if (containsStringVars(sObject))
841 {
842 // Store the strings in string variables
843 StripSpaces(sObject);
844 if (sObject.find(' ') != std::string::npos)
845 return 0;
846 try
847 {
848 if (nCurrentComponent >= nStrings)
849 setStringValue(sObject, "");
850 else
851 setStringValue(sObject, strRes.vResult[nCurrentComponent].to_string());
852 nCurrentComponent++;
853 }
854 catch (...)
855 {
856 throw;
857 }
858 }
859 else
860 {
861 // Store the results as numerical values
862 StripSpaces(sObject);
863 if (sObject.find(' ') != std::string::npos)
864 {
865 return 0;
866 }
867
868 // Search for the adress of the current variable
869 if (getPointerToVariable(sObject, _parser))
870 {
871 if (strRes.vNoStringVal.size() > nCurrentComponent && !strRes.vNoStringVal[nCurrentComponent])
872 {
873 return 0;
874 }
875 }
876
877 // If this is a numerical value
878 if (strRes.vNoStringVal.size() > nCurrentComponent && strRes.vNoStringVal[nCurrentComponent])
879 {
880 try
881 {
882 // Parse and store it
883 int nResults = 0;
884 mu::value_type* v = 0;
885 _parser.SetExpr(sObject + " = " + strRes.vResult[nCurrentComponent]);
886 v = _parser.Eval(nResults);
887
888 // Replace the evaluated expression with its result,
889 // which will be shown in the terminal. The actual precision
890 // remains untouched!
891 if (nResults)
892 {
893 vAns = v[0];
895 std::string sValues;
896 strRes.vNumericalValues.insert(strRes.vNumericalValues.end(), v, v+nResults);
897
898 // Transform the results into a string
899 for (int n = 0; n < nResults; n++)
900 {
901 sValues += toString(v[n], _option.getPrecision()) + ",";
902 }
903 sValues.pop_back();
904
905 // replace the current expression
906 strRes.vResult[nCurrentComponent] = sValues;
907 }
908
909 nCurrentComponent++;
910 }
911 catch (...)
912 {
913 throw;
914 }
915 }
916 else if (strRes.vNoStringVal.size() <= nCurrentComponent)
917 {
918 // Fallback: try to find the variable address
919 // although it doesn't seem to be a numerical value
920 if (!getPointerToVariable(sObject, _parser))
921 {
922 try
923 {
924 // If there's no numerical value, create
925 // a new string variable
926 setStringValue(sObject, "");
927 nCurrentComponent++;
928 }
929 catch (...)
930 {
931 throw;
932 }
933 }
934 }
935 else
936 {
937 try
938 {
939 // Create a new string variable
940 setStringValue(sObject, strRes.vResult[nCurrentComponent].to_string());
941 nCurrentComponent++;
942 }
943 catch (...)
944 {
945 throw;
946 }
947 }
948 }
949 }
950
951 return 1;
952 }
953
954
967 std::string StringParser::createStringOutput(StringResult& StrRes, std::string& sLine, int parserFlags, bool bSilent)
968 {
969 sLine.clear();
971 ans.clear();
972
973 s_vect& vFinal = StrRes.vResult;
974 std::vector<bool>& vIsNoStringValue = StrRes.vNoStringVal;
975
976 // Catch the cases, where the results are
977 // numerical only here
978 if (StrRes.bOnlyLogicals)
979 {
980 if (StrRes.vNumericalValues.size())
982 else
983 {
984 for (size_t i = 0; i < vFinal.size(); i++)
985 sLine += vFinal.getRef(i) + ",";
986
987 sLine.pop_back();
988 }
989
990 return sLine;
991 }
992
993 std::string sConsoleOut;
994 //std::string sCurrentComponent;
995
996 if (parserFlags & PEEK || !(NumeReKernel::bSupressAnswer || bSilent))
997 sConsoleOut = createTerminalOutput(StrRes, parserFlags);
998
999 // Every result in the current return values
1000 // is a single string result
1001 for (size_t j = 0; j < vFinal.size(); j++)
1002 {
1003 // In this case, no conversions are done
1004 // the results are simply put together and returned
1005 if (parserFlags & KEEP_MASKED_CONTROL_CHARS && parserFlags & KEEP_MASKED_QUOTES)
1006 {
1007 if (!(parserFlags & NO_QUOTES) && !vIsNoStringValue[j])
1008 sLine += vFinal.getRef(j);
1009 else
1010 sLine += vFinal[j].to_string();
1011
1012 if (j < vFinal.size() - 1)
1013 sLine += ",";
1014
1015 continue;
1016 }
1017
1018 if (!vIsNoStringValue[j])
1019 {
1020 ans.push_back(vFinal[j].to_string());
1021
1022 if (parserFlags & NO_QUOTES)
1023 sLine += vFinal[j].to_string();
1024 else
1025 sLine += vFinal.getRef(j);
1026 }
1027 else
1028 {
1029 _parser.SetExpr(vFinal[j]);
1030 int nResults = 0;
1031 mu::value_type* v = _parser.Eval(nResults);
1032 std::string stres;
1033
1034 for (int k = 0; k < nResults-1; k++)
1035 {
1036 ans.push_back(v[k]);
1037 stres = toCmdString(v[k]);
1038 sLine += stres + ", ";
1039 }
1040
1041 ans.push_back(v[nResults-1]);
1042 stres = toCmdString(v[nResults-1]);
1043 sLine += stres;
1044 }
1045
1046 // Break the loop, if this was the last string value
1047 if (j + 1 == vFinal.size())
1048 break;
1049
1050 // Add a comma, if neither the next nor the current string
1051 // is a special case
1052 sLine += ", ";
1053 }
1054
1055 return sConsoleOut;
1056 }
1057
1058
1068 std::string StringParser::createTerminalOutput(StringResult& strRes, int parserFlags)
1069 {
1070 // Shall the output be printed?
1071 if (parserFlags & NO_QUOTES && parserFlags & PEEK)
1072 {
1073 std::string sConsoleOut = "|-> ";
1074 bool bLineBreaks = false;
1075
1076 // Every result in the current return values
1077 // is a single string result
1078 for (size_t j = 0; j < strRes.vResult.size(); j++)
1079 {
1080 if (!strRes.vNoStringVal[j])
1081 {
1082 if (strRes.vResult[j].find('\n') != std::string::npos)
1083 bLineBreaks = true;
1084
1085 sConsoleOut = sConsoleOut + strRes.vResult[j];
1086 }
1087 else
1088 {
1089 _parser.SetExpr(strRes.vResult[j]);
1090 int nResults = 0;
1091 mu::value_type* v = _parser.Eval(nResults);
1092 std::string stres;
1093
1094 for (int k = 0; k < nResults-1; k++)
1095 {
1096 stres = toString(v[k], _option.getPrecision());
1097 sConsoleOut += stres + ", ";
1098 }
1099
1100 stres = toString(v[nResults-1], _option.getPrecision());
1101 sConsoleOut += stres;
1102 }
1103
1104 // Break the loop, if this was the last string value
1105 if (j + 1 == strRes.vResult.size())
1106 break;
1107
1108 // Add a comma, if neither the next nor the current string
1109 // is a special case
1110 sConsoleOut += ", ";
1111 }
1112
1113 // Replace all line break characters with the console
1114 // indentation, if that is needed
1115 if (bLineBreaks)
1116 replaceAll(sConsoleOut, "\n", "\n| ");
1117
1118 return sConsoleOut;
1119
1120 }
1121 else
1122 {
1123 std::vector<std::string> vStringResult;
1124 // Every result in the current return values
1125 // is a single string result
1126 for (size_t j = 0; j < strRes.vResult.size(); j++)
1127 {
1128 if (!strRes.vNoStringVal[j])
1129 {
1130 if (parserFlags & NO_QUOTES)
1131 {
1132 vStringResult.push_back(strRes.vResult[j].to_string());
1133 replaceAll(vStringResult.back(), "\"", "\\\"");
1134 }
1135 else
1136 {
1137 vStringResult.push_back(strRes.vResult.getRef(j));
1138 replaceAll(vStringResult.back(), "\"", "\\\"", 1, vStringResult.back().length()-1);
1139 }
1140
1141 replaceAll(vStringResult.back(), "\n", "\\n");
1142 replaceAll(vStringResult.back(), "\t", "\\t");
1143 }
1144 else
1145 {
1146 _parser.SetExpr(strRes.vResult[j]);
1147 //vStringResult.pop_back();
1148 int nResults = 0;
1149 mu::value_type* v = _parser.Eval(nResults);
1150
1151 for (int k = 0; k < nResults-1; k++)
1152 {
1153 vStringResult.push_back(toString(v[k], _option.getPrecision()));
1154 }
1155
1156 vStringResult.push_back(toString(v[nResults-1], _option.getPrecision()));
1157 }
1158 }
1159
1160 return "|-> " + NumeReKernel::formatResultOutput(vStringResult);
1161 }
1162
1163 }
1164
1165
1175 int StringParser::decodeStringParams(std::string& sLine)
1176 {
1177 int parserFlags = NO_FLAG;
1178 std::vector<int> vPositions;
1179
1180 // Search for every parameter and add the
1181 // corresponding flag, if the parameter was
1182 // detected
1183 for (auto iter = m_mStringParams.begin(); iter != m_mStringParams.end(); ++iter)
1184 {
1185 vPositions.push_back(findParameter(sLine, iter->first));
1186
1187 if (vPositions.back())
1188 parserFlags |= iter->second;
1189 }
1190
1191 // Return, if no flags were attached
1192 // to the current expression
1193 if (!vPositions.size())
1194 return parserFlags;
1195
1196 // Sort the vector (only about 6 elements,
1197 // should be quite fast) to obtain the
1198 // smallest, non-zero object quite fast
1199 sort(vPositions.begin(), vPositions.end());
1200
1201 // Find the start of the parameter list and
1202 // erase them from the expression
1203 for (size_t i = 0; i < vPositions.size(); i++)
1204 {
1205 if (vPositions[i])
1206 {
1207 sLine.erase(sLine.rfind('-', vPositions[i]));
1208 break;
1209 }
1210 }
1211
1212 // Return the calculated flags
1213 return parserFlags;
1214 }
1215
1216
1230 bool StringParser::isSimpleString(const std::string& sLine)
1231 {
1232 size_t nQuotes = 0;
1233
1234 // Got through the string
1235 for (size_t i = 0; i < sLine.size(); i++)
1236 {
1237 if (sLine[i] == '"' && (!i || sLine[i-1] != '\\'))
1238 {
1239 // Count quotation marks
1240 nQuotes++;
1241 continue;
1242 }
1243
1244 // Not in quotes and not a space?
1245 if (!(nQuotes % 2) && !isspace(sLine[i]) && sLine[i] != ',')
1246 return false;
1247 }
1248
1249 return true;
1250 }
1251
1252
1263 bool StringParser::isToken(const char* sToken, const std::string& sLine, size_t pos)
1264 {
1265 size_t nLength = strlen(sToken);
1266
1267 if (sLine.length() < pos + nLength)
1268 return false;
1269
1270 if (sLine.substr(pos, nLength) == sToken && (sLine.length() == pos+nLength || isDelimiter(sLine[pos+nLength])))
1271 return true;
1272
1273 return false;
1274 }
1275
1276
1286 std::string StringParser::maskControlCharacters(std::string sString)
1287 {
1288 replaceAll(sString, "\n", "\\n");
1289 replaceAll(sString, "\t", "\\t");
1290 return sString;
1291 }
1292
1293
1303 {
1304 if (oprt == "+")
1305 return 10;
1306
1307 if (oprt == ":")
1308 return 7;
1309
1310 if (oprt == "==" || oprt == "!=" || oprt == "<" || oprt == ">" || oprt == "<=" || oprt == ">=")
1311 return 5;
1312
1313 if (oprt == "&&" || oprt == "||" || oprt == "|||")
1314 return 2;
1315
1316 return 0;
1317 }
1318
1319
1328 static void finalizeStack(std::vector<StringStackItem>& rpnStack)
1329 {
1330 std::stack<size_t> stIf;
1331 std::stack<size_t> stElse;
1332 int idx = 0;
1333 bool lastIsIf = false;
1334
1335 for (size_t j = 0; j < rpnStack.size(); j++)
1336 {
1337 if (rpnStack[j].m_data == "?")
1338 {
1339 stIf.push(j);
1340 lastIsIf = true;
1341 }
1342
1343 // Only consider ":" as part of a ? : , if
1344 // there's already a ? in the stack
1345 if (rpnStack[j].m_data == ":" && stIf.size())
1346 {
1347 if (!lastIsIf && stElse.size())
1348 {
1349 // Finalize this ? : expression
1350 idx = stElse.top();
1351 stElse.pop();
1352 rpnStack[idx].m_val = j;
1353 }
1354
1355 // Finalize the if part of the expression
1356 stElse.push(j);
1357 idx = stIf.top();
1358 stIf.pop();
1359 rpnStack[idx].m_val = j;
1360 lastIsIf = false;
1361 }
1362 }
1363
1364 // Finalize all remaining ? : expressions
1365 while (stElse.size())
1366 {
1367 idx = stElse.top();
1368 stElse.pop();
1369 rpnStack[idx].m_val = rpnStack.size();
1370 }
1371 }
1372
1373
1382 static std::vector<StringStackItem> convertToStack(const std::vector<StringView>& vTokens)
1383 {
1384 std::vector<StringStackItem> rpnStack;
1385 std::stack<StringView> operators;
1386 int hasIf = 0;
1387
1388 // Now convert the tokens to the RPN stack
1389 for (size_t i = 0; i < vTokens.size(); i++)
1390 {
1391 // Odd numbers are operators
1392 if (i % 2)
1393 {
1394 // This case is special, because this is already
1395 // in RPN
1396 if (vTokens[i] == "?" || (vTokens[i] == ":" && hasIf > 0))
1397 {
1398 // Clear all operators first
1399 while (operators.size())
1400 {
1401 rpnStack.push_back(StringStackItem(operators.top(), 0));
1402 operators.pop();
1403 }
1404
1405 rpnStack.push_back(StringStackItem(vTokens[i], 0));
1406 hasIf += (vTokens[i] == "?") - (vTokens[i] == ":");
1407 continue;
1408 }
1409
1410 // This case is special, because it creates an additional
1411 // return value stack
1412 if (vTokens[i] == "," && !hasIf)
1413 {
1414 // Clear all operators first
1415 while (operators.size())
1416 {
1417 rpnStack.push_back(StringStackItem(operators.top(), 0));
1418 operators.pop();
1419 }
1420
1421 rpnStack.push_back(StringStackItem(vTokens[i], 0));
1422 continue;
1423 }
1424
1425 // Operators with larger or equal precedence
1426 // have to be evaluated first. Remove them from
1427 // the operator stack
1428 while (operators.size()
1429 && getOperatorPrecedence(operators.top()) >= getOperatorPrecedence(vTokens[i]))
1430 {
1431 rpnStack.push_back(StringStackItem(operators.top(), 0));
1432 operators.pop();
1433 }
1434
1435 // Add the new operator to the operator stack
1436 operators.push(vTokens[i]);
1437 }
1438 else
1439 rpnStack.push_back(StringStackItem(vTokens[i]));
1440 }
1441
1442 while (operators.size())
1443 {
1444 rpnStack.push_back(StringStackItem(operators.top(), 0));
1445 operators.pop();
1446 }
1447
1448 // Finalize the if-else logic
1449 finalizeStack(rpnStack);
1450
1451 // Dump the stack
1452 //std::string sDump;
1453 //
1454 //for (size_t i = 0; i < rpnStack.size(); i++)
1455 //{
1456 // sDump += "[" + rpnStack[i].m_data.to_string() + "]";
1457 //}
1458 //
1459 //g_logger.info("RPNSTACK = " + sDump);
1460
1461 // Nothing more to do. Return the stack
1462 return rpnStack;
1463 }
1464
1465
1475 std::vector<StringStackItem> StringParser::createStack(StringView sExpr) const
1476 {
1477 std::vector<StringView> vTokens;
1478
1479 size_t nQuotes = 0;
1480 int hasIf = 0;
1481
1482 // As long as the expression has a length
1483 while (sExpr.length())
1484 {
1485 // Remove all surrounding whitespace
1486 sExpr.strip();
1487
1488 // Go through the expression
1489 for (size_t i = 0; i < sExpr.length(); i++)
1490 {
1491 // Count quotes
1492 if (sExpr[i] == '"' && (!i || sExpr[i-1] != '\\'))
1493 nQuotes++;
1494
1495 if (nQuotes % 2)
1496 continue;
1497
1498 // Jump over possible parentheses
1499 if (sExpr[i] == '(' || sExpr[i] == '[' || sExpr[i] == '{')
1500 i += getMatchingParenthesis(sExpr.subview(i));
1501
1502 // Detect operators
1503 if (sExpr.subview(i, 3) == "|||")
1504 {
1505 // Prepare the token
1506 StringView sToken = sExpr.subview(0, i);
1507 sToken.strip();
1508
1509 // Store token and operator
1510 vTokens.push_back(sToken);
1511 vTokens.push_back(sExpr.subview(i, 3));
1512
1513 // Remove the beginning and restart the loop
1514 sExpr.trim_front(i+3);
1515 break;
1516 }
1517 else if (sExpr.subview(i, 2) == "=="
1518 || sExpr.subview(i, 2) == "!="
1519 || sExpr.subview(i, 2) == "<="
1520 || sExpr.subview(i, 2) == ">="
1521 || sExpr.subview(i, 2) == "&&"
1522 || sExpr.subview(i, 2) == "||")
1523 {
1524 // Prepare the token
1525 StringView sToken = sExpr.subview(0, i);
1526 sToken.strip();
1527
1528 // Store token and operator
1529 vTokens.push_back(sToken);
1530 vTokens.push_back(sExpr.subview(i, 2));
1531
1532 // Remove the beginning and restart the loop
1533 sExpr.trim_front(i+2);
1534 break;
1535 }
1536 else if (sExpr[i] == '+'
1537 || sExpr[i] == '?'
1538 || sExpr[i] == ':'
1539 || sExpr[i] == ','
1540 || sExpr[i] == '<'
1541 || sExpr[i] == '>')
1542 {
1543 if (sExpr[i] == ':' && hasIf <= 0)
1544 continue;
1545 else if (sExpr[i] == ',' && hasIf > 0)
1546 continue;
1547 else if (sExpr[i] == ':')
1548 hasIf--;
1549 else if (sExpr[i] == '?')
1550 hasIf++;
1551
1552 // Prepare the token
1553 StringView sToken = sExpr.subview(0, i);
1554 sToken.strip();
1555
1556 // Store token and operator
1557 vTokens.push_back(sToken);
1558 vTokens.push_back(sExpr.subview(i, 1));
1559
1560 // Remove the beginning and restart the loop
1561 sExpr.trim_front(i+1);
1562 break;
1563 }
1564
1565 // Is this the last token?
1566 if (i+1 == sExpr.length())
1567 {
1568 vTokens.push_back(sExpr);
1569
1570 // Now convert the tokens to the RPN stack
1571 // and return
1572 return convertToStack(vTokens);
1573 }
1574 }
1575 }
1576
1577 // Return the stack (should actually never hit this line)
1578 g_logger.warning("Returned from StringParser::createStack() from an unexpected statement.");
1579 return std::vector<StringStackItem>();
1580 }
1581
1582
1593 StringVector StringParser::evaluateStack(const std::vector<StringStackItem>& rpnStack, size_t from, size_t to)
1594 {
1595 std::stack<StringVector> valueStack;
1596 size_t nReturnValues = 1;
1597
1598 for (size_t i = from; i < to; i++)
1599 {
1600 // This is a value/variable
1601 if (rpnStack[i].m_val < 0)
1602 {
1603 std::string sValue = rpnStack[i].m_data.to_string();
1604
1605 if (sValue.front() == '"') // This is needed because the math parser does not handle string literals
1606 valueStack.push(StringVector::convert_literal(sValue));
1607 else if (isStringVectorVar(sValue))
1608 valueStack.push(getStringVectorVar(sValue));
1609 else if (containsStringVectorVars(sValue) || _parser.ContainsVectorVars(sValue, false))
1610 valueStack.push(evaluateStringVectors(sValue));
1611 else
1612 valueStack.push(StringVector::convert_literal(sValue));
1613 }
1614 else
1615 {
1616 if (rpnStack[i].m_data == "+")
1617 {
1618 StringVector op = valueStack.top();
1619 valueStack.pop();
1620 valueStack.top() += op;
1621 }
1622 else if (rpnStack[i].m_data == ",")
1623 {
1624 nReturnValues++;
1625 continue;
1626 }
1627 else if (rpnStack[i].m_data == "==")
1628 {
1629 StringVector op = valueStack.top();
1630 valueStack.pop();
1631 valueStack.top() = valueStack.top() == op;
1632 }
1633 else if (rpnStack[i].m_data == "!=")
1634 {
1635 StringVector op = valueStack.top();
1636 valueStack.pop();
1637 valueStack.top() = valueStack.top() != op;
1638 }
1639 else if (rpnStack[i].m_data == ">=")
1640 {
1641 StringVector op = valueStack.top();
1642 valueStack.pop();
1643 valueStack.top() = valueStack.top() >= op;
1644 }
1645 else if (rpnStack[i].m_data == "<=")
1646 {
1647 StringVector op = valueStack.top();
1648 valueStack.pop();
1649 valueStack.top() = valueStack.top() <= op;
1650 }
1651 else if (rpnStack[i].m_data == ">")
1652 {
1653 StringVector op = valueStack.top();
1654 valueStack.pop();
1655 valueStack.top() = valueStack.top() > op;
1656 }
1657 else if (rpnStack[i].m_data == "<")
1658 {
1659 StringVector op = valueStack.top();
1660 valueStack.pop();
1661 valueStack.top() = valueStack.top() < op;
1662 }
1663 else if (rpnStack[i].m_data == "&&")
1664 {
1665 StringVector op = valueStack.top();
1666 valueStack.pop();
1667 valueStack.top() = valueStack.top().and_f(op);
1668 }
1669 else if (rpnStack[i].m_data == "||")
1670 {
1671 StringVector op = valueStack.top();
1672 valueStack.pop();
1673 valueStack.top() = valueStack.top().or_f(op);
1674 }
1675 else if (rpnStack[i].m_data == "|||")
1676 {
1677 StringVector op = valueStack.top();
1678 valueStack.pop();
1679 valueStack.top() = valueStack.top().xor_f(op);
1680 }
1681 else if (rpnStack[i].m_data == "?")
1682 {
1683 // Get the absolute jump points
1684 size_t nIfEnd = rpnStack[i].m_val;
1685 size_t nElseEnd = rpnStack[nIfEnd].m_val;
1686
1687 // Evaluate the results recursively (lazy is not possible within this logic)
1688 valueStack.top().evalIfElse(valueStack.top(),
1689 evaluateStack(rpnStack, i+1, nIfEnd),
1690 evaluateStack(rpnStack, nIfEnd+1, nElseEnd));
1691 // Jump this evaluation to the end of the else
1692 // statement (most probably also the end of the
1693 // end of the current stack)
1694 i = nElseEnd;
1695 }
1696 }
1697
1698 //std::string stackTop;
1699 //
1700 //for (size_t i = 0; i < valueStack.top().size(); i++)
1701 // stackTop += valueStack.top().getRef(i).substr(0, 100) + ",";
1702 //
1703 //stackTop.pop_back();
1704 //g_logger.info("STACK.TOP() = " + stackTop);
1705 //g_logger.info("STACK.TOP() = " + valueStack.top().getRef(0).substr(0, 100));
1706 }
1707
1708 // return the value on top of the stack
1709 if (nReturnValues > valueStack.size())
1710 throw std::out_of_range("Stack size (" + toString(valueStack.size()) + ") is smaller than the requested number of return values (" + toString(nReturnValues) + ").");
1711
1712 StringVector vRet = valueStack.top();
1713 valueStack.pop();
1714 nReturnValues--;
1715
1716 while (nReturnValues)
1717 {
1718 vRet.insert(vRet.begin(), valueStack.top().begin(), valueStack.top().end());
1719 valueStack.pop();
1720 nReturnValues--;
1721 }
1722
1723 return vRet;
1724 }
1725
1726
1736 {
1737 std::vector<StringStackItem> rpnStack = createStack(sExpr);
1738 StringResult res;
1739
1740 res.vResult = evaluateStack(rpnStack, 0, rpnStack.size());
1741 res.vNoStringVal.resize(res.vResult.size());
1742 res.bOnlyLogicals = true;
1743
1744 for (size_t i = 0; i < res.vResult.size(); i++)
1745 {
1746 res.vNoStringVal[i] = !res.vResult.is_string(i);
1747
1748 if (!res.vNoStringVal[i])
1749 res.bOnlyLogicals = false;
1750 }
1751
1752 return res;
1753 }
1754
1755
1766 std::vector<bool> StringParser::applyElementaryStringOperations(vector<std::string>& vFinal, bool& bReturningLogicals)
1767 {
1768 std::vector<bool> vIsNoStringValue(vFinal.size(), false);
1769
1770 // Examine the whole passed vector
1771 for (unsigned int n = 0; n < vFinal.size(); n++)
1772 {
1773 // Strip whitespaces and ensure that the
1774 // current component is not empy
1775 StripSpaces(vFinal[n]);
1776
1777 if (!vFinal[n].length())
1778 continue;
1779
1780 // If there are logical expressions in the current
1781 // component, handle them here
1782 if (detectStringLogicals(vFinal[n]))
1783 {
1784 vFinal[n] = evalStringLogic(vFinal[n], bReturningLogicals);
1785 StripSpaces(vFinal[n]);
1786 }
1787
1788 // Concatenate the std::strings
1789 if (vFinal[n].front() == '"' || vFinal[n].back() == '"')
1790 concatenateStrings(vFinal[n]);
1791
1792 // Determine, whether the current component is a string
1793 // or a numerical expression
1794 if (vFinal[n].front() != '"' && vFinal[n].back() != '"')
1795 vIsNoStringValue[n] = true;
1796 }
1797
1798 // check, whether there's a string left
1799 bReturningLogicals = true;
1800
1801 for (size_t i = 0; i < vIsNoStringValue.size(); i++)
1802 {
1803 if (!vIsNoStringValue[i])
1804 {
1805 bReturningLogicals = false;
1806 break;
1807 }
1808 }
1809
1810 return vIsNoStringValue;
1811 }
1812
1813
1825 StringResult StringParser::eval(std::string& sLine, std::string sCache, bool bParseNumericals)
1826 {
1827 StringResult strRes;
1828 bool bObjectContainsTablesOrClusters = false;
1829
1830 // If the current line is a simple string,
1831 // Strip the surrounding spaces and return directly
1832 // This saves between 30-70% of the evaluation time
1833 if (!sCache.length() && isSimpleString(sLine))
1834 {
1835 StripSpaces(sLine);
1836
1837 while (sLine.length())
1838 {
1839 strRes.vResult.push_generic(getNextArgument(sLine, true));
1840 strRes.vNoStringVal.push_back(false);
1841 }
1842
1843 return strRes;
1844 }
1845
1846 StringExpression strExpr(sLine, sCache);
1847
1848 // Recurse for multiple store targets
1849 // Nur Rekursionen durchfuehren, wenn auch '=' in dem String gefunden wurde. Nur dann ist sie naemlich noetig.
1850 if (strExpr.nEqPos && strExpr.sLine.find(',') != std::string::npos)
1851 {
1852 // Get the left part of the assignment
1853 std::string sStringObject = strExpr.sLine.substr(0, strExpr.nEqPos);
1854
1855 // Ensure that the left part contains a data or a string object,
1856 // otherwise it is cleared
1857 if (sStringObject.substr(sStringObject.find_first_not_of(' '), 7) == "string("
1858 || _data.containsTablesOrClusters(sStringObject)
1859 || sStringObject[sStringObject.find_first_not_of(' ')] == '{')
1860 {
1861 // Find the equal sign after the closing parenthesis
1862 size_t nPos = getMatchingParenthesis(strExpr.sLine);
1863 nPos = strExpr.sLine.find('=', nPos);
1864
1865 // Ensure that it exists
1866 if (nPos == std::string::npos)
1868
1869 // Get the data object including the assignment operator and
1870 // cut this part from the original line
1871 if (strExpr.sLine[nPos + 1] == '=')
1872 nPos++;
1873
1874 sStringObject = strExpr.sLine.substr(0, nPos + 1);
1875 strExpr.sLine.erase(0, nPos + 1);
1876 }
1877 else
1878 sStringObject.clear();
1879
1880 // Remove whitespaces
1881 StripSpaces(strExpr.sLine);
1882
1883 // If the current line contains more than one string expressions
1884 if (strExpr.sLine != getNextArgument(strExpr.sLine, false))
1885 {
1886 std::string sRecursion = "";
1887 std::vector<std::string> vResult;
1888
1889 // While the current line is not empty
1890 while (strExpr.sLine.length())
1891 {
1892 // Cut of the first argument
1893 sRecursion = getNextArgument(strExpr.sLine, true);
1894
1895 // Apply the string parser on the current argument and store its
1896 // results in a common vector
1897 StringResult _res = eval(sRecursion, "");
1898
1899 for (size_t n = 0; n < _res.vResult.size(); n++)
1900 vResult.push_back(_res.vResult.getRef(n));
1901 }
1902
1903 // Create a new string vector variable from the results
1904 strExpr.sLine = createStringVectorVar(vResult);
1905 }
1906
1907 // Prepend the stored string object to the current input line
1908 if (sStringObject.length())
1909 strExpr.sLine = sStringObject + strExpr.sLine;
1910
1911 strExpr.findAssignmentOperator();
1912 }
1913
1914 // Find the start of the asignee
1915 size_t n_pos = 0;
1916
1917 if (strExpr.nEqPos)
1918 n_pos = strExpr.nEqPos+1;
1919
1920 // Get the string variables
1921 if (containsStringVars(strExpr.sLine.substr(n_pos)))
1922 getStringValuesAsInternalVar(strExpr.sLine, n_pos);
1923
1924 // Does the current line contain candidates
1925 // for string functions?
1926 if (strExpr.sLine.find('(') != std::string::npos)
1927 {
1928 //Timer timer("String function application");
1929 // Apply the standard string functions
1930 strExpr.sLine = applyStringFuncs(strExpr.sLine);
1931
1932 // Apply the special string functions
1933 strExpr.sLine = applySpecialStringFuncs(strExpr.sLine);
1934
1935 // Get the position of the equal sign after the
1936 // application of all string functions
1937 strExpr.findAssignmentOperator();
1938 }
1939
1940 strExpr.split();
1941
1942 if (strExpr.sAssignee.length() && _data.containsTablesOrClusters(strExpr.sAssignee))
1943 bObjectContainsTablesOrClusters = true;
1944
1945 // Get the contents of "string()", "data()" and the other caches
1946 strExpr.sLine = getDataForString(strExpr.sLine, 0);
1947
1948 // If the line now doesn't contain any strings, return with the onlyLogicals flag set
1949 if (!isStringExpression(strExpr.sLine) && !bObjectContainsTablesOrClusters)
1950 {
1951 // make sure that there are parseable characters between the operators
1952 if (strExpr.sLine.find_first_not_of("+-*/:?!.,;%&<>=^ ") != std::string::npos && bParseNumericals)
1953 {
1954 int nResults = 0;
1955 mu::value_type* v = 0;
1956
1957 // Parse the epression
1958 if (strExpr.sAssignee.length())
1959 _parser.SetExpr(strExpr.sAssignee + "=" + strExpr.sLine);
1960 else
1961 _parser.SetExpr(strExpr.sLine);
1962
1963 v = _parser.Eval(nResults);
1964 vAns = v[0];
1966 //eq_pos = strExpr.sLine.find('=');
1967 //strExpr.findAssignmentOperator();
1968
1969 // Remove the left part of the assignment, because it's already assigned
1970 //if (eq_pos != std::string::npos
1971 // && eq_pos
1972 // && eq_pos < sLine.length() + 1
1973 // && isAssignmentOperator(sLine, eq_pos))
1974 // sLine.erase(0, eq_pos + 1);
1975
1976 StripSpaces(strExpr.sLine);
1977
1978 // Return with the numbers already contained
1979 return StringResult(strExpr.sLine, v, nResults);
1980 }
1981
1982 // return with the onlyLogicals flag
1983 return StringResult(strExpr.sLine, true);
1984 }
1985 else if (!bObjectContainsTablesOrClusters && !strExpr.sAssignee.length() && isSimpleString(strExpr.sLine))
1986 {
1987 // After the data objects are resolved,
1988 // it's quite possible that there are only
1989 // simple strings left in this recursion
1990 StripSpaces(strExpr.sLine);
1991
1992 while (strExpr.sLine.length())
1993 {
1994 strRes.vResult.push_generic(getNextArgument(strExpr.sLine, true));
1995 strRes.vNoStringVal.push_back(false);
1996 }
1997
1998 return strRes;
1999 }
2000
2001 // If there are any opening parentheses, it is possible that we need
2002 // to pre-evaluate its contents
2003 if (strExpr.sLine.find('(') != std::string::npos)
2004 {
2005 size_t nQuotes = 0;
2006
2007 // Examine the whole command line
2008 for (size_t i = 0; i < strExpr.sLine.length(); i++)
2009 {
2010 // Jump over string literals
2011 if (strExpr.sLine[i] == '"')
2012 {
2013 if (i && strExpr.sLine[i - 1] == '\\')
2014 continue;
2015 nQuotes++;
2016 }
2017
2018 // Consider the var parsing feature
2019 if (strExpr.sLine[i] == '#' && !(nQuotes % 2))
2020 {
2021 // Examine, whether the var parsing feature was used
2022 // correctly and search for the end of its current application
2023 for (size_t j = i; j < strExpr.sLine.length(); j++)
2024 {
2025 if (strExpr.sLine[j] == '"')
2027
2028 if ((strExpr.sLine[j] == '(' || strExpr.sLine[j] == '{') && getMatchingParenthesis(strExpr.sLine.substr(j)) != std::string::npos)
2029 j += getMatchingParenthesis(sLine.substr(j));
2030
2031 if (strExpr.sLine[j] == ' ' || strExpr.sLine[j] == '+')
2032 {
2033 i = j;
2034 break;
2035 }
2036
2037 if (j + 1 == strExpr.sLine.length())
2038 {
2039 i = j;
2040 }
2041 }
2042 }
2043
2044 // Examine the current parenthesis: is it able to pre-evaluate the
2045 // current parenthesis?
2046 if (strExpr.sLine[i] == '(' && !(nQuotes % 2))
2047 {
2048 // Ensure that its counterpart exists
2049 if (getMatchingParenthesis(strExpr.sLine.substr(i)) == std::string::npos)
2051
2052 size_t nPos = getMatchingParenthesis(strExpr.sLine.substr(i)) + i;
2053
2054 // Ignore any calls to "string()"
2055 if (i < 6 || strExpr.sLine.substr(i - 6, 6) != "string")
2056 {
2057 // The contents of the parenthesis
2058 std::string sString = strExpr.sLine.substr(i + 1, nPos - i - 1);
2059
2060 // Pre-evaluate the contents of the parenthesis
2061 if (i > 0 && !checkDelimiter(strExpr.sLine.substr(i - 1, nPos - i + 2))) // this is probably a numerical function. Keep the parentheses
2062 {
2063 // Do only something, if the contents are containings strings
2064 if (isStringExpression(sString))
2065 {
2066 StringResult _res = eval(sString, "");
2067 std::string strvar = createStringVectorVar(_res.vResult);
2068
2069 if (!strvar.length())
2071
2072 strExpr.sLine = strExpr.sLine.substr(0, i + 1) + strvar + strExpr.sLine.substr(nPos);
2073 }
2074 }
2075 else // replace the whole parenthesis
2076 {
2077 // Do only something, if the contents are containing strings
2078 if (isStringExpression(sString))
2079 {
2080 StringResult _res = eval(sString, "");
2081 std::string strvar = createStringVectorVar(_res.vResult);
2082
2083 if (!strvar.length())
2085
2086 strExpr.sLine = strExpr.sLine.substr(0, i) + strvar + strExpr.sLine.substr(nPos + 1);
2087 }
2088 }
2089 }
2090 }
2091 }
2092 }
2093
2094 // Are there any vector braces left?
2095 if (strExpr.sLine.find('{') != std::string::npos)
2096 {
2097 size_t nQuotes = 0;
2098
2099 // Examine each vector brace
2100 for (size_t i = 0; i < strExpr.sLine.length(); i++)
2101 {
2102 if (strExpr.sLine[i] == '"' && (!i || strExpr.sLine[i-1] != '\\'))
2103 nQuotes++;
2104
2105 if (!(nQuotes % 2) && strExpr.sLine[i] == '{')
2106 {
2107 size_t nmatching = getMatchingParenthesis(strExpr.sLine.substr(i));
2108 std::string sVectorTemp = strExpr.sLine.substr(i+1, nmatching-1);
2109
2110 // Does the vector brace contain colons? Then it
2111 // might be a numerical vector expansion if it
2112 // is not a string expression.
2113 // CAREFUL: Colons are also part of file paths!
2114 if (sVectorTemp.find(':') != std::string::npos)
2115 {
2116 if (!isStringExpression(sVectorTemp))
2117 {
2118 // Try to evaluate the vector as
2119 // vector expansion
2120 _parser.SetExpr("{" + sVectorTemp + "}");
2121 int nRes = 0;
2122 mu::value_type* res = _parser.Eval(nRes);
2123
2124 // Store the result in a vector and
2125 // create a temporary vector variable
2126 std::vector<mu::value_type> vRes(res, res + nRes);
2127 strExpr.sLine.replace(i, nmatching+1, _parser.CreateTempVectorVar(vRes));
2128
2129 continue;
2130 }
2131 else if (sVectorTemp.find('"') == std::string::npos && !containsStringVectorVars(sVectorTemp))
2132 continue;
2133 }
2134
2135 if (!isStringExpression(sVectorTemp))
2136 {
2137 // Try to evaluate the vector as
2138 // vector expansion
2139 _parser.SetExpr(sVectorTemp);
2140 int nRes = 0;
2141 mu::value_type* res = _parser.Eval(nRes);
2142
2143 // Store the result in a vector and
2144 // create a temporary vector variable
2145 std::vector<mu::value_type> vRes(res, res + nRes);
2146 strExpr.sLine.replace(i, nmatching+1, _parser.CreateTempVectorVar(vRes));
2147
2148 continue;
2149 }
2150
2151 StringResult tempres = eval(sVectorTemp, "");
2152
2153 if (!tempres.vResult.size())
2155
2156 // Create a string vector variable from the returned vector
2157 // if it is a string. Otherwise we create a new temporary
2158 // vector from the parser using the numerical results
2159 if (!tempres.bOnlyLogicals)
2160 sVectorTemp = createStringVectorVar(tempres.vResult);
2161 else if (tempres.vNumericalValues.size())
2162 sVectorTemp = _parser.CreateTempVectorVar(tempres.vNumericalValues);
2163 else if (tempres.vResult.size() == 1 && tempres.vResult.front().find_first_of(":,") != std::string::npos)
2164 {
2165 _parser.SetExpr("{" + tempres.vResult.front() + "}");
2166 int nRes = 0;
2167 mu::value_type* res = _parser.Eval(nRes);
2168
2169 // Store the result in a vector and
2170 // create a temporary vector variable
2171 std::vector<mu::value_type> vRes(res, res + nRes);
2172 sVectorTemp = _parser.CreateTempVectorVar(vRes);
2173 }
2174 else // Should in fact never reach this point
2175 continue;
2176
2177 strExpr.sLine.replace(i, nmatching+1, sVectorTemp);
2178 }
2179 }
2180 }
2181
2182 // Strip all whitespaces and ensure, that there's something left
2183 StripSpaces(strExpr.sLine);
2184
2185 if (!strExpr.sLine.length())
2186 return StringResult("");
2187
2188 // If the current line doesn't contain any further std::string literals or return values
2189 // return it
2190 if (strExpr.sLine.find('"') == std::string::npos
2191 && strExpr.sLine.find('#') == std::string::npos
2192 && !containsStringVectorVars(strExpr.sLine)
2193 && !bObjectContainsTablesOrClusters)
2194 {
2195 // Ensure that this is no false positive
2196 if (strExpr.sLine.find("string(") != std::string::npos || containsStringVars(strExpr.sLine))
2198
2199 // return the current line
2200 return StringResult(strExpr.sLine);
2201 }
2202
2203 // Apply the "#" parser to the string
2204 strExpr.sLine = numToString(strExpr.sLine);
2205
2206 // Evaluate the remaining expression
2207 strRes = createAndEvaluateStack(strExpr.sLine);
2208
2209 // Ensure that there is at least one result
2210 if (!strRes.vResult.size())
2212
2213 // store the string results in the variables or inb "string()" respectively
2214 if (!storeStringResults(strRes, strExpr.sAssignee))
2216
2217 // Return the evaluated string command line
2218 return strRes;
2219 }
2220
2221
2234 StringParser::StringParserRetVal StringParser::evalAndFormat(std::string& sLine, std::string& sCache, bool bSilent, bool bCheckAssertions)
2235 {
2236 //Timer timer(sLine);
2237 sLine = " " + sLine + " ";
2238
2239 // Process the parameters and store their
2240 // results in the parser flags
2241 int parserFlags = decodeStringParams(sLine);
2242
2243 // Perform the actual work in the string parser core function
2244 // This function will parse the string, call the corresponding
2245 // static functions and perform all required logical operations
2246 StringResult StrRes = eval(sLine, sCache);
2247
2248 // Clear the internal string vector variables, because they're
2249 // all evaluated and processed now
2251
2252 // Check the results, if the assertion handler is active
2253 // and the results are not logical only
2254 if (bCheckAssertions)
2256
2257 // The result of the string parser core has to be parsed, so that
2258 // it is readable in the terminal. This is done here in this
2259 // function
2260 std::string sConsoleOut = createStringOutput(StrRes, sLine, parserFlags, bSilent);
2261
2262 // The output is probably not desired
2264 bSilent = true;
2265
2266 // Print the output
2267 if ((!bSilent || parserFlags & PEEK) && !StrRes.bOnlyLogicals)
2268 {
2269 // The Line break function is not needed any more
2270 // because the terminal is capable of breaking the
2271 // lines by itself
2272 if (parserFlags & PEEK)
2273 NumeReKernel::printPreFmt("\r" + sConsoleOut + "\n");
2274 else
2275 NumeReKernel::printPreFmt(sConsoleOut + "\n");
2276 }
2277
2278 // return the corresponding value. The string parser may
2279 // evaluate the command line to only contain logical or
2280 // numerical expressions
2281 if (StrRes.bOnlyLogicals)
2282 return STRING_NUMERICAL;
2283
2284 return STRING_SUCCESS;
2285 }
2286
2287
2297 bool StringParser::isStringExpression(const std::string& sExpression)
2298 {
2299 if (sExpression.find_first_of("\"#") != std::string::npos
2300 || sExpression.find("string(") != std::string::npos
2301 || sExpression.find("string_cast(") != std::string::npos
2302 || sExpression.find("char(") != std::string::npos
2303 || sExpression.find("getlasterror(") != std::string::npos
2304 || sExpression.find("getversioninfo(") != std::string::npos
2305 || sExpression.find("valtostr(") != std::string::npos
2306 || sExpression.find("weekday(") != std::string::npos
2307 || sExpression.find("to_tex(") != std::string::npos)
2308 return true;
2309
2310 if (containsStringVars(sExpression) || containsStringVectorVars(sExpression))
2311 return true;
2312
2313 if (sExpression.find('{') == std::string::npos)
2314 return false;
2315
2316 const std::map<std::string,NumeRe::Cluster>& mClusterMap = _data.getClusterMap();
2317
2318 for (auto iter = mClusterMap.begin(); iter != mClusterMap.end(); ++iter)
2319 {
2320 if (iter->second.isMixed() || iter->second.isString())
2321 {
2322 size_t pos = sExpression.find(iter->first + "{");
2323
2324 if (pos != std::string::npos && (!pos || isDelimiter(sExpression[pos-1])))
2325 return true;
2326 }
2327 }
2328
2329 return false;
2330 }
2331}
2332
void checkAssertion(mu::value_type *v, int nNum)
Checks the return value of a muParser evaluated result.
Definition: error.cpp:244
This class is defined to abstrahize the determination of the correct data object and the calculation ...
Definition: dataaccess.hpp:38
Indices & getIndices()
Returns a reference to the stored indices.
Definition: dataaccess.cpp:196
bool isCluster() const
Determines, whether the data access references a cluster.
Definition: dataaccess.cpp:209
std::string & getDataObject()
Returns a reference to the data object identifier.
Definition: dataaccess.cpp:170
void warning(const std::string &sMessage)
Convenience member function.
Definition: logger.hpp:130
This class represents the central memory managing instance. It will handle all tables and clusters,...
TableColumn::ColumnType getType(const VectorIndex &_vCol, const std::string &_sTable) const
const std::map< std::string, std::pair< size_t, size_t > > & getTableMap() const
void overwriteColumn(int col, const std::string &_sCache, TableColumn::ColumnType type)
This member function converts the selected column to the needed type, if this column shall be overwri...
bool containsTablesOrClusters(const std::string &sCmdLine)
This member function evaluates, whether the passed command line contains tables or clusters.
void writeToTable(int _nLine, int _nCol, const std::string &_sCache, const mu::value_type &_dData)
bool setHeadLineElement(int _i, const std::string &_sTable, std::string _sHead)
This class represents a whole cluster. The single items are stored as pointers to the abstract cluste...
Definition: cluster.hpp:325
void clear()
This member function clears the internal memory buffer and frees the associated memory.
Definition: cluster.cpp:395
void setDouble(size_t i, const mu::value_type &value)
This member function assigns a value as data for the i-th cluster item in memory. The type of the i-t...
Definition: cluster.cpp:561
void push_back(ClusterItem *item)
This member function appends an arbitrary cluster item at the back of the internal cluster array buff...
Definition: cluster.cpp:274
void setString(size_t i, const std::string &strval)
This member function assigns a string as data for the i-th cluster item in memory....
Definition: cluster.cpp:801
void setDoubleArray(const std::vector< mu::value_type > &vVals)
This member function assigns values as data for the all cluster items in memory. The type of the clus...
Definition: cluster.cpp:648
Cluster & getCluster(StringView sCluster)
This member function returns a reference to the cluster indicated by the passed cluster identifier.
Definition: cluster.cpp:2077
const std::map< std::string, Cluster > & getClusterMap() const
Definition: cluster.hpp:475
This class provides the complete function evaluation logic to the StringParser class.
std::string applyStringFuncs(std::string sLine)
This member function searches for an occurence of a known string function in the passed command line ...
std::string applySpecialStringFuncs(std::string sLine)
This member function applies special string functions in the expression, which cannot be implemented ...
size_t findNextFunction(const std::string &sFunc, StringView sLine, size_t nStartPos, size_t &nEndPosition, bool searchForMethods=false)
Finds the position of the next function occurence in the passed string including the position of the ...
StringView getFunctionArgumentList(const std::string &sFunc, StringView sLine, size_t nStartPosition, size_t nEndPosition)
Returns the contents of the argument parentheses of the function starting at nStartPosition.
void declareStringFuncs(const std::map< std::string, StringFuncHandle > &mStringFuncs)
This member function is used to fill the internal map of declared string functions with the data of t...
std::string printValue(const mu::value_type &value)
Prints a value to a string respecting possible integer optimizations.
This class handles all logical operations on string expressions.
void concatenateStrings(std::string &sExpr)
This member function performs the actual string concatenation of the passed string expression.
std::string evalStringLogic(std::string sLine, bool &bReturningLogicals)
This member function will evaluate logical string expressions in the passed command line.
bool detectStringLogicals(const std::string &sString)
This member function is may detect logical expressions in the passed string expression.
StringResult createAndEvaluateStack(StringView sExpr)
Create a stack from the expression and evaluate it.
bool isToken(const char *sToken, const std::string &sLine, size_t pos)
Determines, whether the passed token can be found at the passed position.
std::string getDataForString(std::string sLine, size_t n_pos)
This member function returns the contents of the data objects and expands them as a list.
std::string maskControlCharacters(std::string sString)
This member function masks the line break and the tabulator control characters for storing the proces...
MemoryManager & _data
bool isSimpleString(const std::string &sLine)
This member function determines, whether the passed string is simple, i.e. it is a string literal wit...
virtual bool isStringExpression(const std::string &sExpression) override
Returns true, if the passed expression is an expression containing strings, string variables or strin...
std::vector< bool > applyElementaryStringOperations(std::vector< std::string > &vFinal, bool &bReturningLogicals)
This member function applies some elementary string operations like concatenation to the string expre...
void storeStringToStringObject(const std::vector< std::string > &vFinal, std::string &sObject, size_t &nCurrentComponent, size_t nStrings)
This member function is a helper for StringParser::storeStringResults(). It will store the strings in...
std::string numToString(const std::string &sLine)
This member function implements the so-called value-to-string parser (called via #VAR in code).
std::map< std::string, int > m_mStringParams
std::string parseStringsInIndices(std::string sIndexExpression)
Parses the string expressions in index expressions so that they may used as numerical index expressio...
mu::Parser & _parser
std::string createTerminalOutput(StringResult &strRes, int parserFlags)
This private member function creates the output specialized for the terminal.
void replaceDataOccurence(std::string &sLine, const std::string &sOccurence)
Replaces all occurences of the passed data access occurence in the passed string.
std::vector< StringStackItem > createStack(StringView sExpr) const
This member function creates a stack from the passed expression, which may then be evaluated more eas...
virtual StringResult eval(std::string &sLine, std::string sCache, bool bParseNumericals=true) override
This public member function provides the string parser core functionality and is the function,...
StringVector evaluateStack(const std::vector< StringStackItem > &rpnStack, size_t from, size_t to)
Evaluate the created RPN stack between the selected start and end points.
int storeStringResults(StringResult &strRes, std::string sObject)
This member function stores the processed and calculated string results in their desired targets.
void storeStringToDataObjects(StringResult &strRes, std::string &sObject, size_t &nCurrentComponent, size_t nStrings)
This member function is a helper for StringParser::storeStringResults(). It will store the strings in...
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...
StringParser(mu::Parser &parser, MemoryManager &data, Settings &option)
String parser constructor.
std::string createStringOutput(StringResult &strRes, std::string &sLine, int parserFlags, bool bSilent)
This member function converts the processed string parser results into an output string,...
int decodeStringParams(std::string &sLine)
This member function finds and decodes all passed string expression parameters and removes them from ...
StringVector evaluateStringVectors(std::string sLine)
This member function evaluates the passed string vector and returns it's evaluated components in sepa...
const StringVector & getStringVectorVar(const std::string &sVarName) const
Return a reference to the identified string vector variable or throw if it does not exist.
bool containsStringVars(const std::string &sLine) const
This public member function determines, whether the passed string line contains string variables as p...
void removeStringVectorVars()
This member function removes all internal string vector variables.
bool isStringVectorVar(const std::string &sVarName) const
Check, whether the passed string identifies a string vector variable.
bool containsStringVectorVars(const std::string &sLine)
This member function determines, whether there are string vector variables in the passed command line...
void setStringValue(const std::string &sVar, const std::string &sValue)
This public member function creates or updates a string variable and fills it with the passed value.
std::string createStringVectorVar(const std::vector< std::string > &vStringVector)
This member function is used to create a string vector variable.
void getStringValuesAsInternalVar(std::string &sLine, unsigned int nPos=0)
This public member function resolves all string variable occurences and replaces them with an interna...
static NumeReKernel * getInstance()
This static member function returns a a pointer to the singleton instance of the kernel.
Definition: kernel.hpp:221
static bool bSupressAnswer
Definition: kernel.hpp:199
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
NumeRe::Cluster & getAns()
Definition: kernel.hpp:268
static std::string formatResultOutput(int nNum, mu::value_type *v)
This static function is used to format the result output in the terminal for numerical-only results.
Definition: kernel.cpp:2730
This class manages the setting values of the internal (kernel) settings of this application.
Definition: settings.hpp:663
std::string getLoadPath() const
Returns the current loading path.
Definition: settings.hpp:1038
std::string getWorkPath() const
Returns the current working path (connected to the <wp> token).
Definition: settings.hpp:1020
std::string getSavePath() const
Returns the current saving path.
Definition: settings.hpp:1029
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 getProcPath() const
Returns the current procedure root import path.
Definition: settings.hpp:1068
std::string getPlotPath() const
Returns the current plotting path (plot storing location).
Definition: settings.hpp:1048
std::string getExePath() const
Returns the current application root folder path.
Definition: settings.hpp:1010
std::string getScriptPath() const
Returns the current script import folder path.
Definition: settings.hpp:1058
bool writeString(const std::string &_sString, unsigned int _nthString=std::string::npos, unsigned int nCol=0)
std::string maxString(unsigned int i1=0, unsigned int i2=std::string::npos, unsigned int nCol=0)
unsigned int getStringElements(unsigned int nCol=std::string::npos) const
std::string readString(unsigned int _nthString=std::string::npos, unsigned int nCol=0)
std::string minString(unsigned int i1=0, unsigned int i2=std::string::npos, unsigned int nCol=0)
std::string sumString(unsigned int i1=0, unsigned int i2=std::string::npos, unsigned int nCol=0)
This class is an extension to the std::vector<std::string> to provide the vector-like functionalities...
std::string & getRef(size_t i)
Return a reference to the i-th element in this string.
void convert_to_string(size_t i, size_t minChars=0)
Convert the i-th element to a string.
void push_generic(const std::string &sStr)
Append a generic string value to the end of this vector. Depending on the existence of surrounding qu...
std::vector< bool > xor_f(const StringVector &sVect) const
This member function represents an XOR operator.
bool is_string(size_t i) const
Check whether the i-th element represents a string or a numeric value.
std::vector< bool > or_f(const StringVector &sVect) const
This member function represents an OR operator.
std::vector< bool > and_f(const StringVector &sVect) const
This member function represents an AND operator.
static StringVector convert_literal(const std::string &sLiteral)
Static member function to create a StringVector instance from a string literal.
void strip()
This member function shrinks the viewed section to remove all leading or trailing whitespace characte...
void trim_front(size_t len)
This member function can be used to remove characters from the front of the viewed section.
size_t length() const
This member function simply returns the length of the viewed section.
This class is the immutable (const) version of a string view. It can be constructed from a MutableStr...
StringView subview(size_t pos=0, size_t len=std::string::npos) const
This member function creates a new StringView class instance using the selected position and length a...
Common exception class for all exceptions thrown in NumeRe.
Definition: error.hpp:32
@ UNMATCHED_PARENTHESIS
Definition: error.hpp:224
@ STRING_ERROR
Definition: error.hpp:209
static size_t invalid_position
Definition: error.hpp:235
bool isValid() const
This member function determines, whether the internal index set is valid.
Definition: structures.hpp:601
VectorIndex subidx(size_t pos, size_t nLen=std::string::npos) const
This member function returns a subset of the internal stored index just like the std::string::substr(...
Definition: structures.hpp:238
size_t size() const
This member function returns the size of the indices stored in this class.
Definition: structures.hpp:314
bool isOpenEnd() const
This member function determines, whether the internal index set has an open end.
Definition: structures.hpp:614
void setRange(int nMin, int nMax)
This member function can be used to force the indices stored internally to be in a defined interval....
Definition: structures.hpp:712
bool isString() const
This member function determines, whether the internal index set referres to the table headlines.
Definition: structures.hpp:627
int & back()
This member function returns a reference to the final index value stored internally.
Definition: structures.hpp:653
int & front()
This member function returns a reference to the first index value stored internally.
Definition: structures.hpp:640
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...
void DisableAccessCaching()
Disable the data access caching for this position.
bool ContainsVectorVars(StringView sExpr, bool ignoreSingletons)
This member function checks, whether the passed expression contains a vector.
Mathematical expressions parser.
Definition: muParser.h:51
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
void replaceDataEntities(string &sLine, const string &sEntity, MemoryManager &_data, Parser &_parser, const Settings &_option, int options)
This function replaces all calls to a single data entity with an internal vector or its value,...
Definition: dataaccess.cpp:436
bool parser_CheckMultArgFunc(const string &sLeft, const string &sRight)
This function checks, whether the argument located between sLeft and sRight is part of a multi-argume...
Indices getIndices(StringView sCmd, mu::Parser &_parser, MemoryManager &_data, const Settings &_option)
Wrapper for the new getIndices function interface.
Definition: indices.cpp:49
@ REPLACE_NAN
Definition: dataaccess.hpp:60
@ INSERT_STRINGS
Definition: dataaccess.hpp:61
Assertion _assertionHandler
Definition: error.cpp:27
std::string replacePathSeparator(const std::string &)
This function replaces the Windows style path sparators to UNIX style.
DetachedLogger g_logger
Definition: logger.cpp:23
unsigned int getMatchingParenthesis(const StringView &)
Returns the position of the closing parenthesis.
Definition: tools.cpp:414
static std::vector< StringStackItem > convertToStack(const std::vector< StringView > &vTokens)
Static function to convert the tokens to a RPN stack.
static void finalizeStack(std::vector< StringStackItem > &rpnStack)
Static function to finalize the if-else logic in this stack.
static size_t getOperatorPrecedence(StringView oprt)
Static function to obtain the passed operator's precedence.
MUP_BASETYPE value_type
The numeric datatype used by the parser.
Definition: muParserDef.h:251
bool isreal(value_type *v, int nElem)
Definition: muParserDef.h:384
unsigned int getPositionOfFirstDelimiter(const string &sLine)
This function returns the position of the first delimiter in the passed string, but it jumps over par...
void convertVectorToExpression(string &sLine, const Settings &_option)
This function replaces vector expressions with their corresponding multi- expression equation.
mu::value_type * getPointerToVariable(const string &sVarName, Parser &_parser)
This function returns the pointer to the passed variable.
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
@ KEEP_MASKED_QUOTES
@ KEEP_MASKED_CONTROL_CHARS
static std::map< std::string, StringFuncHandle > getStringFuncHandles()
This static function is used to construct the string map.
std::string removeQuotationMarks(const std::string &sString)
This function simply removes the surrounding quotation marks.
std::string addQuotationMarks(const std::string &sString)
This function simply adds the surrounding quotation marks.
value_type vAns
double StrToDb(const std::string &sString)
Converts a string into a double.
std::string toCmdString(double dNumber)
Converts a numerical value into a "full" precision string.
std::string getNextArgument(std::string &sArgList, bool bCut)
Definition: tools.cpp:2294
void replaceAll(std::string &sToModify, const char *sToRep, const char *sNewValue, size_t nStart, size_t nEnd)
This function replaces all occurences of the string sToRep in the string sToModify with the new value...
This structure is central for managing the indices of a table or cluster read or write data access....
VectorIndex col
VectorIndex row
This struct encodes a string expression. It tracks the position of an equal sign in the expression in...
void split()
Splits expression and its assignee and sets the assignment operator position to 0.
void findAssignmentOperator()
Searches for the assignment operator (the equal sign separating expression and assignee)....
This structure contains all possible return values of the central string parser in single combined st...
std::vector< bool > vNoStringVal
std::vector< mu::value_type > vNumericalValues
A simple container for a single item in the string expression RPN stack.
std::string toString(int)
Converts an integer to a string without the Settings bloat.
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
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
bool isDelimiter(char c)
This function determines, if the passed character is a delimiter character.
Definition: tools.cpp:1852