00001
00002
00003
00004 #include "parser.ih"
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 #include <iostream>
00058 #include <sstream>
00059 #include <string>
00060 #include <map>
00061 #include <iomanip>
00062
00063 namespace
00064 {
00065 char const author[] = "Frank B. Brokken (f.b.brokken@rug.nl)";
00066
00067 enum
00068 {
00069 STACK_EXPANSION = 5
00070
00071 };
00072
00073 enum ReservedTokens
00074 {
00075 PARSE_ACCEPT = 0,
00076 _UNDETERMINED_ = -2,
00077 _EOF_ = -1,
00078 _error_ = 256
00079 };
00080 enum StateType
00081 {
00082 NORMAL,
00083 ERR_ITEM,
00084 REQ_TOKEN,
00085 ERR_REQ,
00086 DEF_RED,
00087 ERR_DEF,
00088 REQ_DEF,
00089 ERR_REQ_DEF
00090 };
00091 struct PI__
00092 {
00093 size_t d_nonTerm;
00094
00095 size_t d_size;
00096 };
00097
00098 struct SR__
00099 {
00100 union
00101 {
00102 int _field_1_;
00103
00104 int d_type;
00105 int d_token;
00106 };
00107 union
00108 {
00109 int _field_2_;
00110
00111 int d_lastIdx;
00112 int d_action;
00113
00114 size_t d_errorState;
00115 };
00116 };
00117
00118
00119
00120
00121 PI__ const s_productionInfo[] =
00122 {
00123 {0, 0},
00124 {260, 1},
00125 {261, 1},
00126 {261, 2},
00127 {262, 1},
00128 {263, 5},
00129 {264, 2},
00130 {264, 2},
00131 {265, 1},
00132 {265, 1},
00133 {266, 4},
00134 {267, 0},
00135 {268, 1},
00136 };
00137
00138
00139
00140
00141 SR__ const s_0[] =
00142 {
00143 { { REQ_TOKEN}, { 6} },
00144 { { 260}, { 1} },
00145 { { 261}, { 2} },
00146 { { 262}, { 3} },
00147 { { 263}, { 4} },
00148 { { 259}, { 5} },
00149 { { 0}, { 0} },
00150 };
00151
00152 SR__ const s_1[] =
00153 {
00154 { { REQ_TOKEN}, { 2} },
00155 { { _EOF_}, { PARSE_ACCEPT} },
00156 { { 0}, { 0} },
00157 };
00158
00159 SR__ const s_2[] =
00160 {
00161 { { REQ_DEF}, { 4} },
00162 { { 262}, { 6} },
00163 { { 263}, { 4} },
00164 { { 259}, { 5} },
00165 { { 0}, { -1} },
00166 };
00167
00168 SR__ const s_3[] =
00169 {
00170 { { DEF_RED}, { 1} },
00171 { { 0}, { -2} },
00172 };
00173
00174 SR__ const s_4[] =
00175 {
00176 { { DEF_RED}, { 1} },
00177 { { 0}, { -4} },
00178 };
00179
00180 SR__ const s_5[] =
00181 {
00182 { { REQ_TOKEN}, { 2} },
00183 { { 123}, { 7} },
00184 { { 0}, { 0} },
00185 };
00186
00187 SR__ const s_6[] =
00188 {
00189 { { DEF_RED}, { 1} },
00190 { { 0}, { -3} },
00191 };
00192
00193 SR__ const s_7[] =
00194 {
00195 { { REQ_TOKEN}, { 6} },
00196 { { 264}, { 8} },
00197 { { 265}, { 9} },
00198 { { 257}, { 10} },
00199 { { 266}, { 11} },
00200 { { 258}, { 12} },
00201 { { 0}, { 0} },
00202 };
00203
00204 SR__ const s_8[] =
00205 {
00206 { { REQ_TOKEN}, { 6} },
00207 { { 125}, { 13} },
00208 { { 265}, { 14} },
00209 { { 257}, { 10} },
00210 { { 266}, { 11} },
00211 { { 258}, { 12} },
00212 { { 0}, { 0} },
00213 };
00214
00215 SR__ const s_9[] =
00216 {
00217 { { REQ_TOKEN}, { 2} },
00218 { { 59}, { 15} },
00219 { { 0}, { 0} },
00220 };
00221
00222 SR__ const s_10[] =
00223 {
00224 { { DEF_RED}, { 1} },
00225 { { 0}, { -8} },
00226 };
00227
00228 SR__ const s_11[] =
00229 {
00230 { { DEF_RED}, { 1} },
00231 { { 0}, { -9} },
00232 };
00233
00234 SR__ const s_12[] =
00235 {
00236 { { REQ_TOKEN}, { 2} },
00237 { { 40}, { 16} },
00238 { { 0}, { 0} },
00239 };
00240
00241 SR__ const s_13[] =
00242 {
00243 { { REQ_TOKEN}, { 2} },
00244 { { 259}, { 17} },
00245 { { 0}, { 0} },
00246 };
00247
00248 SR__ const s_14[] =
00249 {
00250 { { DEF_RED}, { 1} },
00251 { { 0}, { -7} },
00252 };
00253
00254 SR__ const s_15[] =
00255 {
00256 { { DEF_RED}, { 1} },
00257 { { 0}, { -6} },
00258 };
00259
00260 SR__ const s_16[] =
00261 {
00262 { { DEF_RED}, { 2} },
00263 { { 267}, { 18} },
00264 { { 0}, { -11} },
00265 };
00266
00267 SR__ const s_17[] =
00268 {
00269 { { DEF_RED}, { 1} },
00270 { { 0}, { -5} },
00271 };
00272
00273 SR__ const s_18[] =
00274 {
00275 { { REQ_TOKEN}, { 2} },
00276 { { 41}, { 19} },
00277 { { 0}, { 0} },
00278 };
00279
00280 SR__ const s_19[] =
00281 {
00282 { { DEF_RED}, { 1} },
00283 { { 0}, { -10} },
00284 };
00285
00286
00287
00288 SR__ const *s_state[] =
00289 {
00290 s_0, s_1, s_2, s_3, s_4, s_5, s_6, s_7, s_8, s_9,
00291 s_10, s_11, s_12, s_13, s_14, s_15, s_16, s_17, s_18, s_19,
00292 };
00293
00294 typedef std::map<int, char const *> SMap;
00295 typedef SMap::value_type SMapVal;
00296
00297 SMapVal s_symArr[] =
00298 {
00299 SMapVal(-2, "_UNDETERMINED_"),
00300 SMapVal(-1, "_EOF_"),
00301 SMapVal(256, "_error_"),
00302
00303 SMapVal(257, "MOVEUNIT"),
00304 SMapVal(258, "LOADMAP"),
00305 SMapVal(259, "TESTCASE"),
00306 SMapVal(260, "asctextfile"),
00307 SMapVal(261, "blocks"),
00308 SMapVal(262, "block"),
00309 SMapVal(263, "testblock"),
00310 SMapVal(264, "commands"),
00311 SMapVal(265, "command"),
00312 SMapVal(266, "loadmapcommand"),
00313 SMapVal(267, "filename"),
00314 SMapVal(268, "asctextfile_$"),
00315 };
00316
00317 SMap s_symbol
00318 (
00319 s_symArr, s_symArr + sizeof(s_symArr) / sizeof(SMapVal)
00320 );
00321
00322 }
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332 ParserBase::ParserBase()
00333 :
00334 d_stackIdx__(-1),
00335
00336 d_debug__(true),
00337 d_nErrors__(0),
00338
00339 d_requiredTokens__(0),
00340 d_acceptedTokens__(d_requiredTokens__),
00341 d_token__(_UNDETERMINED_),
00342 d_nextToken__(_UNDETERMINED_)
00343 {}
00344
00345
00346
00347 std::ostringstream ParserBase::s_out__;
00348
00349 std::ostream &ParserBase::dflush(std::ostream &out)
00350 {
00351 std::ostringstream &s_out__ = dynamic_cast<std::ostringstream &>(out);
00352
00353 std::cout << " " << s_out__.str() << std::flush;
00354 s_out__.clear();
00355 s_out__.str("");
00356 return out;
00357 }
00358
00359 std::string ParserBase::symbol(int value) const
00360 {
00361 using namespace std;
00362 ostringstream ostr;
00363 SMap::const_iterator it = s_symbol.find(value);
00364 if (it != s_symbol.end())
00365 ostr << "`" << it->second << "'";
00366 else if (isprint(value))
00367 ostr << "`" << static_cast<char>(value) << "' (" << value << ")";
00368 else
00369 ostr << "'\\x" << setfill('0') << hex << setw(2) << value << "'";
00370 return ostr.str();
00371 }
00372
00373 std::string ParserBase::stype__(char const *pre, STYPE__ const &semVal, char const *post) const
00374 {
00375 return "";
00376 }
00377
00378 void ParserBase::clearin()
00379 {
00380 d_token__ = d_nextToken__ = _UNDETERMINED_;
00381 }
00382
00383 void ParserBase::push__(size_t state)
00384 {
00385 if (static_cast<size_t>(d_stackIdx__ + 1) == d_stateStack__.size())
00386 {
00387 size_t newSize = d_stackIdx__ + STACK_EXPANSION;
00388 d_stateStack__.resize(newSize);
00389 d_valueStack__.resize(newSize);
00390 }
00391 ++d_stackIdx__;
00392 d_stateStack__[d_stackIdx__] = d_state__ = state;
00393 *(d_vsp__ = &d_valueStack__[d_stackIdx__]) = d_val__;
00394
00395 if (d_debug__)
00396 s_out__ << "push(state " << state << stype__(", semantic TOS = ", d_val__, ")") << ')' << "\n" << dflush;
00397 }
00398
00399 void ParserBase::popToken__()
00400 {
00401 d_token__ = d_nextToken__;
00402
00403 d_val__ = d_nextVal__;
00404 d_nextVal__ = STYPE__();
00405
00406 d_nextToken__ = _UNDETERMINED_;
00407 }
00408
00409 void ParserBase::pushToken__(int token)
00410 {
00411 d_nextToken__ = d_token__;
00412 d_nextVal__ = d_val__;
00413 d_token__ = token;
00414 }
00415
00416 void ParserBase::pop__(size_t count)
00417 {
00418
00419 if (d_debug__)
00420 s_out__ << "pop(" << count << ") from stack having size " << (d_stackIdx__ + 1) << "\n" << dflush;
00421 if (d_stackIdx__ < static_cast<int>(count))
00422 {
00423
00424 if (d_debug__)
00425 s_out__ << "Terminating parse(): unrecoverable input error at token " << symbol(d_token__) << "\n" << dflush;
00426 ABORT();
00427 }
00428
00429 d_stackIdx__ -= count;
00430 d_state__ = d_stateStack__[d_stackIdx__];
00431 d_vsp__ = &d_valueStack__[d_stackIdx__];
00432
00433 if (d_debug__)
00434 s_out__ << "pop(): next state: " << d_state__ << ", token: " << symbol(d_token__) ;
00435
00436 if (d_debug__)
00437 s_out__ << stype__("semantic: ", d_val__) << "\n" << dflush;
00438 }
00439
00440 inline size_t ParserBase::top__() const
00441 {
00442 return d_stateStack__[d_stackIdx__];
00443 }
00444
00445 void Parser::executeAction(int production)
00446 {
00447 if (d_token__ != _UNDETERMINED_)
00448 pushToken__(d_token__);
00449
00450
00451 if (int size = s_productionInfo[production].d_size)
00452 d_val__ = d_vsp__[1 - size];
00453
00454
00455 if (d_debug__)
00456 s_out__ << "executeAction(): of rule " << production ;
00457
00458 if (d_debug__)
00459 s_out__ << stype__(", semantic [TOS]: ", d_val__) << " ..." << "\n" << dflush;
00460 switch (production)
00461 {
00462
00463
00464 }
00465
00466 if (d_debug__)
00467 s_out__ << "... action of rule " << production << " completed" ;
00468
00469 if (d_debug__)
00470 s_out__ << stype__(", semantic: ", d_val__) << "\n" << dflush;
00471 }
00472
00473 inline void ParserBase::reduce__(PI__ const &pi)
00474 {
00475 d_token__ = pi.d_nonTerm;
00476 pop__(pi.d_size);
00477
00478
00479 if (d_debug__)
00480 s_out__ << "reduce(): by rule " << (&pi - s_productionInfo) ;
00481
00482 if (d_debug__)
00483 s_out__ << " to N-terminal " << symbol(d_token__) << stype__(", semantic = ", d_val__) << "\n" << dflush;
00484 }
00485
00486
00487
00488 void Parser::nextToken()
00489 {
00490 if (d_token__ != _UNDETERMINED_)
00491 return;
00492
00493 if (d_nextToken__ != _UNDETERMINED_)
00494 {
00495 popToken__();
00496
00497 if (d_debug__)
00498 s_out__ << "nextToken(): popped " << symbol(d_token__) << stype__(", semantic = ", d_val__) << "\n" << dflush;
00499 }
00500 else
00501 {
00502 ++d_acceptedTokens__;
00503
00504 d_token__ = lex();
00505 if (d_token__ <= 0)
00506 d_token__ = _EOF_;
00507 }
00508 print();
00509
00510 if (d_debug__)
00511 s_out__ << "nextToken(): using " << symbol(d_token__) << stype__(", semantic = ", d_val__) << "\n" << dflush;
00512 }
00513
00514
00515
00516
00517 int Parser::lookup(bool recovery)
00518 {
00519
00520 SR__ const *sr = s_state[d_state__];
00521 int lastIdx = sr->d_lastIdx;
00522
00523 SR__ const *lastElementPtr = sr + lastIdx;
00524 SR__ const *elementPtr = sr + 1;
00525
00526 while (elementPtr != lastElementPtr && elementPtr->d_token != d_token__)
00527 ++elementPtr;
00528
00529 if (elementPtr == lastElementPtr)
00530 {
00531 if (elementPtr->d_action < 0)
00532 {
00533
00534 if (d_debug__)
00535 s_out__ << "lookup(" << d_state__ << ", " << symbol(d_token__) ;
00536
00537 if (d_debug__)
00538 s_out__ << "): default reduction by rule " << -elementPtr->d_action << "\n" << dflush;
00539 return elementPtr->d_action;
00540 }
00541
00542 if (d_debug__)
00543 s_out__ << "lookup(" << d_state__ << ", " << symbol(d_token__) << "): Not " ;
00544
00545 if (d_debug__)
00546 s_out__ << "found. " << (recovery ? "Continue" : "Start") << " error recovery." << "\n" << dflush;
00547
00548
00549 throw UNEXPECTED_TOKEN__;
00550 }
00551
00552
00553
00554
00555 int action = elementPtr->d_action;
00556
00557
00558 if (d_debug__)
00559 {
00560 s_out__ << "lookup(" << d_state__ << ", " << symbol(d_token__);
00561
00562 if (action < 0)
00563 s_out__ << "): reduce by rule " << -action;
00564 else if (action == 0)
00565 s_out__ << "): ACCEPT";
00566 else
00567 s_out__ << "): shift " << action << " (" << symbol(d_token__) <<
00568 " processed)";
00569
00570 s_out__ << "\n" << dflush;
00571 }
00572
00573 return action;
00574 }
00575
00576
00577
00578
00579
00580
00581
00582
00583 void Parser::errorRecovery()
00584 try
00585 {
00586 if (d_acceptedTokens__ >= d_requiredTokens__)
00587 {
00588 ++d_nErrors__;
00589 error("Syntax error");
00590
00591 }
00592
00593
00594 if (d_debug__)
00595 s_out__ << "errorRecovery(): " << d_nErrors__ << " error(s) so far. State = " << top__() << "\n" << dflush;
00596
00597
00598 while (not (s_state[top__()][0].d_type & ERR_ITEM))
00599 {
00600
00601 if (d_debug__)
00602 s_out__ << "errorRecovery(): pop state " << top__() << "\n" << dflush;
00603 pop__();
00604 }
00605
00606 if (d_debug__)
00607 s_out__ << "errorRecovery(): state " << top__() << " is an ERROR state" << "\n" << dflush;
00608
00609
00610
00611
00612
00613
00614
00615
00616 int lastToken = d_token__;
00617
00618
00619
00620 pushToken__(_error_);
00621 push__(lookup(true));
00622
00623 d_token__ = lastToken;
00624
00625
00626
00627 bool gotToken = true;
00628
00629 while (true)
00630 {
00631 try
00632 {
00633 if (s_state[d_state__]->d_type & REQ_TOKEN)
00634 {
00635 gotToken = d_token__ == _UNDETERMINED_;
00636 nextToken();
00637 }
00638
00639 int action = lookup(true);
00640
00641 if (action > 0)
00642 {
00643 push__(action);
00644 popToken__();
00645
00646 if (d_debug__)
00647 s_out__ << "errorRecovery() SHIFT state " << action ;
00648
00649 if (d_debug__)
00650 s_out__ << ", continue with " << symbol(d_token__) << "\n" << dflush;
00651
00652 if (gotToken)
00653 {
00654
00655 if (d_debug__)
00656 s_out__ << "errorRecovery() COMPLETED: next state " ;
00657
00658 if (d_debug__)
00659 s_out__ << action << ", no token yet" << "\n" << dflush;
00660
00661 d_acceptedTokens__ = 0;
00662 return;
00663 }
00664 }
00665 else if (action < 0)
00666 {
00667
00668
00669 if (d_token__ != _UNDETERMINED_)
00670 pushToken__(d_token__);
00671
00672
00673 reduce__(s_productionInfo[-action]);
00674
00675 if (d_debug__)
00676 s_out__ << "errorRecovery() REDUCE by rule " << -action ;
00677
00678 if (d_debug__)
00679 s_out__ << ", token = " << symbol(d_token__) << "\n" << dflush;
00680 }
00681 else
00682 ABORT();
00683
00684 }
00685 catch (...)
00686 {
00687 if (d_token__ == _EOF_)
00688 ABORT();
00689
00690 popToken__();
00691 }
00692 }
00693 }
00694 catch (ErrorRecovery__)
00695 {
00696 ABORT();
00697 }
00698
00699
00700
00701
00702
00703
00704
00705
00706
00707
00708
00709
00710
00711
00712
00713
00714
00715
00716
00717
00718
00719
00720
00721
00722
00723
00724
00725
00726
00727 int Parser::parse()
00728 try
00729 {
00730
00731 if (d_debug__)
00732 s_out__ << "parse(): Parsing starts" << "\n" << dflush;
00733 push__(0);
00734 clearin();
00735
00736 while (true)
00737 {
00738
00739 if (d_debug__)
00740 s_out__ << "==" << "\n" << dflush;
00741 try
00742 {
00743 if (s_state[d_state__]->d_type & REQ_TOKEN)
00744 nextToken();
00745
00746
00747 int action = lookup(false);
00748
00749 if (action > 0)
00750 {
00751 push__(action);
00752 popToken__();
00753 }
00754 else if (action < 0)
00755 {
00756 executeAction(-action);
00757
00758 reduce__(s_productionInfo[-action]);
00759 }
00760 else
00761 ACCEPT();
00762 }
00763 catch (ErrorRecovery__)
00764 {
00765 errorRecovery();
00766 }
00767 }
00768 }
00769 catch (Return__ retValue)
00770 {
00771
00772 if (d_debug__)
00773 s_out__ << "parse(): returns " << retValue << "\n" << dflush;
00774 return retValue;
00775 }
00776