static int pushDefaultOperator(StateObj *pStObj) { if(pStObj->nextTurn == TURN_BINARY_OPERATOR){ DEBUG(" nextTurn == TURN_BINARY_OPERATOR"); } if(pStObj->posWithinPhrase == FALSE){ DEBUG( " posWithinPhrase == FALSE"); } if (pStObj->nextTurn == TURN_BINARY_OPERATOR && pStObj->posWithinPhrase == FALSE) return pushOperator(pStObj,&m_defaultOperatorNode); return SUCCESS; }
void ExprEvaluator::E() { P(); tokenizer.nextToken(); while(tokenizer.isBinary()) { pushOperator(binary(tokenizer.nextToken())); tokenizer.consumeToken(); P(); tokenizer.nextToken(); } while(operators.back() != oper::SANTINEL) popOperator(); }
void ExprEvaluator::P() { tokenizer.nextToken(); if(tokenizer.isNumber()){ operands.push_back(tokenizer.value()); tokenizer.consumeToken(); }else if(tokenizer.isOpenBrace()){ tokenizer.consumeToken(); operators.push_back(oper::SANTINEL); E(); expect(ExprTokenizer::token_type::CLOSE_BRACE); pop(operators); } else if(tokenizer.isUnary()){ pushOperator(unary(tokenizer.nextToken())); tokenizer.consumeToken(); P(); } else throw new Error(tokenizer.getExpr(), tokenizer.getTokPos(), ":Arithmetic expression missmatch."); }
void convertToPostfix(char *str){ /* o1: Holds the precedence of the new operator * o2: Holds the precendence of the topmost operator on the stack * ptoken: The pointer to the start of each string delimited by commas * stringToAdd: Houses a single character so strcat() can add singular characters * aCopy: A copy of the given string used to read from as we are modifying the original string */ int o1, o2; char *ptoken, stringToAdd[] = "0", aCopy[100]; /* Copy the given string to a second string to be read from */ strcpy(aCopy, str); /* Set the first element of the given string to NULL, effectively erasing the string from the point of view of strcat() */ *str = '\0'; /* Cycle through each group of characters delimited by a whitespace */ for(ptoken = strtok(aCopy," "); ptoken != NULL; ptoken = strtok(NULL, " ")){ /* If the character is a bracket or operator, then run this code */ if(isOperator(*ptoken) && strlen(ptoken) == 1){ /* Code to figure out precedences of operators */ if(*ptoken == '*' || *ptoken == '/') o1 = 3; else if(*ptoken == '^') o1 = 4; else if(*ptoken == '+' || *ptoken == '-' ) o1 = 2; if(seeOperator() == '*' || seeOperator() == '/') o2 = 3; else if(seeOperator() == '^') o2 = 4; else if(seeOperator() == '+' || seeOperator() == '-' ) o2 = 2; else o2 = 0; /* If the operator stack isn't empty, and the precedence of the new operator is less than or equal to the top operator * in the stack, then pop the top operator in to the post-fix string, and push the new operator in to the stack. */ if(emptyOperator() != 1 && o1 <= o2){ *stringToAdd = popOperator(); strcat(str," "); strcat(str,stringToAdd); pushOperator(*ptoken); } /* Otherwise, if it's empty or the new operator has greater precedence, push to the operator stack */ else{ pushOperator(*ptoken); } } /* If the character is a left bracket, push it into the operator stack */ else if(*ptoken == '('){ pushOperator(*ptoken); } /* If the character is a right bracket, pop operators off until you reach a left bracket, then pop off the left bracket without * adding it to the string */ else if(*ptoken == ')'){ while(seeOperator() != '('){ *stringToAdd = popOperator(); strcat(str," "); strcat(str, stringToAdd); } popOperator(); } /* Otherwise(i.e. the string is a operand), just catenate the operand to the end of the string */ else{ strcat(str, " "); strcat(str, ptoken); } } /* Check if the operator stack is empty, if it isn't, add the top most operator to the end of the string, repeat until * stack is empty. * If the character is a bracket, then just pop it and don't add to the string. */ while(emptyOperator() == FALSE){ if(seeOperator() == '(' || seeOperator() == ')') popOperator(); else{ *stringToAdd = popOperator(); strcat(str," "); strcat(str, stringToAdd); } } }
/* * This function is used for morph parsing. * * The value is passed to parsetext which will call the right dictionary to * lexize the word. If it turns out to be a stopword, we push a QI_VALSTOP * to the stack. * * All words belonging to the same variant are pushed as an ANDed list, * and different variants are ORred together. */ static void pushval_morph(Datum opaque, TSQueryParserState state, char *strval, int lenval, int2 weight, bool prefix) { int4 count = 0; ParsedText prs; uint32 variant, pos, cntvar = 0, cntpos = 0, cnt = 0; Oid cfg_id = DatumGetObjectId(opaque); /* the input is actually * an Oid, not a pointer */ prs.lenwords = 4; prs.curwords = 0; prs.pos = 0; prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords); parsetext(cfg_id, &prs, strval, lenval); if (prs.curwords > 0) { while (count < prs.curwords) { pos = prs.words[count].pos.pos; cntvar = 0; while (count < prs.curwords && pos == prs.words[count].pos.pos) { variant = prs.words[count].nvariant; cnt = 0; while (count < prs.curwords && pos == prs.words[count].pos.pos && variant == prs.words[count].nvariant) { pushValue(state, prs.words[count].word, prs.words[count].len, weight, ((prs.words[count].flags & TSL_PREFIX) || prefix) ? true : false); pfree(prs.words[count].word); if (cnt) pushOperator(state, OP_AND); cnt++; count++; } if (cntvar) pushOperator(state, OP_OR); cntvar++; } if (cntpos) pushOperator(state, OP_AND); cntpos++; } pfree(prs.words); } else pushStop(state); }
static int QPP_parse(void* word_db, char infix[], int max_infix_size, QueryNode postfix[], int maxNode) { QueryNode quNode; char tmpQueryStr[STRING_SIZE]; int nRet = 0; TokenObj tkObj; StateObj stObj; DEBUG("infix query: [%s]",infix); strncpy(tmpQueryStr,infix,STRING_SIZE-1); tmpQueryStr[STRING_SIZE-1] = '\0'; DEBUG("before tokenizer set string"); tk_setString(&tkObj,tmpQueryStr); stk_init(&(stObj.postfixStack)); stk_init(&(stObj.operatorStack)); stObj.searchField = -1; // search all field stObj.nextTurn = TURN_OPERAND; stObj.posWithinPhrase = FALSE; stObj.numPhraseOperand = 0; stObj.truncated = 0; stObj.virtualfield = 0; stObj.virtualfield_morpid = 20; stObj.natural_search = 0; quNode.original_word[0] = '\0'; // 초기화 DEBUG("before entering while loop"); while (1) { nRet = tk_getNextToken(&tkObj,&quNode,MAX_ORIGINAL_WORD_LEN); DEBUG("got next token nRet [%d], token_string[%s]",nRet, quNode.original_word); // error if (nRet == END_OF_STRING) break; else if (nRet == TOKEN_OVERFLOW) continue; // FIXME warn and push the token to stack.. else if (nRet == 0) continue; // right token switch (nRet) { case TOKEN_STAR: nRet = pushStarredWord(word_db, &stObj,&quNode); break; case TOKEN_NUMERIC: nRet = pushNumeric(&stObj,&quNode); break; case TOKEN_OPERATOR: nRet = pushOperator(&stObj,&quNode); break; default: // case nRet < 0 nRet = pushExtendedOperand(word_db, &stObj,&quNode); break; } if (nRet < 0) break; } DEBUG("stack postfix index is [%d]",stObj.postfixStack.index); // parse된 데이터가 있고, // operator로 끝나서 다음이 operand차례이면 // fake operand를 집어넣는다. if (stObj.postfixStack.index > 0 && stObj.nextTurn ==TURN_OPERAND) { DEBUG("pushing fake operand because stack ended with operator"); pushFakeOperand(&stObj); } nRet = stk_moveTillBottom(&(stObj.operatorStack),&(stObj.postfixStack)); DEBUG("stk_moveTillBottom nRet is (%d)",nRet); nRet = stk_copyQueryNodes(&(stObj.postfixStack),maxNode,postfix); DEBUG("stk_copyQueryNodes nRet is (%d)",nRet); if (nRet == QPP_QUERY_NODE_OVERFLOW) { error("query node overflow. maxNode:%d", maxNode); return QPP_QUERY_NODE_OVERFLOW; } /* if (nRet == QPP_QUERY_NODE_OVERFLOW) { DEBUG("OVERFLOW handling"); return handle_query_overflow(maxNode, postfix); }*/ return stObj.postfixStack.index; }
void OperatorsStack::pushBack(char myOperator) { pushOperator(myOperator, pointer); }
/* * This function is used for morph parsing. * * The value is passed to parsetext which will call the right dictionary to * lexize the word. If it turns out to be a stopword, we push a QI_VALSTOP * to the stack. * * All words belonging to the same variant are pushed as an ANDed list, * and different variants are ORed together. */ static void pushval_morph(Datum opaque, TSQueryParserState state, char *strval, int lenval, int16 weight, bool prefix) { int32 count = 0; ParsedText prs; uint32 variant, pos = 0, cntvar = 0, cntpos = 0, cnt = 0; MorphOpaque *data = (MorphOpaque *) DatumGetPointer(opaque); prs.lenwords = 4; prs.curwords = 0; prs.pos = 0; prs.words = (ParsedWord *) palloc(sizeof(ParsedWord) * prs.lenwords); parsetext(data->cfg_id, &prs, strval, lenval); if (prs.curwords > 0) { while (count < prs.curwords) { /* * Were any stop words removed? If so, fill empty positions with * placeholders linked by an appropriate operator. */ if (pos > 0 && pos + 1 < prs.words[count].pos.pos) { while (pos + 1 < prs.words[count].pos.pos) { /* put placeholders for each missing stop word */ pushStop(state); if (cntpos) pushOperator(state, data->qoperator, 1); cntpos++; pos++; } } /* save current word's position */ pos = prs.words[count].pos.pos; /* Go through all variants obtained from this token */ cntvar = 0; while (count < prs.curwords && pos == prs.words[count].pos.pos) { variant = prs.words[count].nvariant; /* Push all words belonging to the same variant */ cnt = 0; while (count < prs.curwords && pos == prs.words[count].pos.pos && variant == prs.words[count].nvariant) { pushValue(state, prs.words[count].word, prs.words[count].len, weight, ((prs.words[count].flags & TSL_PREFIX) || prefix)); pfree(prs.words[count].word); if (cnt) pushOperator(state, OP_AND, 0); cnt++; count++; } if (cntvar) pushOperator(state, OP_OR, 0); cntvar++; } if (cntpos) { /* distance may be useful */ pushOperator(state, data->qoperator, 1); } cntpos++; } pfree(prs.words); } else pushStop(state); }
ParseStatus Parser::evalExpression() { ParseStatus error = PARSE_OK; while (error == PARSE_OK) { Token t = lex[0]; // Check for terminators if we're not in a nested expression. if (t.isDelimiter()) { if (t.isTerminator() && delimiterDepth == 0) { break; } error = pushDelimiter(t); } if (t.isLiteral()) { error = pushSymbol(t); } if (t.isOperator()) { error = pushOperator(t); } if (!error) lex++; continue; } if (error) return error; return emitEval(); /* Token base = lex[0]; Token op = lex[1]; if (op.isDelimiter(DL_SEMICOLON)) { // either "literal;" or "identifier;" return evalLiteral(); } if (base.isKeyword(KW_FUNCTION)) { return parseFunction(); } if (base.isDelimiter(DL_LPAREN)) { // Tuple return parseTuple(); } if (base.isDelimiter(DL_LBRACE)) { return parseBlock(); } switch(base.type) { case TT_EOF: case TT_INVALID: // Something's broken. assert(false); break; case TT_OPERATOR: // Unary operator assert(false); break; case TT_DELIMITER: // Tuple, array literal, block literal. assert(false); break; case TT_NATIVE: // Static cast to native type. assert(false); break; case TT_IDENTIFIER: // Function call or copy from variable. assert(false); case TT_INTEGER: // Expression starting with integer. assert(false); case TT_FLOAT: assert(false); case TT_RUNE: assert(false); case TT_STRING: assert(false); case TT_DIRECTIVE: assert(false); case TT_COMMENT: assert(false); } assert(false); return PARSE_ERROR; */ }