class Parser
{
/* reference: http://totty.iteye.com/blog/123252
* infix expression => postfix expression
*/
class PostExpStack
{
private:
#define STACK_SIZE 100
Symbol *sym[STACK_SIZE];
int index;
public:
PostExpStack()
{
index = 0;
}
int push(Symbol *s)
{
int err = OB_SUCCESS;
if (NULL == s)
{
TBSYS_LOG(WARN, "unexpected NULL. wtfQ");
}
TBSYS_LOG(DEBUG, "push an element into stack");
if (index < STACK_SIZE)
{
sym[index] = s;
index++;
}
else
{
err = OB_ERROR;
}
return err;
}
Symbol *pop()
{
Symbol *s;
TBSYS_LOG(DEBUG, "pop an element from stack");
if(!is_empty())
{
index--;
s = sym[index];
if (NULL == s)
{
TBSYS_LOG(WARN, "unexpected NULLi. index = %d", index);
}
}
else
{
s = NULL;
}
return s;
}
inline bool is_empty()
{
return (0 == index);
}
};
public:
Parser(Symbol *sym_list, int size):sym_list(sym_list),len(size)
{
TBSYS_LOG(DEBUG, "init Parser");
idx = 0;
if (NULL == sym_list)
{
TBSYS_LOG(WARN, "invalid sym list");
}
TBSYS_LOG(DEBUG, "init Parser succ. sys_list=%p, size=%d", sym_list, len);
}
~Parser(){}
public:
int parse()
{
int err = 0;
int i = 0;
err = parse_Expression();
return err;
}
private:
PostExpStack stack;
Symbol *sym_list;
int len;
int idx;
private:
int parse_Expression()
{
int err = OB_SUCCESS;
int i = 0;
int code = 0;
Symbol *sym = NULL;
for (i = 0; i < len; i++)
{
sym = &sym_list[i];
code = sym->code;
TBSYS_LOG(DEBUG, "code = %d", code);
switch(code)
{
case peCodeLeftBracket:
err = stack.push(sym);
break;
case peCodeRightBracket:
err = do_oper2();
break;
case peCodeMul:
case peCodeDiv:
//break;
case peCodeAdd:
case peCodeSub:
// break;
case peCodeLessThan:
case peCodeLessOrEqual:
case peCodeEqual:
case peCodeNotEqual:
case peCodeGreaterThan:
case peCodeGreaterOrEqual:
case peCodeIs:
case peCodeLike:
// break;
case peCodeAnd:
// break;
case peCodeOr:
err = do_oper1(sym);
break;
case peCodeString:
case peCodeInt:
case peCodeFloat:
case peCodeDateTime:
case peCodeNull:
case peCodeTrue:
case peCodeFalse:
err = output(sym);
break;
default:
err = output(sym);
/*
err = OB_ERR_UNEXPECTED;
TBSYS_LOG(WARN, "unexpected symbol found");
*/
break;
}
if (OB_SUCCESS != err)
{
break;
}
}
while((OB_SUCCESS == err) && !stack.is_empty())
{
err = output(stack.pop());
}
return err;
}
int do_oper1(Symbol *new_sym)
{
int err = OB_SUCCESS;
Symbol *old_sym;
int code = 0;
int new_prio = 0;
int old_prio = 0;
if (NULL != new_sym)
{
while((OB_SUCCESS == err) && (!stack.is_empty()))
{
old_sym = stack.pop();
if (NULL == old_sym)
{
TBSYS_LOG(WARN, "unexpect null pointer");
err = OB_ERROR;
break;
}
code = old_sym->code;
if (peCodeLeftBracket == code)
{
err = stack.push(old_sym);
if (OB_SUCCESS != err)
{
TBSYS_LOG(WARN, "fail to push symbol into stack. stack is full!");
}
break;
}
else
{
new_prio = new_sym->prio;
old_prio = old_sym->prio;
if (new_prio > old_prio)
{
err = stack.push(old_sym);
if (OB_SUCCESS != err)
{
TBSYS_LOG(WARN, "fail to push symbol into stack. stack is full!");
}
break;
}
else
{
err = output(old_sym);
}
}
} /* while */
TBSYS_LOG(DEBUG, "push new sym");
if (OB_SUCCESS == err)
{
err = stack.push(new_sym);
}
}
else
{
TBSYS_LOG(WARN, "symbol pointer is null");
err = OB_ERROR;
}
return err;
}
int do_oper2()
{
int err = OB_SUCCESS;
Symbol *sym;
int code = 0;
while(!stack.is_empty())
{
sym = stack.pop();
if (NULL == sym)
{
TBSYS_LOG(WARN, "fail to pop symbol from stack. stack is empty!");
err = OB_ERROR;
}
code = sym->code;
if (peCodeLeftBracket == code)
{
break;
}
else
{
err = output(sym);
if (OB_SUCCESS != err)
{
TBSYS_LOG(WARN, "unexpected error");
break;
}
}
}
return err;
}
int output(Symbol *s)
{
TBSYS_LOG(INFO, ">>>>>>>>output===>>>>: [code:%d, value:%.*s]",
s->code,
s->length,
s->value);
s->encode.dump();
return OB_SUCCESS;
}
};
int infix2postfix(Symbol *sym_list, int size, ObObj *arr)
{
int err;
Parser *p = new Parser(sym_list, size);
err = p->parse();
if (OB_ITER_END != err)
{
err = OB_ERROR;
}
else
{
err = OB_SUCCESS;
}
return err;
}
支持多种运算:
enum peCode{
peCodeLeftBracket = 1,
peCodeRightBracket = 2,
peCodeMul = 3,
peCodeDiv = 4,
peCodeAdd = 5,
peCodeSub = 6,
peCodeLessThan = 7,
peCodeLessOrEqual = 8,
peCodeEqual = 9,
peCodeNotEqual = 10,
peCodeGreaterThan = 11,
peCodeGreaterOrEqual = 12,
peCodeIs = 13,
peCodeLike = 14,
peCodeAnd = 15,
peCodeOr = 16,
peCodeColumnName = 50,
peCodeString = 51,
peCodeInt = 52,
peCodeFloat = 53,
peCodeDateTime = 54,
peCodeNull = 55,
peCodeTrue = 56,
peCodeFalse = 57
};
enum pePriority{
pePrioLeftBracket = 100, /* highest */
pePrioRightBracket = 0, /* lowest */
pePrioMul = 9,
pePrioDiv = 9,
pePrioAdd = 8,
pePrioSub = 8,
pePrioLessThan = 7,
pePrioLessOrEqual = 7,
pePrioEqual = 7,
pePrioNotEqual = 7,
pePrioGreaterThan = 7,
pePrioGreaterOrEqual = 7,
pePrioIs = 7,
pePrioLike = 7,
pePrioAnd = 6,
pePrioOr = 5 /*,
pePrioString = -1,
pePrioInt = -1,
pePrioFloat = -1,
pePrioDateTime = -1,
pePrioNull = -1,
pePrioTrue = -1,
pePrioFalse = -1
*/
};