Tekkotsu Homepage
Demos
Overview
Downloads
Dev. Resources
Reference
Credits

KodeCreator.cc

Go to the documentation of this file.
00001 #include "Kodu/Parsing/Parser.h"
00002 #include "Kodu/Primitives/KoduCondition.h"
00003 #include "Kodu/Primitives/KoduAction.h"
00004 
00005 namespace Kodu {
00006         
00007     bool Parser::KodeCreator::createKode(const std::vector<ParsedPage*>& tempPages,
00008         std::vector<KoduPage*>& koduPages)
00009     {
00010         // main kode parsing loop
00011         const std::size_t kTempPagesSize = tempPages.size();
00012         for (std::size_t pgIndex = 0; pgIndex < kTempPagesSize; pgIndex++) {
00013             // get the current page
00014             ParsedPage* tempPage = NULL;
00015 
00016             // used to check if and record that a page needs vision
00017             bool currentPageRequiresVision = false;
00018 
00019             // ASSERTION: the current page should not be NULL
00020             PARSER_ASSERT(((tempPage = tempPages[pgIndex]) != NULL),
00021                 errorMessage << "Temp page[" << pgIndex << "] is NULL!");
00022 
00023             // create a Kodu page
00024             KoduPage* koduPage = NULL;
00025 
00026             // ASSERTION: A new Kodu page was created successfully
00027             PARSER_ASSERT(((koduPage = new KoduPage(tempPage->getPageNumber())) != NULL),
00028                 errorMessage << "An error occurred while trying to create a new Kodu page\n");
00029             
00030             // std::cout << "Created a page: PAGE " << koduPage->getPageNumber() << std::endl;
00031             // create the rules for the current page
00032             const std::size_t kRuleCount = tempPage->getRuleCount();
00033             for (std::size_t rIndex = 0; rIndex < kRuleCount; rIndex++) {
00034                 ParsedRule* tempRule = NULL;
00035                 KoduAction* koduAction = NULL;
00036                 KoduCondition* koduCondition = NULL;
00037 
00038                 // ASSERTION: the current rule should not be NULL
00039                 PARSER_ASSERT(((tempRule = tempPage->getRuleInPos(rIndex)) != NULL),
00040                     errorMessage << "Temp page[" << pgIndex << "], Temp Rule[" << rIndex
00041                     << "] is NULL!");
00042                 
00043                 int ruleNumber = tempRule->getRuleNumber();
00044                 int parentNumber = tempRule->getParentNumber();
00045 
00046                 // create the Kodu condition
00047                 // ASSERTION: The condition was successfully created
00048                 PARSER_ASSERT(((koduCondition = getConditionKode(tempRule->getConditionPhrase())) != NULL),
00049                     errorMessage << "An error occurred while trying to create the condition for "
00050                     << "rule " << ruleNumber << ". See above.");
00051                 
00052                 // create the Kodu action
00053                 // ASSERTION: The action was successfully created
00054                 PARSER_ASSERT(((koduAction = getActionKode(tempRule->getActionPhrase())) != NULL),
00055                     errorMessage << "An error occurred while trying to create the action for "
00056                     << "rule " << ruleNumber << ". See above.");
00057                 
00058                 // create a Kodu rule (object) and add the condition and action to it
00059                 KoduRule* koduRule = NULL;
00060 
00061                 // ASSERTION: The Kodu rule was created successfully
00062                 PARSER_ASSERT(((koduRule = new KoduRule(ruleNumber, parentNumber)) != NULL),
00063                     errorMessage << "An error occurred while trying to create a Kodu rule.");
00064 
00065                 koduRule->condition = koduCondition;
00066                 koduRule->action = koduAction;
00067                 // std::cout << "Created Kodu Rule (" << koduRule->getRuleNumber() << ". " 
00068                 //          << koduCondition->getPrimitiveType() << " + " << koduAction->getPrimitiveType() << ").\n";
00069 
00070                 // add the newly created rule to the page
00071                 koduPage->addKoduRule(koduRule);
00072                 // std::cout << "Added Kodu Rule " << koduRule->getRuleNumber()
00073                 //           << " to Page " << koduPage->getPageNumber() << ".\n";
00074 
00075                 // check if this page requires vision
00076                 if (currentPageRequiresVision == false) {
00077                     // check if the condition is see
00078                     if ((koduRule->condition->getConditionType() == KoduCondition::CT_SEE)
00079                         // check if the condition is bump
00080                         || (koduRule->condition->getConditionType() == KoduCondition::CT_BUMP)
00081                         // check if the action is move (and not turn)
00082                         || (koduRule->action->getActionType() == KoduAction::AT_MOTION
00083                             && static_cast<KoduActionMotion*>(koduRule->action)->motionTypeIsMove())
00084                         // check if the action is grab
00085                         || (koduRule->action->getActionType() == KoduAction::AT_GRAB))
00086                     {
00087                         // if any of the above statements is true, then the page requires vision
00088                         currentPageRequiresVision = true;
00089                         koduPage->setPageRequiresVision(true);
00090                     }
00091                 }
00092                 
00093                 // bookkeeping
00094                 tempRule = NULL;
00095                 koduAction = NULL;
00096                 koduCondition = NULL;
00097                 koduRule = NULL;
00098             }
00099             // add the newly created Kodu page to the Kodu pages vector
00100             koduPages.push_back(koduPage);
00101             // std::cout << "Added Kodu Page " << koduPage->getPageNumber() << " to the Pages vector.\n";
00102 
00103             // bookkeeping
00104             tempPage = NULL;
00105             koduPage = NULL;
00106         }
00107         return true;
00108     }
00109 
00110     KoduCondition* Parser::KodeCreator::getConditionKode(ParsedPhrase* tempCondition) {
00111         // ASSERTION: The Phrase pointer is not NULL
00112         PARSER_ASSERT((tempCondition != NULL),
00113             errorMessage << "The variable that (temporarily) holds the parsed action is NULL!");
00114 
00115         // get the head of the phrase (the condition type)
00116         std::string conditionStr = tempCondition->getPhraseHead()->getKeywordData();
00117 
00118         // the condition that will be returned
00119         KoduCondition* condition = NULL;
00120 
00121         // Kodu Condition Always
00122         if (conditionStr == "always") {
00123             PARSER_ASSERT(((condition = new KoduConditionAlways()) != NULL),
00124                 errorMessage << "An error occurred while trying to create the Kodu Condition Always.\n");
00125             // return the condition immediately (there is no need to do any else for the condition)
00126             std::cout << "Created Always condition...\n";
00127             return condition;
00128         }
00129         
00130         // get the modifiers for a phrase (only called if the condition is not of type Kodu Conditon Always)
00131         std::vector<TokenBase*> tempModifiers = tempCondition->getPhraseModifiers();
00132 
00133         // Kodu Condition Bump
00134         if (conditionStr == "bump") {
00135             // ASSERTION: the Kodu bump condition was successfully created
00136             PARSER_ASSERT(((condition = createBumpKode(tempModifiers)) != NULL),
00137                 errorMessage << "An error occurred while trying to create the Bump condition. "
00138                 << "See above.");
00139             std::cout << "Created Bump condition...\n";
00140         }
00141 
00142         // Kodu Condition Got
00143         else if (conditionStr == "got") {
00144             // ASSERTION: the Kodu got condition was successfully created
00145             PARSER_ASSERT(((condition = createGotKode(tempModifiers)) != NULL),
00146                 errorMessage << "An error occurred while trying to create the Got condition. "
00147                 << "See above.");
00148             std::cout << "Created Got condition...\n";
00149         }
00150 
00151         // Kodu Condition See
00152         else if (conditionStr == "see") {
00153             // ASSERTION: the Kodu see condition was succesfully created
00154             PARSER_ASSERT(((condition = createSeeKode(tempModifiers)) != NULL),
00155                 errorMessage << "An error occurred while trying to create the See condition. "
00156                 << "See above.");
00157             // std::cout << "Created See condition...\n";
00158         }
00159         else  if (conditionStr == "hear") {
00160      PARSER_ASSERT(((condition = createHearKode(tempModifiers)) != NULL),
00161                 errorMessage << "An error occurred while trying to create the Hear condition. "
00162                 << "See above.");
00163             std::cout << "Created Hear condition...\n";
00164   }
00165 
00166         // Kodu Condition Scored
00167         else if (conditionStr == "scored") {
00168             // ASSERTION: the Kodu scored condition was successfully created
00169             PARSER_ASSERT(((condition = createScoredKode(tempModifiers)) != NULL),
00170                 errorMessage << "An error occurred while trying to create the Scored condition. "
00171                 << "See above.");
00172             std::cout << "Created Scored condition...\n";
00173         }
00174         // Kodu Timer Condition
00175         else if (conditionStr == "timer") {
00176             // ASSERTION: the Kodu timer condition was successfully created
00177             PARSER_ASSERT(((condition = createTimerKode(tempModifiers)) != NULL),
00178                 errorMessage << "An error occurred while trying to create the Timer condition. See above.");
00179             std::cout << "Created Timer condition...\n";
00180         } else if (conditionStr == "gamepad") {
00181           PARSER_ASSERT(((condition = createGamepadKode(tempModifiers)) != NULL),
00182                         errorMessage << "An error occured creating joystick event");
00183           std::cout << "Created Gamepad condition...\n";
00184         } 
00185         // The user did not use a recognized condition
00186         else {
00187             PARSER_ASSERT((ERROR),
00188                 errorMessage << "The keyword \"" << conditionStr
00189                 << "\" is not a recognized condition.");
00190 
00191         }
00192         return condition;
00193     }
00194 
00195     KoduAction* Parser::KodeCreator::getActionKode(ParsedPhrase* tempAction) {
00196         // ASSERTION: The Phrase pointer is not NULL
00197         PARSER_ASSERT((tempAction != NULL),
00198             errorMessage << "The variable that (temporarily) hold the parsed action is NULL!");
00199 
00200         // get the head of the phrase (the action type)
00201         std::string actionStr = tempAction->getPhraseHead()->getKeywordData();
00202         
00203         // the action that will be returned
00204         KoduAction* action = NULL;
00205 
00206         // Kodu Action Do Nothing
00207         if (actionStr == "do_nothing") {
00208             PARSER_ASSERT(((action = new KoduActionDoNothing()) != NULL),
00209                 errorMessage << "An error occurred while trying to create the Do Nothing action.");
00210             std::cout << "Created Do Nothing action...\n";
00211             // return the action immediately (there is no need to do any else for the action)
00212             return action;
00213         }
00214 
00215         // get the modifiers for a phrase
00216         std::vector<TokenBase*> tempModifiers = tempAction->getPhraseModifiers();
00217         // Kodu Action Give
00218         if (actionStr == "give"){
00219              PARSER_ASSERT(((action = createGiveKode(tempModifiers)) != NULL),
00220                 errorMessage << "An error occurred while trying to create the Give action. "
00221                 << "See above.");
00222              std::cout << "Created Give Action...\n";
00223 
00224         }
00225         // Kodu Action Drop
00226         else if (actionStr == "drop") {
00227             // ASSERTION: The Kodu grab action was successfully created
00228             PARSER_ASSERT(((action = createDropKode(tempModifiers)) != NULL),
00229                 errorMessage << "An error occurred while trying to create the Drop action. "
00230                 << "See above.");
00231             std::cout << "Created Drop action...\n";
00232         }
00233         // Kodu Action Grab
00234         else if (actionStr == "grab") {
00235             // ASSERTION: The Kodu grab action was successfully created
00236             PARSER_ASSERT(((action = createGrabKode(tempModifiers)) != NULL),
00237                 errorMessage << "An error occurred while trying to create the Grab action. "
00238                 << "See above.");
00239             std::cout << "Created Grab action...\n";
00240         }
00241         // Kodu Action Motion (Move)
00242         else if (actionStr == "move") {
00243             // ASSERTION: The Kodu motion (move) action was successfully created
00244             PARSER_ASSERT(((action = createMoveKode(tempModifiers)) != NULL),
00245                 errorMessage << "An error occurred while trying to create the Move (Motion) action. "
00246                 << "See above.");
00247             // std::cout << "Created Move (Motion) action...\n";
00248         }
00249         // Kodu Action Play
00250         else if (actionStr == "play") {
00251             // ASSERTION: The Kodu play action was successfully created
00252             PARSER_ASSERT(((action = createPlayKode(tempModifiers)) != NULL),
00253                 errorMessage << "An error occurred while trying to create the Play action. "
00254                 << "See above.");
00255             std::cout << "Created Play action...\n";
00256         }
00257         // Kodu Action Say
00258         else if (actionStr == "say") {
00259             // ASSERTION: The Kodu say action was successfully created
00260             PARSER_ASSERT(((action = createSayKode(tempModifiers)) != NULL),
00261                 errorMessage << "An error occurred while trying to create the Say action. "
00262                 << "See above.");
00263             std::cout << "Created Say action...\n";
00264         }
00265         // Kodu Action Score/Set Score/Subtract
00266         else if (actionStr == "score" || actionStr == "set_score" || actionStr == "subtract") {
00267             // ASSERTION: The Scoring action was successfully created
00268             PARSER_ASSERT(((action = createScoreKode(actionStr, tempModifiers)) != NULL),
00269                 errorMessage << "An error occurred while trying to create the "
00270                 << "Score/Set Score/Subtract action. See above.");
00271             std::cout << "Created Scoring (score | set score | subtract) action...\n";
00272         }
00273         // Kodu Action Switch to Page (does not need to be parsed)
00274         else if (actionStr == "switch_to_page") {
00275             int pageNumb = static_cast<int>(tempAction->getPhraseModifiers()[0]->getNumericData());
00276             PARSER_ASSERT(((action = new KoduActionPageSwitch(NumericGenerator(pageNumb, 0))) != NULL),
00277                 errorMessage << "An error occurred while trying to create the Page Switch action.");
00278             std::cout << "Created Page Switch action...\n";
00279         }
00280         // Kodu Action Motion (Turn)
00281         else if (actionStr == "turn") {
00282             // ASSERTION: The Kodu motion (turn) action was successfully created
00283             PARSER_ASSERT(((action = createTurnKode(tempModifiers)) != NULL),
00284                 errorMessage << "An error occurred while trying to create the Turn (Motion) action. "
00285                 << "See above.");
00286             std::cout << "Created Turn (Motion) action...\n";
00287         }
00288         // The user did not use a recognized action
00289         else {
00290             // ASSERTION: The user did not use a recognized action
00291             PARSER_ASSERT((ERROR),
00292                 errorMessage << "The keyword \"" << actionStr << "\" is not a recognized action.");
00293         }
00294         return action;
00295     }
00296 
00297     bool Parser::KodeCreator::isComparisonOperator(TokenBase* mod) {
00298         return (mod != NULL && mod->isKeywordToken()
00299             && Parser::isValidComparisonOperator(mod->getKeywordData()));
00300     }
00301 
00302     bool Parser::KodeCreator::isScoreDesignator(TokenBase* mod) {
00303         return (mod != NULL && mod->isKeywordToken()
00304             && (Parser::isValidColor(mod->getKeywordData())
00305                 || Parser::isValidScoreLetter(mod->getKeywordData())));
00306     }
00307 
00308     bool Parser::KodeCreator::isNumericSpecifier(TokenBase* mod) {
00309         return (mod != NULL
00310             && (mod->isNumericToken() || (mod->isKeywordToken() && mod->getKeywordData() == "random")));
00311     }
00312 
00313     bool Parser::KodeCreator::numericGenParser(std::vector<TokenBase*>& mods, NumericGenerator& numgen) {
00314         float constOrModuloDivisor = -1.0f;
00315         float moduloDivisor = -1.0f;
00316         bool prevTokenWasNumeric = false;
00317         bool randomKeywordFound = false;
00318         bool randomTokenWasFoundBeforeNumericToken = false;
00319 
00320         // loop until the current token is not a numeric or keyword token
00321         while (!mods.empty() && (mods[0]->isNumericToken() || mods[0]->isKeywordToken())) {
00322             // check to see if the current token is numeric
00323             if (mods[0]->isNumericToken()) {
00324                 // ASSERTION: The previous token was not a numeric token
00325                 PARSER_ASSERT((!prevTokenWasNumeric),
00326                     errorMessage << "A numeric token cannot succeed another numeric token. "
00327                     "Token \"" << mods[0]->getNumericData() << "\" caused the error.");
00328                 // check if this is the first numeric token
00329                 if (constOrModuloDivisor < 0.0f) {
00330                     // assign the first constant/upper bound found
00331                     constOrModuloDivisor = mods[0]->getNumericData();
00332                     // used to check if the next token is numeric
00333                     prevTokenWasNumeric = true;
00334                 } else if (moduloDivisor < 0.0f) {
00335                     // set the upper bound
00336                     moduloDivisor = mods[0]->getNumericData();
00337                     prevTokenWasNumeric = true;
00338                 }
00339             }
00340             // it has to be a keyword token
00341             else {
00342                 if (mods[0]->getKeywordData() == "random") {
00343                     // ASSERTION: The random token was not already found
00344                     PARSER_ASSERT((!randomKeywordFound),
00345                         errorMessage << "Only one random modifier is allowed in an action or a condition.");
00346                     // note that the "random" keyword was found
00347                     randomKeywordFound = true;
00348                     // note that the previous token is not numeric
00349                     prevTokenWasNumeric = false;
00350                     // if the random modifier was found before the numeric token, then do the following
00351                     if (constOrModuloDivisor < 0.0f) {
00352                         randomTokenWasFoundBeforeNumericToken = true;
00353                     }
00354                 } else {
00355                     // the keyword is something else which SHOULD signal there is nothing for this
00356                     // parsing function to handle
00357                     break;
00358                 }
00359             }
00360             // bookkeeping and prevent infinite looping
00361             GeneralFncs::destroyPtrInVector(mods, 0);
00362         }
00363         // create the numeric request
00364         // check if the random keyword was found
00365         if (randomKeywordFound) {
00366             // if an upper bound was set along with a constant, do the following (pattern: ## random ##)
00367             if (moduloDivisor >= 0.0f) {
00368                 numgen.setNumericValues(constOrModuloDivisor, moduloDivisor);
00369             }
00370 
00371             else if (constOrModuloDivisor >= 0.0f) {
00372                 // the random token was found before the numeric token (pattern: random ##)
00373                 if (randomTokenWasFoundBeforeNumericToken) {
00374                     numgen.setNumericValues(0.0f, constOrModuloDivisor);
00375                 }
00376                 // the random token was found after the numeric token (pattern: ## random)
00377                 else {
00378                     numgen.setNumericValues(constOrModuloDivisor, 5.0f);
00379                 }
00380             }
00381             // no numeric tokens were found and it is the standalone random modifier (pattern: random)
00382             else {
00383                 numgen.setNumericValues(0.0f, 5.0f);
00384             }
00385         }
00386         // no random keyword was found, so the number found must only be a numeric constant (pattern: ##)
00387         else {
00388             numgen.setNumericValues(constOrModuloDivisor, 0.0f);
00389         }
00390         return true;
00391     }
00392 }

Tekkotsu v5.1CVS
Generated Mon May 9 04:58:42 2016 by Doxygen 1.6.3