Seamly2D
Code documentation
qmutokenparser.cpp
Go to the documentation of this file.
1 /***************************************************************************************************
2  **
3  ** Copyright (C) 2015 Roman Telezhynskyi
4  **
5  ** Permission is hereby granted, free of charge, to any person obtaining a copy of this
6  ** software and associated documentation files (the "Software"), to deal in the Software
7  ** without restriction, including without limitation the rights to use, copy, modify,
8  ** merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
9  ** permit persons to whom the Software is furnished to do so, subject to the following conditions:
10  **
11  ** The above copyright notice and this permission notice shall be included in all copies or
12  ** substantial portions of the Software.
13  **
14  ** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
15  ** NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
16  ** NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
17  ** DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
18  ** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
19  **
20  ******************************************************************************************************/
21 
22 #include "qmutokenparser.h"
23 
24 #include <QMap>
25 #include <QStaticStringData>
26 #include <QStringData>
27 #include <QStringDataPtr>
28 
29 #include "qmuparsererror.h"
30 
31 namespace qmu
32 {
33 
34 //---------------------------------------------------------------------------------------------------------------------
36 {
37  InitCharSets();
38  setAllowSubexpressions(false);//Only one expression per time
39 }
40 
41 //---------------------------------------------------------------------------------------------------------------------
42 /**
43  * @brief QmuTokenParser class constructor. Make easy initialization math parser.
44  *
45  * This constructor hide initialization variables, operators, character sets.
46  * Use this constuctor to get tokens from formula. All formulas must be converted to external look.
47  * Example:
48  *
49  * QmuTokenParser *cal = new QmuTokenParser(formula, osSeparator, false);
50  * tokens = cal->GetTokens();
51  * numbers = cal->GetNumbers();
52  * delete cal;
53  *
54  * @param formula string with formula.
55  * @param fromUser true if we parse formula from user
56  */
57 QmuTokenParser::QmuTokenParser(const QString &formula, bool osSeparator, bool fromUser)
59 {
60  InitCharSets();
61  setAllowSubexpressions(false);//Only one expression per time
63 
64  SetSepForTr(osSeparator, fromUser);
65 
66  SetExpr(formula);
67  //Need run for making tokens. Don't catch exception here, because we want know if formula has error.
68  Eval();
69 }
70 
71 //---------------------------------------------------------------------------------------------------------------------
73 {
74 }
75 
76 //---------------------------------------------------------------------------------------------------------------------
77 /**
78  * @brief IsSingle test formula and return true if it contain only one number.
79  *
80  * Work only with expressions in internal (C) locale.
81  * @param formula expression for test
82  * @return true if fomula has single number
83  */
84 bool QmuTokenParser::IsSingle(const QString &formula)
85 {
86  if (formula.isEmpty())
87  {
88  return false;// if don't know say no
89  }
90 
91  QScopedPointer<QmuTokenParser> cal(new QmuTokenParser());
92 
93  // Parser doesn't know any variable on this stage. So, we just use variable factory that for each unknown
94  // variable set value to 0.
95  cal->SetVarFactory(AddVariable, cal.data());
96  cal->SetSepForEval();//Reset separators options
97 
98  try
99  {
100  cal->SetExpr(formula);
101  cal->Eval();// We don't need save result, only parse formula
102  }
103  catch (const qmu::QmuParserError &e)
104  {
105  Q_UNUSED(e)
106  return false;// something wrong with formula, say no
107  }
108 
109  QMap<int, QString> tokens = cal->GetTokens();// Tokens (variables, measurements)
110  const QMap<int, QString> numbers = cal->GetNumbers();// All numbers in expression
111  delete cal.take();
112 
113  // Remove "-" from tokens list if exist. If don't do that unary minus operation will broken.
114  RemoveAll(tokens, QStringLiteral("-"));
115 
116  if (tokens.isEmpty() && numbers.size() == 1)
117  {
118  return true;
119  }
120  else
121  {
122  return false;
123  }
124 }
125 
126 }// namespace qmu
virtual void InitCharSets() Q_DECL_OVERRIDE
InitCharSets init character set for parser.
void SetSepForTr(bool osSeparator, bool fromUser)
SetSepForTr set separators for translation expression.
static void RemoveAll(QMap< int, QString > &map, const QString &val)
RemoveAll remove token from token list.
static qreal * AddVariable(const QString &a_szName, void *a_pUserData)
void setAllowSubexpressions(bool value)
void SetExpr(const QString &a_sExpr)
Set the formula.
void SetVarFactory(facfun_type a_pFactory, void *pUserData=nullptr)
Set a function that can create variable pointer for unknown expression variables.
qreal Eval() const
Calculate the result.
Error class of the parser.
static bool IsSingle(const QString &formula)
IsSingle test formula and return true if it contain only one number.
virtual ~QmuTokenParser() Q_DECL_OVERRIDE
Namespace for mathematical applications.
This file defines the error class used by the parser.