Index: src/CodeBlocks.cbp
===================================================================
--- src/CodeBlocks.cbp (revision 6203)
+++ src/CodeBlocks.cbp (working copy)
@@ -1154,6 +1154,12 @@
+
+
+
+
+
+
Index: src/plugins/codecompletion/Makefile.am
===================================================================
--- src/plugins/codecompletion/Makefile.am (revision 6203)
+++ src/plugins/codecompletion/Makefile.am (working copy)
@@ -25,7 +25,8 @@
parser/parserthread.cpp \
parser/token.cpp \
parser/tokenizer.cpp \
- parser/searchtree.cpp
+ parser/searchtree.cpp \
+ parser/expression
noinst_HEADERS = ccdebuginfo.h \
ccoptionsdlg.h \
@@ -40,4 +41,5 @@
parser/parserthread.h \
parser/token.h \
parser/tokenizer.h \
- parser/searchtree.h
+ parser/searchtree.h \
+ parser/expression.h
Index: src/plugins/codecompletion/parser/expression.cpp
===================================================================
--- src/plugins/codecompletion/parser/expression.cpp (revision 0)
+++ src/plugins/codecompletion/parser/expression.cpp (revision 0)
@@ -0,0 +1,447 @@
+/*
+ * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
+ * http://www.gnu.org/licenses/gpl-3.0.html
+ * Designed by Loaden (loaden@gmail.com)
+ */
+
+#include
+#include "expression.h"
+#include "logmanager.h"
+
+#include
+
+#define PARSERTHREAD_DEBUG_OUTPUT 0
+
+#ifdef PARSER_TEST
+ extern void ParserTrace(const wxChar* format, ...);
+ #define TRACE(format, args...)\
+ ParserTrace(format , ## args)
+#else
+#if PARSERTHREAD_DEBUG_OUTPUT
+ #define TRACE(format, args...)\
+ Manager::Get()->GetLogManager()->DebugLog(F( format , ## args))
+#else
+ #define TRACE(format, args...)
+#endif
+#endif
+
+namespace ExpressionConsts
+{
+ const wxString Plus (_T("+"));
+ const wxString Subtract (_T("-"));
+ const wxString MultiPly (_T("*"));
+ const wxString Divide (_T("/"));
+ const wxString LParentheses (_T("("));
+ const wxString RParentheses (_T(")"));
+ const wxString Mod (_T("%"));
+ const wxString Power (_T("^"));
+ const wxString BitwiseAnd (_T("&"));
+ const wxString BitwiseOr (_T("|"));
+ const wxString And (_T("&&"));
+ const wxString Or (_T("||"));
+ const wxString Not (_T("!"));
+ const wxString Equal (_T("=="));
+ const wxString Unequal (_T("!="));
+ const wxString GT (_T(">"));
+ const wxString LT (_T("<"));
+ const wxString GTOrEqual (_T(">="));
+ const wxString LTOrEqual (_T("<="));
+ const wxString LShift (_T("<<"));
+ const wxString RShift (_T(">>"));
+}
+
+ExpressionNode::ExpressionNode()
+{
+ Initialize(wxEmptyString);
+}
+
+void ExpressionNode::Initialize(wxString token)
+{
+ m_Unitary = false;
+ m_Token = token;
+ m_Type = ParseNodeType(m_Token);
+ m_Priority = GetNodeTypePriority(m_Type);
+}
+
+ExpressionNode::ExpressionNodeType ExpressionNode::ParseNodeType(wxString token)
+{
+ if (token.IsEmpty() || token.IsNull()) return ExpressionNode::Unknown;
+ else if (token == ExpressionConsts::Plus) return ExpressionNode::Plus;
+ else if (token == ExpressionConsts::Subtract) return ExpressionNode::Subtract;
+ else if (token == ExpressionConsts::MultiPly) return ExpressionNode::MultiPly;
+ else if (token == ExpressionConsts::Divide) return ExpressionNode::Divide;
+ else if (token == ExpressionConsts::Mod) return ExpressionNode::Mod;
+ else if (token == ExpressionConsts::Power) return ExpressionNode::Power;
+ else if (token == ExpressionConsts::LParentheses) return ExpressionNode::LParentheses;
+ else if (token == ExpressionConsts::RParentheses) return ExpressionNode::RParentheses;
+ else if (token == ExpressionConsts::BitwiseAnd) return ExpressionNode::BitwiseAnd;
+ else if (token == ExpressionConsts::BitwiseOr) return ExpressionNode::BitwiseOr;
+ else if (token == ExpressionConsts::And) return ExpressionNode::And;
+ else if (token == ExpressionConsts::Or) return ExpressionNode::Or;
+ else if (token == ExpressionConsts::Not) return ExpressionNode::Not;
+ else if (token == ExpressionConsts::Equal) return ExpressionNode::Equal;
+ else if (token == ExpressionConsts::Unequal) return ExpressionNode::Unequal;
+ else if (token == ExpressionConsts::GT) return ExpressionNode::GT;
+ else if (token == ExpressionConsts::LT) return ExpressionNode::LT;
+ else if (token == ExpressionConsts::GTOrEqual) return ExpressionNode::GTOrEqual;
+ else if (token == ExpressionConsts::LTOrEqual) return ExpressionNode::LTOrEqual;
+ else if (token == ExpressionConsts::LShift) return ExpressionNode::LShift;
+ else if (token == ExpressionConsts::RShift) return ExpressionNode::RShift;
+ else if (token == ExpressionConsts::Plus) return ExpressionNode::Plus;
+ else
+ {
+ if (token.IsNumber()) return ExpressionNode::Numeric;
+ else return ExpressionNode::Unknown;
+ }
+}
+
+long ExpressionNode::GetNodeTypePriority(ExpressionNodeType type)
+{
+ switch (type)
+ {
+ case LParentheses:
+ case RParentheses:
+ return 9;
+ case Not:
+ return 8;
+ case Mod:
+ return 7;
+ case MultiPly:
+ case Divide:
+ case Power:
+ return 6;
+ case Plus:
+ case Subtract:
+ return 5;
+ case LShift:
+ case RShift:
+ return 4;
+ case BitwiseAnd:
+ case BitwiseOr:
+ return 3;
+ case Equal:
+ case Unequal:
+ case GT:
+ case LT:
+ case GTOrEqual:
+ case LTOrEqual:
+ return 2;
+ case And:
+ case Or:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+bool ExpressionNode::IsUnitaryNode(ExpressionNodeType type)
+{
+ switch (type)
+ {
+ case ExpressionNode::Plus:
+ case ExpressionNode::Subtract:
+ case ExpressionNode::Not:
+ return true;
+ default:
+ return false;
+ }
+}
+
+
+bool ExpressionNode::IsDoubleOperator(wxString first, wxString second)
+{
+ switch (first.GetChar(0))
+ {
+ case _T('&'):
+ case _T('|'):
+ case _T('='):
+ case _T('!'):
+ case _T('>'):
+ case _T('<'):
+ {
+ wxString newOperator(first + second);
+ if (newOperator == ExpressionConsts::And ||
+ newOperator == ExpressionConsts::Or ||
+ newOperator == ExpressionConsts::Equal ||
+ newOperator == ExpressionConsts::Unequal ||
+ newOperator == ExpressionConsts::GTOrEqual ||
+ newOperator == ExpressionConsts::LTOrEqual ||
+ newOperator == ExpressionConsts::LShift ||
+ newOperator == ExpressionConsts::RShift)
+ return true;
+ else
+ return false;
+ }
+ default:
+ return false;
+ }
+}
+
+void Expression::Clear()
+{
+ m_InfixExpression.clear();
+ m_PostfixExpression.clear();
+}
+
+void Expression::AddToInfixExpression(wxString token)
+{
+ if (!m_InfixExpression.empty())
+ {
+ wxString& lastToken = m_InfixExpression[m_InfixExpression.size() - 1];
+ if (ExpressionNode::IsDoubleOperator(lastToken, token))
+ {
+ lastToken += token;
+ return;
+ }
+ }
+ m_InfixExpression.push_back(token);
+}
+
+void Expression::ConvertInfixToPostfix()
+{
+ if (!m_PostfixExpression.empty() || m_InfixExpression.empty())
+ return;
+
+ m_Result = true;
+ m_Status = true;
+
+ std::stack stackOperator;
+ ExpressionNode::ExpressionNodeType lastType = ExpressionNode::Unknown;
+ for (PostfixVector::size_type i = 0; i < m_InfixExpression.size(); ++i)
+ {
+ ExpressionNode expNode;
+ expNode.Initialize(m_InfixExpression[i]);
+ const ExpressionNode::ExpressionNodeType type = expNode.GetType();
+ if (type == ExpressionNode::Numeric)
+ {
+ // Operand, add to postfix expression
+ m_PostfixExpression.push_back(expNode);
+ while (!stackOperator.empty() && stackOperator.top().IsUnitary())
+ {
+ m_PostfixExpression.push_back(stackOperator.top());
+ stackOperator.pop();
+ }
+ }
+ else if (type == ExpressionNode::LParentheses)
+ {
+ // Left Parentheses, add to stack
+ stackOperator.push(expNode);
+ }
+ else if (type == ExpressionNode::RParentheses)
+ {
+ // Right Parentheses, reverse search the Left Parentheses, add all operator of the middle
+ ExpressionNode node;
+ while (!stackOperator.empty())
+ {
+ node = stackOperator.top();
+ stackOperator.pop();
+ if (node.GetType() == ExpressionNode::LParentheses)
+ {
+ while (!stackOperator.empty() && stackOperator.top().IsUnitary())
+ {
+ m_PostfixExpression.push_back(stackOperator.top());
+ stackOperator.pop();
+ }
+ break;
+ }
+ else
+ m_PostfixExpression.push_back(node);
+ }
+ // The lastest node must be Left Parentheses
+ if (node.GetType() != ExpressionNode::LParentheses)
+ {
+ m_Status = false;
+ }
+ }
+ else
+ {
+ if (ExpressionNode::IsUnitaryNode(type) && (m_PostfixExpression.empty() ||
+ (lastType != ExpressionNode::Unknown &&
+ lastType != ExpressionNode::RParentheses &&
+ lastType != ExpressionNode::Numeric)))
+ {
+ expNode.SetUnitary();
+ stackOperator.push(expNode);
+ }
+ else if (stackOperator.empty())
+ {
+ stackOperator.push(expNode);
+ }
+ else
+ {
+ ExpressionNode beforeExpNode = stackOperator.top();
+ if (beforeExpNode.GetType() != ExpressionNode::LParentheses &&
+ beforeExpNode.GetPriority() >= expNode.GetPriority())
+ {
+ m_PostfixExpression.push_back(beforeExpNode);
+ stackOperator.pop();
+ }
+
+ stackOperator.push(expNode);
+ }
+ }
+
+ lastType = type;
+ }
+
+ while (!stackOperator.empty())
+ {
+ ExpressionNode beforeExpNode = stackOperator.top();
+ if (beforeExpNode.GetType() == ExpressionNode::LParentheses)
+ {
+ m_Status = false;
+ }
+ m_PostfixExpression.push_back(beforeExpNode);
+ stackOperator.pop();
+ }
+
+#ifdef PARSER_TEST
+ wxString infix, postfix;
+ for (InfixVector::size_type i = 0; i < m_InfixExpression.size(); ++i)
+ infix += m_InfixExpression[i] + _T(" ");
+ for (PostfixVector::size_type i = 0; i < m_PostfixExpression.size(); ++i)
+ postfix += m_PostfixExpression[i].GetToken() + _T(" ");
+ TRACE(_T("ConvertInfixToPostfix() : InfixExpression : %s"), infix.wx_str());
+ TRACE(_T("ConvertInfixToPostfix() : PostfixExpression : %s"), postfix.wx_str());
+#endif
+}
+
+bool Expression::CalcPostfix()
+{
+ std::pair pair;
+ std::stack stack;
+ int cntNumeric = 0;
+
+ for (PostfixVector::size_type i = 0; i < m_PostfixExpression.size(); ++i)
+ {
+ const ExpressionNode& node = m_PostfixExpression[i];
+ const ExpressionNode::ExpressionNodeType type = node.GetType();
+ if (type == ExpressionNode::Numeric)
+ {
+ ++cntNumeric;
+ if (cntNumeric == 1)
+ {
+ pair.first = node.GetTokenValue();
+ }
+ else if (cntNumeric == 2)
+ {
+ pair.second = node.GetTokenValue();
+ }
+ else if (cntNumeric == 3)
+ {
+ --cntNumeric;
+ stack.push(pair.first);
+ TRACE(_T("CalcPostfix() : stack.push(pair.first) : %d"), pair.first);
+ pair.first = pair.second;
+ pair.second = node.GetTokenValue();
+ }
+ }
+ else
+ {
+ if (node.IsUnitary())
+ {
+ if (cntNumeric == 1)
+ {
+ pair.first = CalculateUnitary(type, pair.first);
+ }
+ else if (cntNumeric == 2)
+ {
+ pair.second = CalculateUnitary(type, pair.second);
+ }
+ }
+ else
+ {
+ if (cntNumeric == 2)
+ {
+ --cntNumeric;
+ pair.first = Calculate(type, pair.first, pair.second);
+ }
+ else if (cntNumeric == 1)
+ {
+ if (stack.empty())
+ {
+ m_Status = false;
+ return false;
+ }
+ pair.second = pair.first;
+ pair.first = stack.top();
+ TRACE(_T("CalcPostfix() : stack.pop() : %d"), pair.first);
+ stack.pop();
+ pair.first = Calculate(type, pair.first, pair.second);
+ }
+ }
+ }
+
+ TRACE(_T("CalcPostfix() : pair.first : %d, pair.second : %d"), pair.first, pair.second);
+
+ if (!m_Status)
+ return false;
+ }
+
+ if (!stack.empty())
+ m_Status = false;
+ if (m_Status)
+ m_Result = pair.first ? true : false;
+
+ return true;
+}
+
+long Expression::Calculate(ExpressionNode::ExpressionNodeType type, long first, long second)
+{
+ switch (type)
+ {
+ case ExpressionNode::Plus:
+ return first + second;
+ case ExpressionNode::Subtract:
+ return first - second;
+ case ExpressionNode::MultiPly:
+ return first * second;
+ case ExpressionNode::Divide:
+ if (second == 0) { m_Status = false; return 0; }
+ else return first / second;
+ case ExpressionNode::Mod:
+ if (second == 0) { m_Status = false; return 0; }
+ else return first / second;
+ case ExpressionNode::BitwiseAnd:
+ return first & second;
+ case ExpressionNode::BitwiseOr:
+ return first | second;
+ case ExpressionNode::And:
+ return first && second;
+ case ExpressionNode::Or:
+ return first || second;
+ case ExpressionNode::Equal:
+ return first == second;
+ case ExpressionNode::Unequal:
+ return first != second;
+ case ExpressionNode::GT:
+ return first > second;
+ case ExpressionNode::LT:
+ return first < second;
+ case ExpressionNode::GTOrEqual:
+ return first >= second;
+ case ExpressionNode::LTOrEqual:
+ return first <= second;
+ case ExpressionNode::LShift:
+ return first << second;
+ case ExpressionNode::RShift:
+ return first >> second;
+ default:
+ return 0;
+ }
+}
+
+long Expression::CalculateUnitary(ExpressionNode::ExpressionNodeType type, long value)
+{
+ switch (type)
+ {
+ case ExpressionNode::Plus:
+ return value;
+ case ExpressionNode::Subtract:
+ return 0 - value;
+ case ExpressionNode::Not:
+ return !value;
+ default:
+ return 0;
+ }
+}
Index: src/plugins/codecompletion/parser/expression.h
===================================================================
--- src/plugins/codecompletion/parser/expression.h (revision 0)
+++ src/plugins/codecompletion/parser/expression.h (revision 0)
@@ -0,0 +1,97 @@
+/*
+ * This file is part of the Code::Blocks IDE and licensed under the GNU General Public License, version 3
+ * http://www.gnu.org/licenses/gpl-3.0.html
+ * Designed by Loaden (loaden@gmail.com)
+ */
+
+#ifndef EXPRESSION_H
+#define EXPRESSION_H
+
+#include
+#include
+
+class ExpressionNode
+{
+public:
+ enum ExpressionNodeType
+ {
+ Unknown, // Unknown
+ Plus, // +
+ Subtract, // -
+ MultiPly, // *
+ Divide, // /
+ LParentheses, // (
+ RParentheses, // )
+ Mod, // %
+ Power, // ^
+ BitwiseAnd, // &
+ BitwiseOr, // |
+ And, // &&
+ Or, // ||
+ Not, // !
+ Equal, // ==
+ Unequal, // !=
+ GT, // >
+ LT, // <
+ GTOrEqual, // >=
+ LTOrEqual, // <=
+ LShift, // <<
+ RShift, // >>
+ Numeric, // Numeric
+ };
+
+ ExpressionNode();
+ void Initialize(wxString token);
+
+ ExpressionNodeType GetType() const { return m_Type; }
+
+ bool IsUnitary() const { return m_Unitary; }
+ void SetUnitary(bool unitary = true) { m_Unitary = unitary; }
+
+ long GetPriority() const { return m_Priority; }
+ wxString GetToken() const { return m_Token; }
+ long GetTokenValue() const
+ {
+ long r;
+ m_Token.ToLong(&r);
+ return r;
+ }
+
+ static ExpressionNodeType ParseNodeType(wxString token);
+ static long GetNodeTypePriority(ExpressionNodeType type);
+ static bool IsUnitaryNode(ExpressionNodeType type);
+ static bool IsDoubleOperator(wxString first, wxString second);
+
+private:
+ wxString m_Token;
+ ExpressionNodeType m_Type;
+ bool m_Unitary;
+ long m_Priority;
+};
+
+class Expression
+{
+public:
+ void AddToInfixExpression(wxString token);
+ void ConvertInfixToPostfix();
+ bool CalcPostfix();
+ bool GetResult() const { return m_Result; }
+ bool GetStatus() const { return m_Status; }
+ void Clear();
+
+private:
+ long Calculate(ExpressionNode::ExpressionNodeType type, long first, long second);
+ long CalculateUnitary(ExpressionNode::ExpressionNodeType type, long value);
+
+private:
+ typedef std::vector PostfixVector;
+ PostfixVector m_PostfixExpression;
+
+ typedef std::vector InfixVector;
+ InfixVector m_InfixExpression;
+
+ bool m_Result;
+ bool m_Status;
+};
+
+#endif // EXPRESSION_H
Index: src/plugins/codecompletion/parser/parserthread.cpp
===================================================================
--- src/plugins/codecompletion/parser/parserthread.cpp (revision 6203)
+++ src/plugins/codecompletion/parser/parserthread.cpp (working copy)
@@ -15,18 +15,25 @@
#include
#include "logmanager.h"
#include
+#include "expression.h"
#include
#include
#define PARSERTHREAD_DEBUG_OUTPUT 0
+#ifdef PARSER_TEST
+ extern void ParserTrace(const wxChar* format, ...);
+ #define TRACE(format, args...)\
+ ParserTrace(format , ## args)
+#else
#if PARSERTHREAD_DEBUG_OUTPUT
#define TRACE(format, args...)\
Manager::Get()->GetLogManager()->DebugLog(F( format , ## args))
#else
#define TRACE(format, args...)
#endif
+#endif
int THREAD_START = wxNewId();
int THREAD_END = wxNewId();
@@ -71,6 +78,7 @@
const wxString kw_ifdef (_T("ifdef"));
const wxString kw_ifndef (_T("ifndef"));
const wxString kw_elif (_T("elif"));
+ const wxString kw_el (_T("el"));
const wxString kw_endif (_T("endif"));
const wxString kw_include (_T("include"));
const wxString kw_inline (_T("inline"));
@@ -117,7 +125,6 @@
m_EncounteredTypeNamespaces(),
m_LastUnnamedTokenName(wxEmptyString),
m_ParsingTypedef(false),
- m_PreprocessorIfCount(0),
m_IsBuffer(parserThreadOptions.useBuffer),
m_Buffer(bufferOrFilename),
m_IsPointer(false),
@@ -1162,40 +1169,78 @@
void ParserThread::HandlePreprocessorBlocks(const wxString& preproc)
{
- if (preproc.StartsWith(ParserConsts::kw_if)) // #if, #ifdef, #ifndef
+#ifndef PARSER_TEST
+ wxString proc = preproc;
+ wxString peekToken = m_Tokenizer.PeekToken();
+#endif
+
+ // need to force the tokenizer skip raw expression
+ TokenizerState oldState = m_Tokenizer.GetState();
+ m_Tokenizer.SetState(tsReadRawExpression);
+
+ // #if #ifdef #ifndef
+ if (preproc.StartsWith(ParserConsts::kw_if))
{
- wxString token = preproc;
- ++m_PreprocessorIfCount;
-
- token = m_Tokenizer.GetToken();
- if (token.IsSameAs(_T("0")))
+ bool state;
+ if (preproc == ParserConsts::kw_if)
{
- // TODO: handle special case "#if 0"
- TRACE(_T("HandlePreprocessorBlocks() : Special case \"#if 0\" not skipped."));
+ state = CalcConditionExpression();
+ m_ExpressionState.push(state);
}
- m_Tokenizer.SkipToEOL();
+ else
+ {
+ state = (preproc == ParserConsts::kw_ifdef) ? IsMacroDefined() : !IsMacroDefined();
+ m_ExpressionState.push(state);
+ m_Tokenizer.SkipToEOL();
+ }
+
+ if (!state)
+ SkipToNextPreprocessorBlock();
}
- else if (preproc==ParserConsts::kw_else || preproc==ParserConsts::kw_elif) // #else, #elif
+
+ // #elif
+ else if (preproc == ParserConsts::kw_elif)
{
- TRACE(_T("HandlePreprocessorBlocks() : Saving nesting level: %d"), m_Tokenizer.GetNestingLevel());
- m_Tokenizer.SaveNestingLevel();
- wxString token = preproc;
- while (!token.IsEmpty() && token != ParserConsts::kw_endif)
- token = m_Tokenizer.GetToken();
- --m_PreprocessorIfCount;
-#if PARSERTHREAD_DEBUG_OUTPUT
- int l = m_Tokenizer.GetNestingLevel();
-#endif
- m_Tokenizer.RestoreNestingLevel();
- TRACE(_T("HandlePreprocessorBlocks() : Restoring nesting level: %d (was %d)"), m_Tokenizer.GetNestingLevel(), l);
+ if (!m_ExpressionState.empty() && !m_ExpressionState.top() && CalcConditionExpression())
+ m_ExpressionState.top() = true;
+ else
+ SkipToNextPreprocessorBlock();
+
+ if (m_ExpressionState.empty())
+ TRACE(_T("HandlePreprocessorBlocks() : #kw_elif : %s, %d"), m_Tokenizer.GetFilename().wx_str(), m_Tokenizer.GetLineNumber());
}
- else if (preproc==ParserConsts::kw_endif) // #endif
- --m_PreprocessorIfCount;
+
+ // #else
+ else if (preproc==ParserConsts::kw_else)
+ {
+ if (!m_ExpressionState.empty() && !m_ExpressionState.top())
+ m_Tokenizer.SkipToEOL();
+ else
+ SkipToEndPreprocessorBlock();
+
+ if (m_ExpressionState.empty())
+ TRACE(_T("HandlePreprocessorBlocks() : #endif : %s, %d"), m_Tokenizer.GetFilename().wx_str(), m_Tokenizer.GetLineNumber());
+ }
+
+ // #endif
+ else if (preproc==ParserConsts::kw_endif)
+ {
+ m_Tokenizer.SkipToEOL(false, true);
+ if (!m_ExpressionState.empty())
+ m_ExpressionState.pop();
+ else
+ TRACE(_T("HandlePreprocessorBlocks() : #endif : %s, %d"), m_Tokenizer.GetFilename().wx_str(), m_Tokenizer.GetLineNumber());
+ }
+
+ // other
else
{
m_Tokenizer.SkipToEOL();
- TRACE( _T("HandlePreprocessorBlocks() : Skip Unrecognized Preprocessor blocks") );
+ TRACE(_T("HandlePreprocessorBlocks() : Skip Unrecognized Preprocessor blocks"));
}
+
+ // reset tokenizer's functionality
+ m_Tokenizer.SetState(oldState);
}
void ParserThread::HandleNamespace()
@@ -2182,3 +2227,135 @@
return stripped_args;
}
+
+void ParserThread::GetPreprocessorValue(const wxString& token, bool& found, long& value)
+{
+ Token* tk = TokenExists(token, 0, tkPreprocessor);
+ if (tk != NULL)
+ {
+ found = true;
+ if (tk->m_Type.IsEmpty())
+ {
+ return;
+ }
+
+ if (!tk->m_Type.IsNumber())
+ {
+ GetPreprocessorValue(tk->m_Type, found, value);
+ }
+ else
+ {
+ found = tk->m_Type.ToLong(&value, tk->m_Type.StartsWith(_T("0x")) ? 16 : 10);
+ }
+ }
+}
+
+bool ParserThread::CalcConditionExpression()
+{
+ wxString buf(m_Tokenizer.ReadToEOL());
+ buf += _T("#");
+
+ Expression exp;
+ Tokenizer tk;
+ tk.SetState(tsReadRawExpression);
+ tk.InitFromBuffer(buf);
+ while (tk.NotEOF())
+ {
+ wxString token = tk.GetToken();
+ if (token == _T("\\") || token == _T("defined") || token == _T("#"))
+ continue;
+
+ if (token.Length() > 1 && !token.IsNumber() && token[0] != _T('('))
+ {
+ bool found = false; // Must be initialized to false
+ long value = -1; // Must be initialized to -1
+ GetPreprocessorValue(token, found, value);
+ if (found)
+ {
+ if (value == -1) value = 1;
+ token.Printf(_T("%d"), value);
+ }
+ else
+ {
+ value = 0;
+ token.Printf(_T("%d"), value);
+ }
+ }
+
+ exp.AddToInfixExpression(token);
+ }
+
+ exp.ConvertInfixToPostfix();
+ if (exp.CalcPostfix())
+ {
+ bool state = exp.GetStatus() && exp.GetResult();
+ TRACE(_T("CalcConditionExpression() : exp.GetStatus() : %d, exp.GetResult() : %d"), exp.GetStatus(), exp.GetResult());
+ return state;
+ }
+ return true;
+}
+
+void ParserThread::SkipToNextPreprocessorBlock()
+{
+ wxString token(_T("#"));
+ wxString prevToken;
+ do
+ {
+ prevToken = token;
+ token = m_Tokenizer.PeekToken();
+
+ if (prevToken == _T("#"))
+ {
+ if (token.StartsWith(ParserConsts::kw_if))
+ {
+ m_Tokenizer.GetToken();
+ SkipToEndPreprocessorBlock(false);
+ token = m_Tokenizer.PeekToken();
+ }
+
+ if (token.StartsWith(ParserConsts::kw_el) || (token == ParserConsts::kw_endif))
+ break;
+ }
+ }
+ while (!m_Tokenizer.GetToken().IsEmpty());
+ m_Tokenizer.UngetToken();
+}
+
+void ParserThread::SkipToEndPreprocessorBlock(bool ungetToken)
+{
+ wxString token(_T("#"));
+ wxString prevToken;
+ do
+ {
+ prevToken = token;
+ token = m_Tokenizer.PeekToken();
+
+ if (prevToken == _T("#"))
+ {
+ if (token.StartsWith(ParserConsts::kw_if))
+ {
+ m_Tokenizer.GetToken();
+ SkipToEndPreprocessorBlock(false);
+ token = m_Tokenizer.PeekToken();
+ }
+
+ if (token == ParserConsts::kw_endif)
+ break;
+ }
+ }
+ while (!m_Tokenizer.GetToken().IsEmpty());
+
+ if (ungetToken)
+ m_Tokenizer.UngetToken();
+ else
+ m_Tokenizer.GetToken();
+}
+
+bool ParserThread::IsMacroDefined()
+{
+ wxString token = m_Tokenizer.GetToken();
+ bool found = false; // Must be initialized to false
+ long value = -1; // Must be initialized to -1
+ GetPreprocessorValue(token, found, value);
+ return found;
+}
Index: src/plugins/codecompletion/parser/parserthread.h
===================================================================
--- src/plugins/codecompletion/parser/parserthread.h (revision 6203)
+++ src/plugins/codecompletion/parser/parserthread.h (working copy)
@@ -16,6 +16,7 @@
#include
#include
+#include
//extern int THREAD_START;
//extern int THREAD_END;
@@ -239,6 +240,28 @@
*/
wxString GetStrippedArgs(const wxString & args);
+ /** Get the value of pre-processor
+ * @param 'found' MUST BE Initialized to false, 'value' MUST BE Initialized to -1
+ * @return finded or not)
+ */
+ void GetPreprocessorValue(const wxString& token, bool& found, long& value);
+
+ /** Judge what is the first block
+ */
+ bool CalcConditionExpression();
+
+ /** Skip to next blocks, To mark #else #elif #endif as the end
+ */
+ void SkipToNextPreprocessorBlock();
+
+ /** Skip to end blocks, To mark #endif as the end
+ */
+ void SkipToEndPreprocessorBlock(bool ungetToken = true);
+
+ /** If the macro defined, return true
+ */
+ bool IsMacroDefined();
+
/** if we regard the parserThread class as a syntax anilyzer, then the Tokenizer class is
* regard as the lexer, which always feeds a wxString by calling m_Tokenizer.GetToken()
*/
@@ -319,6 +342,9 @@
/** holds current template agrument(s) when a template occurs */
wxString m_TemplateArgument;
+
+ /** Expression value */
+ std::stack m_ExpressionState;
};
#endif // PARSERTHREAD_H
Index: src/plugins/codecompletion/parser/tokenizer.cpp
===================================================================
--- src/plugins/codecompletion/parser/tokenizer.cpp (revision 6203)
+++ src/plugins/codecompletion/parser/tokenizer.cpp (working copy)
@@ -15,15 +15,22 @@
#include "manager.h"
#include
#include
+#include "logmanager.h"
#define TOKENIZER_DEBUG_OUTPUT 0
+#ifdef PARSER_TEST
+ extern void ParserTrace(const wxChar* format, ...);
+ #define TRACE(format, args...)\
+ ParserTrace(format , ## args)
+#else
#if TOKENIZER_DEBUG_OUTPUT
#define TRACE(format, args...)\
Manager::Get()->GetLogManager()->DebugLog(F( format , ## args))
#else
#define TRACE(format, args...)
#endif
+#endif
namespace TokenizerConsts
{
@@ -677,12 +684,20 @@
{
m_IsOperator = false;
- // skip blocks () []
- if (!SkipBlock(CurrentChar()))
- return wxEmptyString;
+ if (m_State & tsReadRawExpression)
+ {
+ str= c;
+ MoveToNextChar();
+ }
+ else
+ {
+ // skip blocks () []
+ if (!SkipBlock(CurrentChar()))
+ return wxEmptyString;
- str = FixArgument(m_Buffer.Mid(start, m_TokenIndex - start));
- CompactSpaces(str);
+ str = FixArgument(m_Buffer.Mid(start, m_TokenIndex - start));
+ CompactSpaces(str);
+ }
}
else
{
@@ -845,4 +860,3 @@
return str;
}
-
Index: src/plugins/codecompletion/parser/tokenizer.h
===================================================================
--- src/plugins/codecompletion/parser/tokenizer.h (revision 6203)
+++ src/plugins/codecompletion/parser/tokenizer.h (working copy)
@@ -17,6 +17,7 @@
tsSkipQuestion = 0x0002,
tsSkipSubScrip = 0x0004,
tsSingleAngleBrace = 0x0008,
+ tsReadRawExpression= 0x0010,
tsSkipNone = 0x1000,
// convenient masks