/** * Attaches expressions and constraints to the plans. Called by the AlicaEngine during start up. */ void ExpressionHandler::attachAll() { PlanRepository* pr = ae->getPlanRepository(); for (auto it : pr->getPlans()) { auto p = it.second; auto ufGen = utilityCreator->createUtility(p->getId()); p->setUtilityFunction(ufGen->getUtilityFunction(p)); if (p->getPreCondition() != nullptr) { if (p->getPreCondition()->isEnabled()) { p->getPreCondition()->setBasicCondition( this->conditionCreator->createConditions(p->getPreCondition()->getId())); attachConstraint(p->getPreCondition()); } else { p->getPreCondition()->setBasicCondition(make_shared<BasicFalseCondition>()); } } if (p->getRuntimeCondition() != nullptr) { p->getRuntimeCondition()->setBasicCondition( this->conditionCreator->createConditions(p->getRuntimeCondition()->getId())); attachConstraint(p->getRuntimeCondition()); } for (auto t : p->getTransitions()) { if (t->getPreCondition() != nullptr) { if (t->getPreCondition()->isEnabled()) { t->getPreCondition()->setBasicCondition( this->conditionCreator->createConditions(t->getPreCondition()->getId())); attachConstraint(t->getPreCondition()); } else { t->getPreCondition()->setBasicCondition(make_shared<BasicFalseCondition>()); } } } } }
//merges dfas to one dfa for traversal lexer_word_repr* lexer_dfa_builder::mergeDfas(const std::vector<lexer_word_repr*>* const words, DfaManager& dfaManager) const { lexer_word_repr* start = dfaManager.createLexerWordRepr(); //So each JOB consists of: // 1) a ptr to dfa node where we left off in mergeToWord // 2) a transition that we suspect is placeable in mergetToWord // 3) a vector of dfa nodes already visited in mergeTo, this prevents folding the fromDfa back "itself" // but in reality there should be at path dinstinguishing mergeFrom from mergeTo that doesn't visit // a node in MergeTo twice. This only makes sense, because the "going back itself" thing is strictly for // kleen closure like behaviour on runtime. The minimal "description" of automata is actually constant // and doesn't need to have two nodes twice. // repeated. auto jobQueue = new std::vector<std::vector<std::tuple<lexer_dfa*, LexerTransition, std::vector<lexer_dfa*>>>*>(); for (int i = 0; i < words->size(); i++) { auto jobVector = new std::vector<std::tuple<lexer_dfa*, LexerTransition, std::vector<lexer_dfa*>>>(); jobQueue->push_back(jobVector); } std::cout << std::endl << "Merging dfas to one, words size: " << words->size() << std::endl; //iterate through words int jobLineIndex = 0; for (int i =0; i < words->size(); i++) { lexer_dfa* word = words->at(i); std::cout << word << std::endl; std::cout << word->getId() << std::endl; lexer_dfa* mergeToDfaPtr = start; lexer_dfa* mergeFromDfaPtr = word; std::vector<LexerTransition> nextTransitions = mergeFromDfaPtr->getTransitions(); DeLOG("Getting transitions for word\n") for (auto transition : nextTransitions) { DeLOG("Adding job to job Queue\n"); std::tuple<lexer_dfa*, LexerTransition, std::vector<lexer_dfa*>> job(mergeToDfaPtr, transition, std::vector<lexer_dfa*>{}); (jobQueue->at(jobLineIndex))->push_back(job); } jobLineIndex++; } DeLOG(std::string("\nMerge Process: ").append(std::to_string(jobQueue->size())).append(" job lines(queues) total\n").c_str()); for (jobLineIndex = 0; jobLineIndex < jobQueue->size(); jobLineIndex++) { DeLOG(std::string("Processing Job line #").append(std::to_string(jobLineIndex+1)).append("\n").c_str()); auto jobVector = jobQueue->at(jobLineIndex); while (jobVector->size() != 0) { DeLOG(std::string("\nThere are ").append(std::to_string(jobVector->size())).append(" in job vector. Processing Job #").append(std::to_string(jobLineIndex + 1)).append("\n").c_str()); auto currJobTuple = jobVector->back(); jobVector->pop_back(); auto currMergeToDfaPtr = std::get<0>(currJobTuple); //here we'll check the currMergeToDfaPtr against the previously visited ptrs in MergeTo //if we've already visited it, we know to ignore it this transition (and NOT to put job back in queue) auto ptrsInMergeToAlreadyVisited = std::get<2>(currJobTuple); auto skipAndContinue = false; for (auto mergeToDfaPtrVisited : ptrsInMergeToAlreadyVisited) { if (currMergeToDfaPtr == mergeToDfaPtrVisited) { skipAndContinue = true; break; } } if (skipAndContinue) { continue; } ptrsInMergeToAlreadyVisited.push_back(currMergeToDfaPtr); auto transitionFromCurrMergeFromDfaPtr = std::get<1>(currJobTuple); auto nextMergeFromDfaPtr = transitionFromCurrMergeFromDfaPtr.getDfaNode(); const auto si = transitionFromCurrMergeFromDfaPtr.getStateAndInput(); DeLOG(std::string{"si = {"}.append(std::to_string(si.getState())).append(1, si.getInput()).append("}\n").c_str()); auto nextMergeToDfaPtrCandidateInfo1 = currMergeToDfaPtr->getNextDfaForInput(si.getInput(), false); auto nextMergeToDfaPtrCandidateProperties1 = nextMergeToDfaPtrCandidateInfo1.second; auto nextMergeToDfaPtrCandidateInfo2 = currMergeToDfaPtr->getNextDfaForInput(si.getInput(), true); auto nextMergeToDfaPtrCandidateProperties2 = nextMergeToDfaPtrCandidateInfo2.second; //aka mergeFromDfaProperties const auto currentMergeFromTransitionProperties = transitionFromCurrMergeFromDfaPtr.getProperties(); if (checkForProperty(currentMergeFromTransitionProperties, Lexer_Dfa_Properties::ISA_PUSH_DOWN_CONTINUANCE) || checkForProperty(currentMergeFromTransitionProperties, Lexer_Dfa_Properties::ISA_PUSH_DOWN_EJECT)) { //If the transition ~to~ current ~mergeFrom~ dfa has the // properties: PUSH_DOWN_EJECT or PUSH_DOWN_CONTINUANCE, // then we assume we are in a state of recursion. If the // recursive pathway in ~mergeTo~ dfa is not taken, // nextMergeaToDfaPtrCandidatePropertes is 0x0, then we // add the current ~mergeFrom~ dfa (noting that it is for a // recursion (stack-count > 0) to the currMergeToDfa. // If the position is filled, properties != 0x0 in dfaInfo // when we query with param indicating stackCount > 0, // then we push the ~nextMergeTo~ dfa into thejobQueue // (along with the properties of this is not already being // done (like w\ the entire transition)) lexer_dfa* nextMergeToDfaPtr = nullptr; if (nextMergeToDfaPtrCandidateProperties2 != 0x0) { nextMergeToDfaPtr = nextMergeToDfaPtrCandidateInfo2.first; } currMergeToDfaPtr->_printTransitions(); std::cout << "is there nextDfaPtr? " << (nextMergeToDfaPtr != nullptr ? "yes" : "no") << nextMergeToDfaPtr << std::endl; if (nextMergeToDfaPtr == nullptr) { LexerStateAndInput aLexerStateAndInput = transitionFromCurrMergeFromDfaPtr.getStateAndInput(); DeLOG(std::string{"::adding transition(["}.append(std::to_string(aLexerStateAndInput.getState())).append(", '").append(1, aLexerStateAndInput.getInput()).append("']->").append(1, nextMergeFromDfaPtr->getId()).append(") to dfa(").append(1, currMergeToDfaPtr->getId()).append(")\n").c_str()); StateAndInput<int,char> aStateAndInput(aLexerStateAndInput.getState(), aLexerStateAndInput.getInput(), transitionFromCurrMergeFromDfaPtr.getIsRanged()); currMergeToDfaPtr->add_next_dfa(aStateAndInput, nextMergeFromDfaPtr, currentMergeFromTransitionProperties); //Sanity check auto nextMergeToDfaPtrCandidateInfoSanity = currMergeToDfaPtr->getNextDfaForInput(si.getInput(), true); auto nextMergeToDfaPtrCandidatePropertiesSanity = nextMergeToDfaPtrCandidateInfoSanity.second; if (nextMergeToDfaPtrCandidateInfoSanity.first == nullptr) { perror("\nCould not find Node. Exiting.\n"); exit(EXIT_FAILURE); } } else { std::vector<LexerTransition> nextTransitions = nextMergeFromDfaPtr->getTransitions(); for (auto transitionFromNextMergeFromDfa : nextTransitions) { const auto si = transitionFromNextMergeFromDfa.getStateAndInput(); DeLOG(std::string{"Couldn't find an opening, pushing back job { to add ("}.append(std::to_string(si.getState())).append(",").append(1, si.getInput()).append(") from dfa-id(").append(std::to_string(nextMergeToDfaPtr->getId())).append(")\n").c_str()); std::tuple<lexer_dfa*, LexerTransition, std::vector<lexer_dfa*>> job(const_cast<lexer_dfa*>(nextMergeToDfaPtr), transitionFromNextMergeFromDfa, ptrsInMergeToAlreadyVisited); jobVector->push_back(job); } } } else if (checkForProperty(currentMergeFromTransitionProperties, Lexer_Dfa_Properties::ISA_NORMAL) || checkForProperty(currentMergeFromTransitionProperties, Lexer_Dfa_Properties::ISA_PUSH_DOWN_ACTIVATOR)) { //Likewise if the transition ~to~ current ~mergeFrom~ dfa // has the properties: NORMAL or PUSH_DOWN_ACTIVATOR, // then we assume then we assume a non-recursive (even if // by the top top level lexer perspective this has yet to // be determined. If the non-recursive pathway in ~mergeTo~ // dfa is not taken, then we add the current ~mergeTo~ dfa // (noting that it is for a recursion (stack-count > 0). // If the position is filled (non-nullptr) dfa result for // query with stackCount > 0 param, then we push the // ~nextMergeTo~ into thejobQueue. lexer_dfa* nextMergeToDfaPtr = nullptr; if (nextMergeToDfaPtrCandidateProperties1 != 0x0) { nextMergeToDfaPtr = nextMergeToDfaPtrCandidateInfo1.first; } currMergeToDfaPtr->_printTransitions(); std::cout << "is there nextDfaPtr? " << (nextMergeToDfaPtr != nullptr ? "yes" : "no") << nextMergeToDfaPtr << std::endl; if (nextMergeToDfaPtr == nullptr) { LexerStateAndInput aLexerStateAndInput = transitionFromCurrMergeFromDfaPtr.getStateAndInput(); DeLOG(std::string{"::adding transition(["}.append(std::to_string(aLexerStateAndInput.getState())).append(", '").append(1, aLexerStateAndInput.getInput()).append("']->").append(1, nextMergeFromDfaPtr->getId()).append(") to dfa(").append(1, currMergeToDfaPtr->getId()).append(")\n").c_str()); StateAndInput<int,char> aStateAndInput(aLexerStateAndInput.getState(), aLexerStateAndInput.getInput(), transitionFromCurrMergeFromDfaPtr.getIsRanged()); currMergeToDfaPtr->add_next_dfa(aStateAndInput, nextMergeFromDfaPtr, currentMergeFromTransitionProperties); //Sanity check auto nextMergeToDfaPtrCandidateInfoSanity = currMergeToDfaPtr->getNextDfaForInput(si.getInput(), false); auto nextMergeToDfaPtrCandidatePropertiesSanity = nextMergeToDfaPtrCandidateInfoSanity; if (nextMergeToDfaPtrCandidateInfoSanity.first == nullptr) { perror("\nYeah, this is bad. After we just added our new transition to merged rep, we can't query for it. The effect of adding a new transition should be immediate (I don't know why it should ever not be...). Exiting.\n"); exit(EXIT_FAILURE); } } else { std::vector<LexerTransition> nextTransitions = nextMergeFromDfaPtr->getTransitions(); for (auto transitionFromNextMergeFromDfa : nextTransitions) { const auto si = transitionFromNextMergeFromDfa.getStateAndInput(); DeLOG(std::string{"Couldn't find an opening, pushing back job { to add ("}.append(std::to_string(si.getState())).append(",").append(1, si.getInput()).append(") from dfa-id(").append(std::to_string(nextMergeToDfaPtr->getId())).append(")\n").c_str()); std::tuple<lexer_dfa*, LexerTransition, std::vector<lexer_dfa*>> job(const_cast<lexer_dfa*>(nextMergeToDfaPtr), transitionFromNextMergeFromDfa, ptrsInMergeToAlreadyVisited); jobVector->push_back(job); } } } else { std::cout << "Undefined language specification: duplicate lexer words?" << std::endl; exit(1); } } delete jobVector; } delete jobQueue; std::cout << "Finished jobs!" << std::endl << std::endl; return start; }