00001 #include "Kodu/Parsing/Parser.h"
00002
00003 namespace Kodu {
00004 KoduActionGive* Parser::KodeCreator::createGiveKode(std::vector<TokenBase*>& mods){
00005
00006
00007 return (new KoduActionGive());
00008 }
00009
00010 KoduActionDrop* Parser::KodeCreator::createDropKode(std::vector<TokenBase*>& mods) {
00011
00012 PARSER_ASSERT((mods.size() == 0),
00013 errorMessage << "The Drop action should have 0 tokens.");
00014
00015
00016 return (new KoduActionDrop());
00017 }
00018
00019 KoduActionGrab* Parser::KodeCreator::createGrabKode(std::vector<TokenBase*>& mods) {
00020
00021
00022 PARSER_ASSERT((0 <= mods.size() && mods.size() <= 2),
00023 errorMessage << "The Grab action should have 1 - 2 tokens.");
00024
00025
00026
00027 bool itModifierWasSpecified = false;
00028
00029
00030 bool onceEnabled = false;
00031
00032
00033 int tokenCount = 1;
00034
00035
00036 while (!mods.empty()) {
00037
00038 if (mods[0]->isKeywordToken()) {
00039 std::string keyword = mods[0]->getKeywordData();
00040 if (keyword == "once") { KoduState state;
00041
00042
00043 PARSER_ASSERT((onceEnabled == false),
00044 errorMessage << "Found a second once modifier (only one is allowed).");
00045 onceEnabled = true;
00046 }
00047
00048 else if (keyword == "it") {
00049
00050 PARSER_ASSERT((itModifierWasSpecified == false),
00051 errorMessage << "Found a second it modifier (only one is allowed).");
00052 itModifierWasSpecified = true;
00053 }
00054
00055 else {
00056
00057 PARSER_ASSERT((ERROR),
00058 errorMessage << "The keyword \"" << keyword
00059 << "\" cannot be used for the grab action.");
00060 }
00061 }
00062
00063 else {
00064
00065 PARSER_ASSERT((ERROR),
00066 errorMessage << "Failed to recognize token " << tokenCount
00067 << " for the grab action.");
00068 }
00069
00070 GeneralFncs::destroyPtrInVector(mods, 0);
00071 tokenCount++;
00072 }
00073 if(itModifierWasSpecified == false)
00074 itModifierWasSpecified = true;
00075
00076
00077
00078
00079
00080
00081 return (new KoduActionGrab(itModifierWasSpecified, onceEnabled));
00082 }
00083
00084 KoduActionMotion* Parser::KodeCreator::createMoveKode(std::vector<TokenBase*>& mods) {
00085
00086 PARSER_ASSERT((0 <= mods.size() && mods.size() <= 5),
00087 errorMessage << "The Move action should only have 0 - 5 tokens.");
00088
00089
00090 KoduActionMotion::MotionType_t motionType = KoduActionMotion::MT_MOVE_GAMEPAD;
00091 KoduActionMotion::MotionRate_t motionRate;
00092 std::string tempMotionRate;
00093 unsigned int motionRateCount = 0;
00094
00095
00096 int tokenCount = 1;
00097 bool parsedMotionType = false;
00098 bool parsedMotionRate = false;
00099 bool parsedDriven = false;
00100
00101
00102 while (!mods.empty()) {
00103
00104 if (mods[0]->isKeywordToken()) {
00105 std::string keyword = mods[0]->getKeywordData();
00106
00107 if (keyword == "quickly" || keyword == "slowly") {
00108 if (parsedMotionRate) {
00109
00110 motionType = KoduActionMotion::MT_MOVE_WANDER;
00111 PARSER_ASSERT((motionRateCount <= 3),
00112 errorMessage << "The move action can only have up to 3 rate specifiers.\n");
00113
00114
00115 PARSER_ASSERT((keyword == tempMotionRate),
00116 errorMessage << "Different types of rate specifiers cannot be used.\n"
00117 << "First type seen: " << tempMotionRate << "\nSecond type seen: "
00118 << keyword);
00119 } else {
00120 tempMotionRate = keyword;
00121 parsedMotionRate = true;
00122 }
00123
00124 motionRateCount++;
00125 }
00126
00127 else if (keyword == "move"){
00128 motionType = KoduActionMotion::MT_MOVE_GAMEPAD;
00129 parsedMotionType = true;
00130 parsedDriven = true;
00131 }
00132
00133 else if (keyword == "wander" || keyword == "forward" || keyword == "towards") {
00134
00135 PARSER_ASSERT((parsedMotionType == false),
00136 errorMessage << "A mowas already selected (There can only "
00137 << "be one). Secowanderwandernd move type found: " << keyword << ".");
00138 PARSER_ASSERT((parsedDriven == false),
00139 errorMessage << "A move type for this action cannot be executed");
00140 if (keyword == "wander")
00141 motionType = KoduActionMotion::MT_MOVE_WANDER;
00142 else if (keyword == "forward")
00143 motionType = KoduActionMotion::MT_MOVE_FORWARD;
00144 else if (keyword == "towards")
00145 motionType = KoduActionMotion::MT_MOVE_TOWARDS;
00146 parsedMotionType = true;
00147 }
00148
00149 else {
00150
00151 PARSER_ASSERT((ERROR),
00152 errorMessage << "The keyword \"" << keyword
00153 << "\" cannot be used with the move action.");
00154 }
00155 }
00156
00157 else {
00158
00159 PARSER_ASSERT((ERROR),
00160 errorMessage << "Token " << tokenCount << " is unrecognized and cannot be used "
00161 << "with the move action.");
00162 }
00163
00164
00165 GeneralFncs::destroyPtrInVector(mods, 0);
00166 }
00167
00168 if (!parsedMotionType) {
00169 motionType = KoduActionMotion::MT_MOVE_GAMEPAD;
00170 }
00171
00172
00173 if (!parsedMotionRate) {
00174 motionRate = KoduActionMotion::MR_NORMAL;
00175 motionRateCount = 1;
00176 } else {
00177 if (tempMotionRate == "quickly")
00178 motionRate = KoduActionMotion::MR_QUICKLY;
00179 else
00180 motionRate = KoduActionMotion::MR_SLOWLY;
00181 }
00182
00183
00184 return (new KoduActionMotion(motionType, motionRate, motionRateCount));
00185 }
00186
00187 KoduActionPlay* Parser::KodeCreator::createPlayKode(std::vector<TokenBase*>& mods) {
00188
00189 PARSER_ASSERT((1 <= mods.size() && mods.size() <= 2),
00190 errorMessage << "The Play action should have 1 - 2 tokens.");
00191
00192
00193 std::string soundFile;
00194
00195
00196 bool onceEnabled = false;
00197
00198
00199 int tokenCount = 1;
00200
00201
00202 while (!mods.empty()) {
00203
00204 if (mods[0]->isStringToken()) {
00205
00206 PARSER_ASSERT((soundFile.empty()),
00207 errorMessage << "Found a second sound file (only one is allowed).");
00208
00209
00210 soundFile = mods[0]->getStringData();
00211 }
00212
00213 else if (mods[0]->isKeywordToken()) {
00214 std::string keyword = mods[0]->getKeywordData();
00215
00216 PARSER_ASSERT((keyword == "once"),
00217 errorMessage << "The keyword \"" << keyword
00218 << "\" cannot be used for this action.");
00219
00220
00221 PARSER_ASSERT((onceEnabled == false),
00222 errorMessage << "Found a second once modifier (only one is allowed).");
00223 onceEnabled = true;
00224 }
00225
00226 else {
00227
00228 PARSER_ASSERT((ERROR),
00229 errorMessage << "Failed to recognize token " << tokenCount
00230 << " for the play action.");
00231 }
00232
00233 GeneralFncs::destroyPtrInVector(mods, 0);
00234 tokenCount++;
00235 }
00236
00237 PARSER_ASSERT((!soundFile.empty()),
00238 errorMessage << "This Play action does not have a sound file to play!");
00239
00240
00241 LiteralGenerator playLiteral(soundFile, Kodu::LiteralGenerator::RO_SEQUENTIAL);
00242 return (new KoduActionPlay(playLiteral, onceEnabled));
00243 }
00244
00245 KoduActionSay* Parser::KodeCreator::createSayKode(std::vector<TokenBase*>& mods) {
00246
00247 PARSER_ASSERT((1 <= mods.size() && mods.size() <= 10),
00248 errorMessage << "The Say action should have 1 - 10 tokens.");
00249
00250
00251 std::vector<std::string> literalStrings;
00252
00253
00254 LiteralGenerator::ReturnOrder_t returnOrder;
00255 bool randomKeywordWasFound = false;
00256 bool onceEnabled = false;
00257 std::string color;
00258
00259
00260 int tokenCount = 1;
00261
00262
00263 while (!mods.empty()) {
00264
00265 if (mods[0]->isStringToken()) {
00266 literalStrings.push_back(mods[0]->getStringData());
00267 }
00268
00269 else if (mods[0]->isKeywordToken()) {
00270 std::string keyword = mods[0]->getKeywordData();
00271
00272 if (keyword == "once") {
00273
00274 PARSER_ASSERT((onceEnabled == false),
00275 errorMessage << "Found a second \"once\" modifier (only one is allowed).");
00276 onceEnabled = true;
00277 }
00278
00279 else if (keyword == "random") {
00280
00281 PARSER_ASSERT((randomKeywordWasFound == false),
00282 errorMessage << "The \"random\" can only be used once in this phrase.");
00283 randomKeywordWasFound = true;
00284 }
00285
00286 else if (Parser::isValidColor(keyword) != -1) {
00287
00288 PARSER_ASSERT((color.empty()),
00289 errorMessage << "Found a second color (only one is allowed).");
00290 color = keyword;
00291 }
00292
00293 else {
00294
00295 PARSER_ASSERT((ERROR),
00296 errorMessage << "Failed to recognize token " << tokenCount
00297 << " for the play action.");
00298 }
00299 }
00300
00301 else {
00302
00303 PARSER_ASSERT((ERROR),
00304 errorMessage << "Failed to recognize token " << tokenCount
00305 << " for the play action.");
00306 }
00307 GeneralFncs::destroyPtrInVector(mods, 0);
00308 tokenCount++;
00309 }
00310
00311 PARSER_ASSERT((!literalStrings.empty()),
00312 errorMessage << "This Say action does not have any strings to say!");
00313
00314
00315 if (randomKeywordWasFound)
00316 returnOrder = LiteralGenerator::RO_RANDOM;
00317 else
00318 returnOrder = LiteralGenerator::RO_SEQUENTIAL;
00319
00320
00321 if (color.empty())
00322 color = Parser::koduDefaultDesignator;
00323
00324
00325 Kodu::LiteralGenerator sayLiterals(literalStrings, returnOrder);
00326 return (new KoduActionSay(color, sayLiterals, onceEnabled));
00327 }
00328
00329 KoduActionScore* Parser::KodeCreator::createScoreKode(const std::string& scoreType,
00330 std::vector<TokenBase*>& mods)
00331 {
00332
00333 PARSER_ASSERT((0 <= mods.size() && mods.size() <= 5),
00334 errorMessage << "The Score action should have 0 - 5 tokens.");
00335
00336
00337 NumericGenerator tempNumGen(1, 0);
00338 bool onceEnabled = false;
00339 std::string scoreDesignator;
00340
00341
00342 int tokenCount = 1;
00343 bool designatorWasSet = false;
00344 bool handledNumerics = false;
00345
00346
00347 KoduActionScore::ScoringType_t scoreOp;
00348 if (scoreType == "score") {
00349 scoreOp = KoduActionScore::ST_SCORE;
00350 } else if (scoreType == "set_score") {
00351 scoreOp = KoduActionScore::ST_SET_SCORE;
00352 } else {
00353 scoreOp = KoduActionScore::ST_SUBTRACT;
00354 }
00355
00356
00357 while (!mods.empty()) {
00358
00359 if (isNumericSpecifier(mods[0])) {
00360
00361 PARSER_ASSERT((handledNumerics == false),
00362 errorMessage << "Numeric specifiers for this action were already handled. "
00363 << "Token " << tokenCount << " is illegal.");
00364
00365
00366 PARSER_ASSERT((numericGenParser(mods, tempNumGen) == true),
00367 errorMessage << "An error occurred while parsing the numeric specifier token(s) "
00368 << "(see above).");
00369
00370 handledNumerics = true;
00371 }
00372
00373 else if (mods[0]->isKeywordToken()) {
00374 std::string keyword = mods[0]->getKeywordData();
00375
00376 if (keyword == "once") {
00377
00378 PARSER_ASSERT((onceEnabled == false),
00379 errorMessage << "Found a second \"once\" modifier (only one is allowed).");
00380 onceEnabled = true;
00381 }
00382
00383 else if (isScoreDesignator(mods[0])) {
00384
00385 PARSER_ASSERT((designatorWasSet == false),
00386 errorMessage << "Found a second score designator (only one is allowed).");
00387 scoreDesignator = keyword;
00388 designatorWasSet = true;
00389 }
00390
00391 else {
00392
00393 PARSER_ASSERT((ERROR),
00394 errorMessage << "Failed to recognize token " << tokenCount
00395 << " for the score/subtract/set score action.");
00396 }
00397
00398 GeneralFncs::destroyPtrInVector(mods, 0);
00399 }
00400
00401 else {
00402
00403 PARSER_ASSERT((ERROR),
00404 errorMessage << "Failed to recognize token " << tokenCount
00405 << " for the score/subtract/set score action.");
00406 }
00407 tokenCount++;
00408 }
00409
00410 if (scoreDesignator.empty())
00411 scoreDesignator = Parser::koduDefaultDesignator;
00412
00413 return (new KoduActionScore(scoreOp, tempNumGen, scoreDesignator, onceEnabled));
00414 }
00415
00416 KoduActionMotion* Parser::KodeCreator::createTurnKode(std::vector<TokenBase*>& mods) {
00417
00418 PARSER_ASSERT((0 <= mods.size() && mods.size() <= 5),
00419 errorMessage << "The Turn action should only have 0 - 5 tokens.");
00420
00421
00422 KoduActionMotion::MotionType_t motionType;
00423 KoduActionMotion::MotionRate_t motionRate;
00424 Direction_t directionToFace;
00425 std::string tempMotionRate;
00426 unsigned int motionRateCount = 0;
00427
00428
00429 int tokenCount = 1;
00430 bool parsedMotionType = false;
00431 bool parsedMotionRate = false;
00432 bool parsedDirection = false;
00433
00434
00435 while (!mods.empty()) {
00436
00437 if (mods[0]->isKeywordToken()) {
00438 std::string keyword = mods[0]->getKeywordData();
00439
00440 if (keyword == "quickly" || keyword == "slowly") {
00441 if (parsedMotionRate) {
00442
00443 PARSER_ASSERT((motionRateCount <= 3),
00444 errorMessage << "The turn action can only have up to 3 rate specifiers.\n");
00445
00446
00447 PARSER_ASSERT((keyword == tempMotionRate),
00448 errorMessage << "Different types of rate specifiers cannot be used.\n"
00449 << "First type seen: " << tempMotionRate << "\nSecond type seen: "
00450 << keyword);
00451 } else {
00452 tempMotionRate = keyword;
00453 parsedMotionRate = true;
00454 }
00455
00456 motionRateCount++;
00457 }
00458
00459 else if (keyword == "left" || keyword == "right" || keyword == "direction") {
00460
00461 PARSER_ASSERT((parsedMotionType == false),
00462 errorMessage << "A turn type for this action was already selected (There can only "
00463 << "be one). Second turn type found: " << keyword << ".");
00464 if (keyword == "left")
00465 motionType = KoduActionMotion::MT_TURN_LEFT;
00466 else if (keyword == "right")
00467 motionType = KoduActionMotion::MT_TURN_RIGHT;
00468 else
00469 motionType = KoduActionMotion::MT_TURN_DIRECTION;
00470 parsedMotionType = true;
00471 }
00472
00473 else if (keyword == "east" || keyword == "north" || keyword == "south"
00474 || keyword == "west")
00475 {
00476
00477 PARSER_ASSERT((parsedMotionType == true),
00478 errorMessage << "The keyword \"direction\" must be specified before the "
00479 << "direction specifier " << keyword << ".");
00480
00481 PARSER_ASSERT((motionType == KoduActionMotion::MT_TURN_DIRECTION),
00482 errorMessage << "Direction specifiers such as " << keyword
00483 << " can only be used with the turn modifier \"direction\".");
00484
00485 PARSER_ASSERT((parsedDirection == false),
00486 errorMessage << "A direction type was already parsed. (There can only "
00487 << "be one). Second direction type found: " << keyword << ".");
00488
00489 if (keyword == "east")
00490 directionToFace = DT_EAST;
00491 else if (keyword == "north")
00492 directionToFace = DT_NORTH;
00493 else if (keyword == "south")
00494 directionToFace = DT_SOUTH;
00495 else
00496 directionToFace = DT_WEST;
00497 parsedDirection = true;
00498 }
00499
00500 else {
00501
00502 PARSER_ASSERT((ERROR),
00503 errorMessage << "The keyword \"" << keyword
00504 << "\" cannot be used with the move action.");
00505 }
00506 }
00507
00508 else {
00509
00510 PARSER_ASSERT((ERROR),
00511 errorMessage << "Token " << tokenCount << " is an unrecognized and cannot be used "
00512 << "with the move action.");
00513 }
00514
00515
00516 GeneralFncs::destroyPtrInVector(mods, 0);
00517 }
00518
00519 if (!parsedMotionType) {
00520 motionType = KoduActionMotion::MT_TURN_LEFT;
00521 }
00522
00523
00524 if (!parsedMotionRate) {
00525 motionRate = KoduActionMotion::MR_NORMAL;
00526 motionRateCount = 1;
00527 } else {
00528 if (tempMotionRate == "quickly")
00529 motionRate = KoduActionMotion::MR_QUICKLY;
00530 else
00531 motionRate = KoduActionMotion::MR_SLOWLY;
00532 }
00533
00534 if (motionType == KoduActionMotion::MT_TURN_DIRECTION) {
00535 PARSER_ASSERT((parsedDirection == true),
00536 errorMessage << "A direction specifier such as north or east must be specified"
00537 << "when using the direction modifier.");
00538
00539 return (new KoduActionMotion(directionToFace, motionRate, motionRateCount));
00540 }
00541
00542
00543 return (new KoduActionMotion(motionType, motionRate, motionRateCount));
00544 }
00545
00546 }