00001 #include "Kodu/Parsing/Parser.h"
00002 #include "Shared/Gamepad.h"
00003
00004
00005 namespace Kodu {
00006
00007 KoduConditionHear* Parser::KodeCreator::createHearKode(std::vector<TokenBase*>& mods) {
00008 bool ishear = false;
00009 bool usenot = false;
00010 std::string said = "";
00011 std::string objecttype = "";
00012 while (!mods.empty()) {
00013
00014
00015 if (mods[0]->isStringToken()) {
00016 std::string word = mods[0]->getStringData();
00017 said = said + word;
00018 }
00019 if (mods[0]->isKeywordToken()) {
00020 std::string keyword = mods[0]->getKeywordData();
00021 if (keyword == "hear") {
00022 ishear = true;
00023 } else if (keyword == "not") {
00024 usenot = true;
00025 } else if (keyword == "robot" || keyword == "kodu" || keyword == "octopus" || keyword == "cycle" || keyword == "turtle") {
00026 objecttype = keyword;
00027 } else if (keyword == "say") {
00028 PARSER_ASSERT((ishear == true), errorMessage << "what are you trying to hear");
00029 }
00030 }
00031 GeneralFncs::destroyPtrInVector(mods, 0);
00032 }
00033 return (new KoduConditionHear(usenot, objecttype, "", said));
00034 }
00035
00036
00037 KoduConditionGamepad* Parser::KodeCreator::createGamepadKode(std::vector<TokenBase*>& mods) {
00038 bool isButton = false;
00039 bool isBumper = false;
00040
00041 float press = -1;
00042 unsigned int input = 0;
00043 while (!mods.empty()) {
00044
00045 std::string keyword = mods[0]->getKeywordData();
00046
00047 if (mods[0]->isKeywordToken()) {
00048 if (keyword == "button") {
00049 isButton = true;
00050 }
00051 else if (isButton && keyword == "press") {
00052 press = 1;
00053 }
00054 else if (isButton && keyword == "release") {
00055 press = 0;
00056 }
00057 else if (!isButton && keyword == "right") {
00058 isBumper = true;
00059 input = GamepadSrcID::gamepadRightBumperSrcID;
00060 }
00061 else if (!isButton && keyword == "left") {
00062 isBumper = true;
00063 input = GamepadSrcID::gamepadLeftBumperSrcID;
00064 }
00065 else if (!isBumper && keyword == "bumper") {
00066 PARSER_ASSERT(isBumper, errorMessage << "Incorrect usage of bumpers");
00067 }
00068 else if (isButton && !isBumper && keyword == "A") {
00069 input = GamepadSrcID::gamepadAButtonSrcID;
00070 }
00071 else if (isButton && !isBumper && keyword == "B") {
00072 input = GamepadSrcID::gamepadBButtonSrcID;
00073 }
00074 else if (isButton && !isBumper && keyword == "X") {
00075 input = GamepadSrcID::gamepadXButtonSrcID;
00076 }
00077 else if (isButton&& !isBumper && keyword == "Y") {
00078 input = GamepadSrcID::gamepadYButtonSrcID;
00079 }
00080 else if (keyword == "joystick") {
00081 std::cout << "Joystick parsed\n";
00082 }
00083 else if (keyword == "L-stick") {
00084 input = GamepadSrcID::gamepadLeftJoyXSrcID;
00085 }
00086 else
00087 input = -1;
00088 }
00089
00090 else {
00091
00092 PARSER_ASSERT((ERROR),
00093 errorMessage << "The keyword \"" << keyword << "\" cannot be used with the " << "Gamepad condition.");
00094 }
00095
00096 GeneralFncs::destroyPtrInVector(mods, 0);
00097 }
00098 return (new KoduConditionGamepad(input, press));
00099 }
00100
00101 KoduConditionBump* Parser::KodeCreator::createBumpKode(std::vector<TokenBase*>& mods) {
00102
00103 std::string objectType;
00104 std::string objectColor;
00105
00106
00107 SearchLocation_t leftRight = SL_UNRESTRICTED;
00108 SearchLocation_t frontBack = SL_UNRESTRICTED;
00109 bool notEnabled = false;
00110
00111
00112 int tokenCount = 1;
00113
00114
00115
00116 while (!mods.empty()) {
00117
00118 if (mods[0]->isKeywordToken()) {
00119 std::string keyword = mods[0]->getKeywordData();
00120
00121 if (keyword == "apple" || keyword == "rock" || keyword == "tree"
00122 || keyword == "robot" || keyword == "kodu" || keyword == "octopus" || keyword == "cycle" || keyword == "turtle") {
00123
00124 PARSER_ASSERT((objectType.empty()),
00125 errorMessage << "The bump condition only accepts one object type.\n"
00126 << "Previous object found: " << objectType);
00127 objectType = keyword;
00128 }
00129
00130 else if (Parser::isValidColor(keyword)) {
00131
00132 PARSER_ASSERT((objectColor.empty()),
00133 errorMessage << "The bump condition only accepts one color.\n"
00134 << "Previous color found: " << objectColor);
00135 objectColor = keyword;
00136 }
00137
00138 else if (keyword == "in_front" || keyword == "behind") {
00139
00140 PARSER_ASSERT((frontBack == 0),
00141 errorMessage << "A front/back regional specifier was already specified.\n"
00142 << "Second instance found: " << keyword);
00143 if (keyword == "in_front")
00144 frontBack = SL_IN_FRONT;
00145 else
00146 frontBack = SL_BEHIND;
00147 }
00148
00149 else if
00150 (keyword == "to_left" || keyword == "to_right") {
00151
00152 PARSER_ASSERT((leftRight == 0),
00153 errorMessage << "A front/back regional specifier was already specified.\n"
00154 << "Second instance found: " << keyword);
00155 if (keyword == "to_left")
00156 leftRight = SL_TO_LEFT
00157 ;
00158 else
00159 leftRight = SL_TO_RIGHT;
00160 }
00161
00162 else if (keyword == "not") {
00163
00164 PARSER_ASSERT((notEnabled == false),
00165 errorMessage << "The \"not\" modifier was already used in this rule. It can " <<
00166 "only be used once per rule.");
00167 notEnabled = true;
00168 }
00169
00170 else {
00171
00172 PARSER_ASSERT((ERROR),
00173 errorMessage << "The keyword \"" << keyword << "\" cannot be used with the " << "Bump condition.");
00174 }
00175
00176 GeneralFncs::destroyPtrInVector(mods, 0);
00177 }
00178
00179 else {
00180 PARSER_ASSERT((ERROR),
00181 errorMessage << "Token " << tokenCount << " cannot be used with the Bump condition.");
00182 }
00183
00184 tokenCount++;
00185 }
00186
00187 PARSER_ASSERT((!objectType.empty()),
00188 errorMessage << "An object type must be specified (e.g. tree, apple, or rock).");
00189
00190
00191
00192
00193
00194
00195
00196 return (new KoduConditionBump(notEnabled, objectType, objectColor, (frontBack | leftRight)));
00197 }
00198
00199 KoduConditionGot* Parser::KodeCreator::createGotKode(std::vector<TokenBase*>& mods) {
00200
00201 std::string objectType;
00202 std::string objectColor;
00203
00204
00205 bool notEnabled = false;
00206
00207
00208 int tokenCount = 1;
00209
00210
00211 while (!mods.empty()) {
00212
00213 if (mods[0]->isKeywordToken()) {
00214 std::string keyword = mods[0]->getKeywordData();
00215
00216 if (keyword == "apple" || keyword == "rock" || keyword == "tree") {
00217
00218 PARSER_ASSERT((objectType.empty()),
00219 errorMessage << "The Got condition only accepts one object type.\n"
00220 << "Previous object found: " << objectType);
00221 objectType = keyword;
00222 }
00223
00224 else if (Parser::isValidColor(keyword)) {
00225
00226 PARSER_ASSERT((objectColor.empty()),
00227 errorMessage << "The Got condition only accepts one color.\n"
00228 << "Previous color found: " << objectColor);
00229 objectColor = keyword;
00230 }
00231
00232 else if (keyword == "not") {
00233
00234 PARSER_ASSERT((notEnabled == false),
00235 errorMessage << "The \"not\" modifier was already used in this rule. It can " <<
00236 "only be used once per rule.");
00237 notEnabled = true;
00238 }
00239
00240 else {
00241
00242 PARSER_ASSERT((ERROR),
00243 errorMessage << "The keyword \"" << keyword << "\" cannot be used with the "
00244 << "Got condition.");
00245 }
00246
00247 GeneralFncs::destroyPtrInVector(mods, 0);
00248 }
00249
00250 else {
00251 PARSER_ASSERT((ERROR),
00252 errorMessage << "Token " << tokenCount << " cannot be used with the Got condition.");
00253 }
00254
00255 tokenCount++;
00256 }
00257
00258 PARSER_ASSERT((!objectType.empty()),
00259 errorMessage << "An object type must be specified (e.g. tree, apple, or rock).");
00260
00261
00262
00263
00264
00265
00266 return (new KoduConditionGot(notEnabled, objectType, objectColor));
00267 }
00268
00269 KoduConditionSee* Parser::KodeCreator::createSeeKode(std::vector<TokenBase*>& mods) {
00270
00271 std::string objectType;
00272 std::string objectColor;
00273
00274
00275 bool notEnabled = false;
00276 SearchLocation_t leftRight = SL_UNRESTRICTED;
00277 SearchLocation_t frontBack = SL_UNRESTRICTED;
00278 SearchLocation_t closeFar = SL_UNRESTRICTED;
00279
00280
00281 int tokenCount = 1;
00282
00283
00284 while (!mods.empty()) {
00285
00286 if (mods[0]->isKeywordToken()) {
00287 std::string keyword = mods[0]->getKeywordData();
00288
00289 if (keyword == "apple" || keyword == "rock" || keyword == "tree"
00290 || keyword == "robot" || keyword == "kodu" || keyword == "octopus" || keyword == "cycle" || keyword == "turtle") {
00291
00292 PARSER_ASSERT((objectType.empty()),
00293 errorMessage << "The see condition only accepts one object type.\n"
00294 << "Previous object found: " << objectType);
00295 objectType = keyword;
00296 }
00297
00298 else if (Parser::isValidColor(keyword)) {
00299
00300 PARSER_ASSERT((objectColor.empty()),
00301 errorMessage << "The see condition only accepts one color.\n"
00302 << "Previous color found: " << objectColor);
00303 objectColor = keyword;
00304 }
00305
00306 else if (keyword == "in_front" || keyword == "behind") {
00307
00308 PARSER_ASSERT((frontBack == SL_UNRESTRICTED),
00309 errorMessage << "A front/back location specifier was already specified.\n"
00310 << "Second instance found: " << keyword);
00311 if (keyword == "in_front")
00312 frontBack = SL_IN_FRONT;
00313 else
00314 frontBack = SL_BEHIND;
00315 }
00316
00317 else if (keyword == "to_left" || keyword == "to_right") {
00318
00319 PARSER_ASSERT((leftRight == SL_UNRESTRICTED),
00320 errorMessage << "A froSeeKodent/back location specifier was already specified.\n"
00321 << "Second instance found: " << keyword);
00322 if (keyword == "to_left")
00323 leftRight = SL_TO_LEFT;
00324 else
00325 leftRight = SL_TO_RIGHT;
00326 }
00327
00328 else if (keyword == "close_by" || keyword == "far_away") {
00329
00330 PARSER_ASSERT((closeFar == SL_UNRESTRICTED),
00331 errorMessage << "A close_by/far_away location specifier was already specified.\n"
00332 << "Second instance found: " << keyword);
00333 if (keyword == "close_by")
00334 closeFar = SL_CLOSE_BY;
00335 else
00336 closeFar = SL_FAR_AWAY;
00337 }
00338
00339 else if (keyword == "not") {
00340
00341 PARSER_ASSERT((notEnabled == false),
00342 errorMessage << "The \"not\" modifier was already used in this rule. It can " <<
00343 "only be used once per rule.");
00344 notEnabled = true;
00345 }
00346
00347 else {
00348
00349 PARSER_ASSERT((ERROR),
00350 errorMessage << "The keyword \"" << keyword << "\" cannot be used with the "
00351 << "See condition.");
00352 }
00353
00354 GeneralFncs::destroyPtrInVector(mods, 0);
00355 }
00356
00357 else {
00358 PARSER_ASSERT((ERROR),
00359 errorMessage << "Token " << tokenCount << " cannot be used with the See condition.");
00360 }
00361
00362 tokenCount++;
00363 }
00364
00365 PARSER_ASSERT((!objectType.empty()),
00366 errorMessage << "An object type must be specified (e.g. tree, apple, or rock).");
00367
00368
00369
00370
00371
00372
00373
00374
00375 return (new KoduConditionSee(notEnabled, objectType, objectColor, (frontBack | leftRight | closeFar)));
00376
00377 }
00378
00379 KoduConditionScored* Parser::KodeCreator::createScoredKode(std::vector<TokenBase*>& mods) {
00380
00381 NumericGenerator tempNumReq(0, 0);
00382 bool notEnabled = false;
00383 KoduConditionScored::CompareType_t comparisonType(KoduConditionScored::INVALID);
00384 bool comparisonOperatorSet = false;
00385 std::string scoreDesignator;
00386
00387
00388 int tokenCount = 1;
00389 bool handledNumerics = false;
00390
00391
00392 while (!mods.empty()) {
00393
00394 if (isComparisonOperator(mods[0])) {
00395
00396 PARSER_ASSERT((handledNumerics == false),
00397 errorMessage << "A numeric value cannot be specified before an "
00398 << "inequality operator.");
00399
00400 PARSER_ASSERT((comparisonOperatorSet == false),
00401 errorMessage << "The comparison type was already set.");
00402 std::string keyword = mods[0]->getKeywordData();
00403
00404 if (keyword == "equals")
00405 comparisonType = KoduConditionScored::CT_EQUALS;
00406 else if (keyword == "above")
00407 comparisonType = KoduConditionScored::CT_ABOVE;
00408 else if (keyword == "below")
00409 comparisonType = KoduConditionScored::CT_BELOW;
00410 else if (keyword == "not_equals")
00411 comparisonType = KoduConditionScored::CT_NOT_EQUALS;
00412 else if (keyword == ">=")
00413 comparisonType = KoduConditionScored::CT_GT_EQUAL;
00414 else if (keyword == "<=")
00415 comparisonType = KoduConditionScored::CT_LT_EQUAL;
00416 comparisonOperatorSet = true;
00417
00418 GeneralFncs::destroyPtrInVector(mods, 0);
00419 }
00420
00421 else if (isNumericSpecifier(mods[0])) {
00422
00423 PARSER_ASSERT((handledNumerics == false),
00424 errorMessage << "Token " << tokenCount << " is illegal. A numeric "
00425 << "specifier (number and/or random modifiers) was already specified.");
00426
00427
00428 PARSER_ASSERT((numericGenParser(mods, tempNumReq) == true),
00429 errorMessage << "An error occurred while parsing the numeric/random token(s).");
00430
00431 handledNumerics = true;
00432 continue;
00433 }
00434
00435 else if (isScoreDesignator(mods[0])) {
00436 std::string keyword = mods[0]->getKeywordData();
00437
00438 PARSER_ASSERT((scoreDesignator.empty()),
00439 errorMessage << "The scored condition cannot have more than one designator. "
00440 << "Second designator: " << keyword << ".");
00441
00442 scoreDesignator = keyword;
00443 }
00444
00445 else if (mods[0]->isKeywordToken()) {
00446
00447 std::string keyword = mods[0]->getKeywordData();
00448
00449 if (keyword == "not") {
00450
00451 PARSER_ASSERT((notEnabled == false),
00452 errorMessage << "The \"not\" modifier can only be used once.");
00453 notEnabled = true;
00454 }
00455
00456 else {
00457
00458 PARSER_ASSERT((ERROR),
00459 errorMessage << "The keyword \"" << keyword << "\" cannot be used "
00460 << "with the Scored condition.");
00461 }
00462
00463 GeneralFncs::destroyPtrInVector(mods, 0);
00464 }
00465
00466 else {
00467
00468 PARSER_ASSERT((ERROR),
00469 errorMessage << "Token " << tokenCount << " cannot be used with the Scored condition.");
00470 }
00471 tokenCount++;
00472 }
00473
00474 if ( comparisonType == KoduConditionScored::INVALID )
00475 comparisonType = KoduConditionScored::CT_EQUALS;
00476
00477 if (scoreDesignator.empty())
00478 scoreDesignator = Parser::koduDefaultDesignator;
00479
00480 return (new KoduConditionScored(notEnabled, comparisonType, tempNumReq, scoreDesignator, handledNumerics));
00481 }
00482
00483 KoduConditionTimer* Parser::KodeCreator::createTimerKode(std::vector<TokenBase*>& mods) {
00484
00485 PARSER_ASSERT((0 <= mods.size() && mods.size() <= 6),
00486 errorMessage << "The Timer condition should have 0 - 6 modifiers.");
00487
00488
00489 NumericGenerator tempNumReq(0.25, 0);
00490
00491
00492 bool notEnabled = false;
00493
00494
00495 int tokenCount = 1;
00496 bool handledNumerics = false;
00497
00498
00499 while (!mods.empty()) {
00500
00501 if (isNumericSpecifier(mods[0])) {
00502
00503 PARSER_ASSERT((handledNumerics == false),
00504 errorMessage << "Numeric specifiers for this action were already handled. "
00505 << "Token " << tokenCount << " is illegal.");
00506
00507
00508 PARSER_ASSERT((numericGenParser(mods, tempNumReq) == true),
00509 errorMessage << "An error occurred while parsing the numeric specifier token(s) "
00510 << "See above.");
00511
00512 handledNumerics = true;
00513 }
00514
00515 else if (mods[0]->isKeywordToken()) {
00516
00517 std::string keyword = mods[0]->getKeywordData();
00518
00519 if (keyword == "not") {
00520
00521 PARSER_ASSERT((notEnabled == false),
00522 errorMessage << "The \"not\" modifier can only be used once.");
00523 notEnabled = true;
00524 }
00525
00526 else {
00527
00528 PARSER_ASSERT((ERROR),
00529 errorMessage << "The keyword \"" << keyword << "\" cannot be used "
00530 << "with the Timer condition.");
00531 }
00532
00533 GeneralFncs::destroyPtrInVector(mods, 0);
00534 }
00535
00536 else {
00537
00538 PARSER_ASSERT((ERROR),
00539 errorMessage << "Token " << tokenCount << " cannot be used with the Timer condition.");
00540 }
00541 tokenCount++;
00542 }
00543
00544 return (new KoduConditionTimer(notEnabled, tempNumReq));
00545 }
00546 }