// creates a predicate object from an AST parse tree boost::shared_ptr< Predicate > createPredicate( const TreeIter& it ) { std::string op( it->value.begin(), it->value.end() ); if ( it->value.id() == PredicateGrammar::predicateId ) { if ( op == "&&" ) return boost::shared_ptr< Predicate >( new PredicateAnd( createPredicate( it->children.begin() ), createPredicate( it->children.begin() + 1 ) ) ); else if ( op == "||" ) return boost::shared_ptr< Predicate >( new PredicateOr( createPredicate( it->children.begin() ), createPredicate( it->children.begin() + 1 ) ) ); else UBITRACK_THROW( "Bad predicate: " + op ); } else if ( it->value.id() == PredicateGrammar::statementId ) { if ( op == "!" ) return boost::shared_ptr< Predicate >( new PredicateNot( createPredicate( it->children.begin() ) ) ); else UBITRACK_THROW( "Bad statement: " + op ); } else if ( it->value.id() == PredicateGrammar::compOpId ) { if ( it->children.size() == 2 ) return boost::shared_ptr< Predicate >( new PredicateCompare( op, createValue( it->children.begin() ), createValue( it->children.begin() + 1 ) ) ); // hack: spirit prunes empty string constants out of the tree if ( it->children.size() == 1 ) return boost::shared_ptr< Predicate >( new PredicateCompare( op, createValue( it->children.begin() ), boost::shared_ptr< AttributeExpression >( new AttributeExpressionConstant( "" ) ) ) ); UBITRACK_THROW( "Problem with comparison parsing: illegal numer of children" ); } else if ( it->value.id() == PredicateGrammar::predicateFunctionId ) { // parse parameters into vector std::vector< boost::shared_ptr< AttributeExpression > > params; for ( TreeIter itParam = it->children.begin(); itParam != it->children.end(); itParam++ ) params.push_back( createValue( itParam ) ); return boost::shared_ptr< Predicate >( new PredicateFunction( op, params ) ); } else { UBITRACK_THROW( "bad predicate" ); } }
/* * Caller is responsible for deleting returned Predicate* if necessary */ Predicate* Domain::getNonEvidenceAtom(const int& index) const { int predId = -1; int numAtomsPerPred; int numAtoms = 0; for (int i = 0; i < getNumPredicates(); i++) { numAtomsPerPred = (*numNonEvidAtomsPerPred_)[i]; if (numAtoms + numAtomsPerPred >= index + 1) { predId = i; break; } numAtoms += numAtomsPerPred; } assert(predId >= 0); // Get the newIndex-th grounding of f.o. pred with id predId Predicate* pred = createPredicate(predId, false); // Not all groundings of pred are non-evidence, so we need the while loop bool foundNE = false; while(!foundNE) { for (int i = 0; i < pred->getNumTerms(); i++) { int termType = pred->getTermTypeAsInt(i); const Array<int>* constantsByType = getConstantsByType(termType); int constIdx = random() % constantsByType->size(); pred->setTermToConstant(i, (*constantsByType)[constIdx]); } assert(pred->isGrounded()); if (!db_->getEvidenceStatus(pred)) foundNE = true; } return pred; }
//Caller is responsible for deleting Array and its contents void Domain::createPredicates(Array<Predicate*>* const & preds, const bool& includeEqualPreds) const { for (int i = 0; i < getNumPredicates(); i++) { Predicate* p = createPredicate(i, includeEqualPreds); if (p) preds->append(p); } }
//Caller is responsible for deleting Array and its contents void Domain::createPredicates(Array<Predicate*>* const & preds, const Array<string>* const & predNames) { for (int i = 0; i < predNames->size(); i++) { int predId = getPredicateId((*predNames)[i].c_str()); Predicate* p = createPredicate(predId, true); if (p) preds->append(p); } }
std::shared_ptr<Operand> PredicateParser::createOperand(const std::string& fullExpression, int idxOpFrom, int idxOpTo, size_t from, size_t to) { auto pPredicate = createPredicate(fullExpression, idxOpFrom, idxOpTo, from, to); auto pOperand = std::dynamic_pointer_cast<Operand>(pPredicate); if(nullptr != pOperand) { return pOperand; } else { return std::make_shared<PredicateOperand>(pPredicate); } }
std::shared_ptr<Predicate> PredicateParser::createPredicate(const std::string& fullExpression, int idxOpFrom, int idxOpTo, size_t from, size_t to) { if(idxOpFrom >= idxOpTo) { unpackBrackets(fullExpression, from, to); PredicateParser childParaser(false); childParaser.parse(fullExpression, from, to); return childParaser.getResult(); } else { auto idxLowerest = idxOpFrom; for(auto idxCur = idxLowerest + 1; idxCur < idxOpTo; ++idxCur) { if(mOperators[idxLowerest] > mOperators[idxCur]) { idxLowerest = idxCur; } } auto& opInfo = mOperators[idxLowerest]; if(mOperators[idxLowerest].isUnary()) { auto pChild = createPredicate(fullExpression, idxLowerest + 1, idxOpTo, opInfo.to, to); auto pUnary = createUnary(opInfo, pChild); return pUnary; } else { auto leftFrom = from; auto rightTo = to; auto pArthemetic = createArthemeticOp(opInfo); if(nullptr != pArthemetic) { auto pLeft = createOperand(fullExpression, idxOpFrom, idxLowerest, leftFrom, opInfo.from); auto pRight = createOperand(fullExpression, idxLowerest + 1, idxOpTo, opInfo.to, rightTo); pArthemetic->setLeft(pLeft); pArthemetic->setRight(pRight); return pArthemetic; } auto pCompare = createCompOp(opInfo); if(nullptr != pCompare) { auto pLeft = createOperand(fullExpression, idxOpFrom, idxLowerest, leftFrom, opInfo.from); auto pRight = createOperand(fullExpression, idxLowerest + 1, idxOpTo, opInfo.to, rightTo); pCompare->setLeft(pLeft); pCompare->setRight(pRight); return pCompare; } auto pLogic = createLogicOp(opInfo); if(nullptr != pLogic) { auto pLeft = createPredicate(fullExpression, idxOpFrom, idxLowerest, leftFrom, opInfo.from); auto pRight = createPredicate(fullExpression, idxLowerest + 1, idxOpTo, opInfo.to, rightTo); pLogic->setLeft(pLeft); pLogic->setRight(pRight); return pLogic; } throw std::logic_error("unknow operator"); } } }
void PredicateParser::parse(const std::string& fullExpression, size_t& fromPos, size_t endPos) { assert(0 != fromPos); std::stack<char> unmatched; if(mRootParser) { unmatched.push('{'); ++fromPos; } fromPos = skipSpace(fullExpression, fromPos, endPos); auto oldFrom = fromPos; size_t outerSize = unmatched.size(); for(; fromPos < endPos && !(mRootParser && unmatched.empty()); ++fromPos) { char c = fullExpression.at(fromPos); if(!matchRange(unmatched, fullExpression, fromPos, endPos) && outerSize == unmatched.size()) { switch(c) { case '=': parseEqual(fullExpression, fromPos); break; case '!': parseNonEqual(fullExpression, fromPos); break; case '>': parseGreat(fullExpression, fromPos); break; case '<': parseLess(fullExpression, fromPos); break; case '^': parseStartsWith(fullExpression, fromPos); break; case '$': parseEndsWith(fullExpression, fromPos); break; case '*': parseContains(fullExpression, fromPos); break; case '~': parseMatch(fullExpression, fromPos); break; case '&': parseAnd(fullExpression, fromPos); break; case '|': parseOr(fullExpression, fromPos); break; case '+': mOperators.emplace_back(OpInfo{OpInfo::Add, fromPos, fromPos + 1, mOperators.size()}); break; case '-': { size_t lastOpEnd = mOperators.empty() ? oldFrom : mOperators.back().to; int from = fromPos - 1; bool isMinus = isSpace(fullExpression, from , lastOpEnd - 1, -1); if(isMinus) { mOperators.emplace_back(OpInfo{OpInfo::Minus, fromPos, fromPos + 1, mOperators.size()}); } else { mOperators.emplace_back(OpInfo{OpInfo::Sub, fromPos, fromPos + 1, mOperators.size()}); } break; } case '/': { auto lastOp = mOperators.empty() ? nullptr : &mOperators.back(); size_t lastOpEnd = nullptr == lastOp ? oldFrom : lastOp->to; int from = fromPos - 1; bool allSpace = isSpace(fullExpression, from , lastOpEnd - 1, -1); if(nullptr != lastOp && (lastOp->op >= OpInfo::Match) && (lastOp->op <= OpInfo::iNotMatch) && lastOp->to == (from - 1)) { } if((oldFrom != fromPos) && (mOperators.empty() || (mOperators.back().op < OpInfo::Match) && (mOperators.back().op > OpInfo::iNotMatch))) { mOperators.emplace_back(OpInfo{OpInfo::Div, fromPos, fromPos + 1, mOperators.size()}); } else { fromPos = skip2(fullExpression, fromPos + 1, '/', endPos) + 1; } } break; case '%': mOperators.emplace_back(OpInfo{OpInfo::Mod, fromPos, fromPos + 1, mOperators.size()}); break; default: break; } }//match range }//foreach char auto newEnd = fromPos - (mRootParser ? 1 : 0); if(mOperators.empty() && '(' != fullExpression.at(oldFrom)) { auto pOperand = createPrimitive(fullExpression, oldFrom, newEnd); mResult = pOperand; } else { auto pPredicate = createPredicate(fullExpression, 0, mOperators.size(), oldFrom, newEnd); mResult = pPredicate; } }