Fix logic error in eval_tokens and add debug output

When faced with sub-expressions, the parser was not correctly advancing
its iterator to the sub-expression's matching end parenthesis, causing
it to evaluate inner conditions twice, and incorrectly terminate early
when it reached the first end parenthesis.

Added preprocessor flag NOTIFO_DEBUG to generate debug output to
PutModule() to validate the expression parsing logic.
This commit is contained in:
John Reese 2011-02-15 10:18:13 -05:00
parent a855fe7eb5
commit a70ff4a364
1 changed files with 47 additions and 2 deletions

View File

@ -25,6 +25,15 @@
#define NOTIFO_AWAY #define NOTIFO_AWAY
#endif #endif
// Debug output
#define NOTIFO_DEBUG 0
#if NOTIFO_DEBUG
#define PutDebug(s) PutModule(s)
#else
#define PutDebug(s) //s
#endif
class CNotifoMod : public CModule class CNotifoMod : public CModule
{ {
protected: protected:
@ -195,10 +204,17 @@ class CNotifoMod : public CModule
VCString tokens; VCString tokens;
padded.Split(" ", tokens, false); padded.Split(" ", tokens, false);
return eval_tokens(tokens.begin(), tokens.end(), context, nick, message); PutDebug("Evaluating message: <" + nick.GetNick() + "> " + message);
bool result = eval_tokens(tokens.begin(), tokens.end(), context, nick, message);
return result;
} }
#define expr(x, y) else if (token == x) { value = oper ? value && y : value || y; } #define expr(x, y) else if (token == x) { \
bool result = y; \
dbg += CString(x) + "/" + CString(result ? "true" : "false") + " "; \
value = oper ? value && result : value || result; \
}
/** /**
* Evaluate a tokenized boolean expression, or sub-expression. * Evaluate a tokenized boolean expression, or sub-expression.
@ -215,26 +231,54 @@ class CNotifoMod : public CModule
bool oper = true; bool oper = true;
bool value = true; bool value = true;
CString dbg = "";
for(; pos != end; pos++) for(; pos != end; pos++)
{ {
CString token = pos->AsLower(); CString token = pos->AsLower();
if (token == "(") if (token == "(")
{ {
// recursively evaluate sub-expressions
bool inner = eval_tokens(++pos, end, context, nick, message); bool inner = eval_tokens(++pos, end, context, nick, message);
dbg += "( inner/" + CString(inner ? "true" : "false") + " ) ";
value = oper ? value && inner : value || inner; value = oper ? value && inner : value || inner;
// search ahead to the matching parenthesis token
unsigned int parens = 1;
while(pos != end)
{
if (*pos == "(")
{
parens++;
}
else if (*pos == ")")
{
parens--;
}
if (parens == 0)
{
break;
}
pos++;
}
} }
else if (token == ")") else if (token == ")")
{ {
pos++; pos++;
PutDebug(dbg);
return value; return value;
} }
else if (token == "and") else if (token == "and")
{ {
dbg += "and ";
oper = true; oper = true;
} }
else if (token == "or") else if (token == "or")
{ {
dbg += "or ";
oper = false; oper = false;
} }
@ -255,6 +299,7 @@ class CNotifoMod : public CModule
} }
} }
PutDebug(dbg);
return value; return value;
} }