void CommutativeRExpTest::testStar() { // 0* = 1 CPPUNIT_ASSERT( CommutativeRExp::null().star() == CommutativeRExp::one() ); CPPUNIT_ASSERT( a->star() == CommutativeRExp(CommutativeRExp::Star, std::shared_ptr<CommutativeRExp>(new CommutativeRExp(*a)))); }
// star the whole RExp CommutativeRExp CommutativeRExp::star() const { if(this->type == Star) return *this; // absorb the star else if (this->type == Empty) return one(); // {}* = ε else return CommutativeRExp(Star, std::shared_ptr<CommutativeRExp>(new CommutativeRExp(*this))); // star the element }
void CommutativeRExpTest::testStar() { // 0* = 1 CPPUNIT_ASSERT( CommutativeRExp::null().star() == CommutativeRExp::one() ); CPPUNIT_ASSERT( a->star() == CommutativeRExp(CommutativeRExp::Star, std::shared_ptr<CommutativeRExp>(new CommutativeRExp(*a)))); // a.b^* != a.(a+b)^* CPPUNIT_ASSERT( (*a) * (*b).star() != (*a) * ((*a) + (*b)).star()); }
// try to find a case of xx^* and convert it to x^+ void CommutativeRExp::optimize_starplus() { // we have to be careful, we will modify the set_copy! // loop over all elements in the set and find the stared elements std::shared_ptr<std::multiset<CommutativeRExp>> set_copy(new std::multiset<CommutativeRExp>()); *set_copy = *this->setm; bool changed = false; for(auto it = this->setm->begin(); it != this->setm->end(); ++it) { if(it->type == Star) // we found a stared element { // distinguish on the nested type switch(it->rexp->type) { case Element: // easy, just try to find this element on the outer set, fall through case case Addition: // addition behaves like an element in the original multiplication set { auto elem = set_copy->find(*it->rexp); if(elem != set_copy->end()) { // create x^+ auto plus_elem = CommutativeRExp(Plus, it->rexp); // delete both x and x^* set_copy->erase(*elem); set_copy->erase(*it); // then insert x^+ set_copy->insert(plus_elem); changed = true; } break; } case Multiplication: // more tricky case, because the inner stared elements are distributed in the original multiplication set { bool found_all_elements = true; // for every element in the starred multiplication for(auto it2 = it->rexp->setm->begin(); it2 != it->rexp->setm->end(); ++it2) { auto elem = set_copy->find(*it2); if(elem == set_copy->end()) { found_all_elements = false; break; } } if(found_all_elements) { // create x^+ auto plus_elem = CommutativeRExp(Plus, it->rexp); // delete both x and x^* for(auto it2 = it->rexp->setm->begin(); it2 != it->rexp->setm->end(); ++it2) set_copy->erase(*it2); set_copy->erase(*it); // then insert x^+ set_copy->insert(plus_elem); changed = true; } break; } case Star: // should not happen, fall through case Plus: // no idea, what to do, fall through case Empty: // should not happen assert(false); // we should have been optimizing this, debug more! break; } } } if(changed) this->setm = set_copy; }