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 */ };