Code::Blocks  SVN r11506
expression.cpp
Go to the documentation of this file.
1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
3  * http://www.gnu.org/licenses/gpl-3.0.html
4  *
5  * $Revision: 10138 $
6  * $Id: expression.cpp 10138 2015-03-10 02:50:53Z ollydbg $
7  * $HeadURL: https://svn.code.sf.net/p/codeblocks/code/trunk/src/plugins/codecompletion/parser/expression.cpp $
8  */
9 
10 #include <sdk.h>
11 
12 #include <stack>
13 
14 #ifndef CB_PRECOMP
15  #include <wx/wx.h>
16 #endif
17 
18 #include <logmanager.h>
19 #include <manager.h>
20 
21 #include "cclogger.h"
22 #include "expression.h"
23 #include "token.h"
24 
25 #define CC_EXPRESSION_DEBUG_OUTPUT 0
26 
27 #if defined(CC_GLOBAL_DEBUG_OUTPUT)
28  #if CC_GLOBAL_DEBUG_OUTPUT == 1
29  #undef CC_EXPRESSION_DEBUG_OUTPUT
30  #define CC_EXPRESSION_DEBUG_OUTPUT 1
31  #elif CC_GLOBAL_DEBUG_OUTPUT == 2
32  #undef CC_EXPRESSION_DEBUG_OUTPUT
33  #define CC_EXPRESSION_DEBUG_OUTPUT 2
34  #endif
35 #endif
36 
37 #ifdef CC_PARSER_TEST
38  #define TRACE(format, args...) \
39  CCLogger::Get()->DebugLog(F(format, ##args))
40  #define TRACE2(format, args...) \
41  CCLogger::Get()->DebugLog(F(format, ##args))
42 #else
43  #if CC_EXPRESSION_DEBUG_OUTPUT == 1
44  #define TRACE(format, args...) \
45  CCLogger::Get()->DebugLog(F(format, ##args))
46  #define TRACE2(format, args...)
47  #elif CC_EXPRESSION_DEBUG_OUTPUT == 2
48  #define TRACE(format, args...) \
49  do \
50  { \
51  if (g_EnableDebugTrace) \
52  CCLogger::Get()->DebugLog(F(format, ##args)); \
53  } \
54  while (false)
55  #define TRACE2(format, args...) \
56  CCLogger::Get()->DebugLog(F(format, ##args))
57  #else
58  #define TRACE(format, args...)
59  #define TRACE2(format, args...)
60  #endif
61 #endif
62 
64 {
65  const wxString Plus (_T("+"));
66  const wxString Subtract (_T("-"));
67  const wxString Multiply (_T("*"));
68  const wxString Divide (_T("/"));
69  const wxString LParenthesis (_T("("));
70  const wxString RParenthesis (_T(")"));
71  const wxString Mod (_T("%"));
72  const wxString Power (_T("^"));
73  const wxString BitwiseAnd (_T("&"));
74  const wxString BitwiseOr (_T("|"));
75  const wxString And (_T("&&"));
76  const wxString Or (_T("||"));
77  const wxString Not (_T("!"));
78  const wxString Equal (_T("=="));
79  const wxString Unequal (_T("!="));
80  const wxString GT (_T(">"));
81  const wxString LT (_T("<"));
82  const wxString GTOrEqual (_T(">="));
83  const wxString LTOrEqual (_T("<="));
84  const wxString LShift (_T("<<"));
85  const wxString RShift (_T(">>"));
86 }
87 
89 {
90  Initialize(wxEmptyString);
91 }
92 
94 {
95  m_UnaryOperator = false;
96  m_Token = token;
97  m_Type = ParseNodeType(m_Token);
98  m_Priority = GetNodeTypePriority(m_Type);
99 }
100 
102 {
103  if (token.IsEmpty()) return ExpressionNode::Unknown;
104  else if (token == ExpressionConsts::Plus) return ExpressionNode::Plus;
105  else if (token == ExpressionConsts::Subtract) return ExpressionNode::Subtract;
106  else if (token == ExpressionConsts::Multiply) return ExpressionNode::Multiply;
107  else if (token == ExpressionConsts::Divide) return ExpressionNode::Divide;
108  else if (token == ExpressionConsts::Mod) return ExpressionNode::Mod;
109  else if (token == ExpressionConsts::Power) return ExpressionNode::Power;
113  else if (token == ExpressionConsts::BitwiseOr) return ExpressionNode::BitwiseOr;
114  else if (token == ExpressionConsts::And) return ExpressionNode::And;
115  else if (token == ExpressionConsts::Or) return ExpressionNode::Or;
116  else if (token == ExpressionConsts::Not) return ExpressionNode::Not;
117  else if (token == ExpressionConsts::Equal) return ExpressionNode::Equal;
118  else if (token == ExpressionConsts::Unequal) return ExpressionNode::Unequal;
119  else if (token == ExpressionConsts::GT) return ExpressionNode::GT;
120  else if (token == ExpressionConsts::LT) return ExpressionNode::LT;
121  else if (token == ExpressionConsts::GTOrEqual) return ExpressionNode::GTOrEqual;
122  else if (token == ExpressionConsts::LTOrEqual) return ExpressionNode::LTOrEqual;
123  else if (token == ExpressionConsts::LShift) return ExpressionNode::LShift;
124  else if (token == ExpressionConsts::RShift) return ExpressionNode::RShift;
125  else
126  {
127  if (wxIsdigit(token[0])) return ExpressionNode::Numeric;
128  else return ExpressionNode::Unknown;
129  }
130 }
131 
133 {
134  switch (type)
135  {
136  case LParenthesis:
137  case RParenthesis: return 10;
138  case Not: return 9;
139  case Mod: return 8;
140  case Multiply:
141  case Divide:
142  case Power: return 7;
143  case Plus:
144  case Subtract: return 6;
145  case LShift:
146  case RShift: return 5;
147  case BitwiseAnd:
148  case BitwiseOr: return 4;
149  case Equal:
150  case Unequal:
151  case GT:
152  case LT:
153  case GTOrEqual:
154  case LTOrEqual: return 3;
155  case And: return 2;
156  case Or: return 1;
157  case Numeric:
158  case Unknown:
159  default: return 0;
160  }
161 }
162 
164 {
165  switch (type)
166  {
169  case ExpressionNode::Not:
170  return true;
176  case ExpressionNode::Mod:
180  case ExpressionNode::And:
181  case ExpressionNode::Or:
184  case ExpressionNode::GT:
185  case ExpressionNode::LT:
191  default:
192  return false;
193  }
194 }
195 
196 
198 {
199  switch ((wxChar)first.GetChar(0))
200  {
201  case _T('&'):
202  case _T('|'):
203  case _T('='):
204  case _T('!'):
205  case _T('>'):
206  case _T('<'):
207  {
208  wxString newOperator(first + second);
209  if (newOperator == ExpressionConsts::And ||
210  newOperator == ExpressionConsts::Or ||
211  newOperator == ExpressionConsts::Equal ||
212  newOperator == ExpressionConsts::Unequal ||
213  newOperator == ExpressionConsts::GTOrEqual ||
214  newOperator == ExpressionConsts::LTOrEqual ||
215  newOperator == ExpressionConsts::LShift ||
216  newOperator == ExpressionConsts::RShift)
217  return true;
218  else
219  return false;
220  }
221  default:
222  return false;
223  }
224 }
225 
227 {
228  m_InfixExpression.clear();
229  m_PostfixExpression.clear();
230 }
231 
233 {
234  if (token.IsEmpty())
235  return;
236 
237  if (!m_InfixExpression.empty())
238  {
239  wxString& lastToken = m_InfixExpression[m_InfixExpression.size() - 1];
240  if (ExpressionNode::IsBinaryOperator(lastToken, token))
241  {
242  lastToken += token;
243  return;
244  }
245  }
246 
247  m_InfixExpression.push_back(token);
248 }
249 
251 {
252  if (!m_PostfixExpression.empty() || m_InfixExpression.empty())
253  return;
254 
255  m_Result = true;
256  m_Status = true;
257 
258  std::stack<ExpressionNode> stackOperator;
260  for (PostfixVector::size_type i = 0; i < m_InfixExpression.size(); ++i)
261  {
262  ExpressionNode expNode;
263  expNode.Initialize(m_InfixExpression[i]);
264  const ExpressionNode::ExpressionNodeType type = expNode.GetType();
265  if (type == ExpressionNode::Numeric)
266  {
267  // Operand, add to postfix expression
268  m_PostfixExpression.push_back(expNode);
269  while (!stackOperator.empty() && stackOperator.top().IsUnaryOperator())
270  {
271  m_PostfixExpression.push_back(stackOperator.top());
272  stackOperator.pop();
273  }
274  }
275  else if (type == ExpressionNode::LParenthesis)
276  {
277  // Left Parentheses, add to stack
278  stackOperator.push(expNode);
279  }
280  else if (type == ExpressionNode::RParenthesis)
281  {
282  // Right Parentheses, reverse search the Left Parentheses, add all operator of the middle
283  ExpressionNode node;
284  while (!stackOperator.empty())
285  {
286  node = stackOperator.top();
287  stackOperator.pop();
289  {
290  while (!stackOperator.empty() && stackOperator.top().IsUnaryOperator())
291  {
292  m_PostfixExpression.push_back(stackOperator.top());
293  stackOperator.pop();
294  }
295  break;
296  }
297  else
298  m_PostfixExpression.push_back(node);
299  }
300  // The lastest node must be Left Parentheses
302  {
303  m_Status = false;
304  }
305  }
306  else
307  {
308  if (ExpressionNode::IsUnaryNode(type) && (m_PostfixExpression.empty() ||
309  (lastType != ExpressionNode::Unknown &&
310  lastType != ExpressionNode::RParenthesis &&
311  lastType != ExpressionNode::Numeric)))
312  {
313  expNode.SetUnaryOperator();
314  stackOperator.push(expNode);
315  }
316  else if (stackOperator.empty())
317  {
318  stackOperator.push(expNode);
319  }
320  else
321  {
322  ExpressionNode beforeExpNode = stackOperator.top();
323  if (beforeExpNode.GetType() != ExpressionNode::LParenthesis &&
324  beforeExpNode.GetPriority() >= expNode.GetPriority())
325  {
326  m_PostfixExpression.push_back(beforeExpNode);
327  stackOperator.pop();
328  }
329 
330  stackOperator.push(expNode);
331  }
332  }
333 
334  lastType = type;
335  }
336 
337  while (!stackOperator.empty())
338  {
339  ExpressionNode beforeExpNode = stackOperator.top();
340  if (beforeExpNode.GetType() == ExpressionNode::LParenthesis)
341  {
342  m_Status = false;
343  }
344  m_PostfixExpression.push_back(beforeExpNode);
345  stackOperator.pop();
346  }
347 
348 #ifdef CC_PARSER_TEST
349  wxString infix, postfix;
350  for (InfixVector::size_type i = 0; i < m_InfixExpression.size(); ++i)
351  infix += m_InfixExpression[i] + _T(" ");
352  for (PostfixVector::size_type i = 0; i < m_PostfixExpression.size(); ++i)
353  postfix += m_PostfixExpression[i].GetToken() + _T(" ");
354  TRACE(_T("ConvertInfixToPostfix() : InfixExpression : %s"), infix.wx_str());
355  TRACE(_T("ConvertInfixToPostfix() : PostfixExpression : %s"), postfix.wx_str());
356 #endif
357 }
358 
360 {
361  std::pair<long, long> pair;
362  std::stack<long> stack;
363  int cntNumeric = 0;
364 
365  for (PostfixVector::size_type i = 0; i < m_PostfixExpression.size(); ++i)
366  {
367  const ExpressionNode& node = m_PostfixExpression[i];
368  const ExpressionNode::ExpressionNodeType type = node.GetType();
369  if (type == ExpressionNode::Numeric)
370  {
371  ++cntNumeric;
372  if (cntNumeric == 1)
373  pair.first = node.GetTokenValue();
374  else if (cntNumeric == 2)
375  pair.second = node.GetTokenValue();
376  else if (cntNumeric == 3)
377  {
378  --cntNumeric;
379  stack.push(pair.first);
380  TRACE(_T("CalcPostfix() : stack.push(pair.first) : %ld"), pair.first);
381  pair.first = pair.second;
382  pair.second = node.GetTokenValue();
383  }
384  }
385  else
386  {
387  if (node.IsUnaryOperator())
388  {
389  if (cntNumeric == 1)
390  pair.first = CalculateUnary(type, pair.first);
391  else if (cntNumeric == 2)
392  pair.second = CalculateUnary(type, pair.second);
393  }
394  else
395  {
396  if (cntNumeric == 2)
397  {
398  --cntNumeric;
399  pair.first = Calculate(type, pair.first, pair.second);
400  }
401  else if (cntNumeric == 1)
402  {
403  if (stack.empty())
404  {
405  m_Status = false;
406  return false;
407  }
408  pair.second = pair.first;
409  pair.first = stack.top();
410  TRACE(_T("CalcPostfix() : stack.pop() : %ld"), pair.first);
411  stack.pop();
412  pair.first = Calculate(type, pair.first, pair.second);
413  }
414  }
415  }
416 
417  TRACE(_T("CalcPostfix() : pair.first : %ld, pair.second : %ld"), pair.first, pair.second);
418 
419  if (!m_Status)
420  return false;
421  }
422 
423  if (!stack.empty())
424  m_Status = false;
425  if (m_Status)
426  m_Result = pair.first; // get the actual value
427 
428  return true;
429 }
430 
432 {
433  switch (type)
434  {
436  return first + second;
438  return first - second;
440  return first * second;
442  if (second == 0) { m_Status = false; return 0; }
443  else return first / second;
444  case ExpressionNode::Mod:
445  if (second == 0) { m_Status = false; return 0; }
446  else return first / second;
448  return first & second;
450  return first | second;
451  case ExpressionNode::And:
452  return first && second;
453  case ExpressionNode::Or:
454  return first || second;
456  return first == second;
458  return first != second;
459  case ExpressionNode::GT:
460  return first > second;
461  case ExpressionNode::LT:
462  return first < second;
464  return first >= second;
466  return first <= second;
468  return first << second;
470  return first >> second;
475  case ExpressionNode::Not:
477  default:
478  return 0;
479  }
480 }
481 
483 {
484  switch (type)
485  {
487  return value;
489  return 0 - value;
490  case ExpressionNode::Not:
491  return !value;
497  case ExpressionNode::Mod:
501  case ExpressionNode::And:
502  case ExpressionNode::Or:
505  case ExpressionNode::GT:
506  case ExpressionNode::LT:
512  default:
513  return 0;
514  }
515 }
const wxString Equal(_T("=="))
const wxString Mod(_T("%"))
static bool IsUnaryNode(ExpressionNodeType type)
Definition: expression.cpp:163
const wxString LParenthesis(_T("("))
const wxString Plus(_T("+"))
void SetUnaryOperator(bool unary=true)
Definition: expression.h:48
const wxString BitwiseAnd(_T("&"))
#define TRACE(format, args...)
Definition: expression.cpp:58
#define _T(string)
bool wxIsdigit(const wxUniChar &c)
const wxString GT(_T(">"))
const wxString Multiply(_T("*"))
static bool IsBinaryOperator(wxString first, wxString second)
Definition: expression.cpp:197
long Calculate(ExpressionNode::ExpressionNodeType type, long first, long second)
Definition: expression.cpp:431
const wxString Divide(_T("/"))
wxUSE_UNICODE_dependent wxChar
const wxString LTOrEqual(_T("<="))
const wxString RParenthesis(_T(")"))
static ExpressionNodeType ParseNodeType(wxString token)
Definition: expression.cpp:101
void Initialize(wxString token)
Definition: expression.cpp:93
const wxString And(_T("&&"))
const wxString Or(_T("||"))
ExpressionNodeType GetType() const
Definition: expression.h:45
const wxString LShift(_T("<<"))
const wxString LT(_T("<"))
long GetTokenValue() const
Definition: expression.h:52
const wxStringCharType * wx_str() const
wxString wxEmptyString
const wxString Unequal(_T("!="))
bool CalcPostfix()
Definition: expression.cpp:359
long GetPriority() const
Definition: expression.h:50
const wxString Power(_T("^"))
bool IsEmpty() const
void AddToInfixExpression(wxString token)
Definition: expression.cpp:232
bool IsUnaryOperator() const
Definition: expression.h:47
const wxString Subtract(_T("-"))
void Clear()
Definition: expression.cpp:226
wxUniChar GetChar(size_t n) const
const wxString RShift(_T(">>"))
const wxString Not(_T("!"))
void ConvertInfixToPostfix()
Definition: expression.cpp:250
long CalculateUnary(ExpressionNode::ExpressionNodeType type, long value)
Definition: expression.cpp:482
const wxString BitwiseOr(_T("|"))
const wxString GTOrEqual(_T(">="))
static long GetNodeTypePriority(ExpressionNodeType type)
Definition: expression.cpp:132