00001
00002
00003
00004
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
00067 #include <limits.h>
00068 #include <iostream>
00069 #include "shared_ptr.hxx"
00070
00071 #include "Options.hxx"
00072 #include "AST.hxx"
00073 #include "MixFix.hxx"
00074 #include "UocInfo.hxx"
00075 #include "libsherpa/INOstream.hxx"
00076
00077 #include "BUILD/TransitionParser.hxx"
00078
00079
00080
00081
00082
00083
00084
00085 #define MIXDEBUG(n) if (Options::mixfixDebug >= (n))
00086
00087 using namespace std;
00088 using namespace boost;
00089 using namespace sherpa;
00090
00091 typedef shared_ptr<AST> ASTPtr;
00092 typedef std::vector<ASTPtr> ASTVec;
00093 typedef std::vector<std::string> StringVec;
00094
00095
00096
00097
00098
00099 template<class T>
00100 static inline
00101 const T& top(const std::vector<T>& vec)
00102 {
00103 assert(vec.size() >= 1);
00104 return vec[vec.size()-1];
00105 }
00106
00107 template<class T>
00108 static inline
00109 T& top(std::vector<T>& vec)
00110 {
00111 assert(vec.size() >= 1);
00112 return vec[vec.size()-1];
00113 }
00114
00115 template<class T>
00116 static inline
00117 const T& topNext(const std::vector<T>& vec)
00118 {
00119 assert(vec.size() >= 2);
00120 return vec[vec.size()-2];
00121 }
00122
00123 template<class T>
00124 static inline
00125 void push(std::vector<T>& vec, const T& elem)
00126 {
00127 vec.push_back(elem);
00128 }
00129
00130 template<class T>
00131 static inline
00132 T pop(std::vector<T>& vec)
00133 {
00134 T elem = top(vec);
00135 vec.pop_back();
00136 return elem;
00137 }
00138
00139
00140 struct QuasiKeyword {
00144 int nOccur;
00145
00148 int nFirst;
00149
00152 int nPre;
00153
00156 int nPost;
00157
00158 QuasiKeyword()
00159 {
00160 nOccur = nPre = nPost = nFirst = 0;
00161 }
00162 };
00163
00164 struct QuasiKeywordMap {
00165 std::map<std::string, QuasiKeyword> theMap;
00166
00167 QuasiKeywordMap()
00168 {
00169 }
00170
00171 void add(std::string qkwd);
00172 void remove(std::string qkwd);
00173
00174 QuasiKeyword& operator[](std::string theKey)
00175 {
00176 return theMap[theKey];
00177 }
00178
00179 bool contains(std::string theKey)
00180 {
00181 return (theMap.find(theKey) != theMap.end());
00182 }
00183
00184 size_t erase(std::string theKey)
00185 {
00186 return theMap.erase(theKey);
00187 }
00188 };
00189
00190 enum MixElemModifierValues {
00191 MEMV_NONE,
00192
00193 MEMV_THUNK
00194 };
00195 typedef sherpa::EnumSet<MixElemModifierValues> MixElemModifiers;
00196
00197 struct MixRuleElement {
00198 SyntacticCategory sc;
00199 MixElemModifiers mods;
00200 std::string name;
00201
00202 MixRuleElement(SyntacticCategory _sc)
00203 {
00204 sc = _sc;
00205 mods = MEMV_NONE;
00206 }
00207 MixRuleElement(std::string _name)
00208 {
00209 sc = msc_keyword;
00210 name = _name;
00211 }
00212
00213 bool isHole() { return sc != msc_keyword; };
00214 };
00215 typedef std::vector<MixRuleElement> MixElemVec;
00216
00217 struct MixRule : public boost::enable_shared_from_this<MixRule> {
00219 std::string name;
00220
00222 MixElemVec rhs;
00223
00225 int fixity;
00226
00228 SyntacticCategory sc;
00229
00231 int prec;
00232
00236 Associativity assoc;
00237
00239 bool isInfix() const { return fixity == infix; }
00240 bool isPrefix() const { return fixity == prefix; }
00241 bool isClosed() const { return fixity == closed; }
00242 bool isPostfix() const { return fixity == postfix; }
00243
00244 bool isHole(size_t pos) {
00245 return (rhs[pos].sc != msc_keyword);
00246 }
00247
00248 bool isKwd(size_t pos) {
00249 return (rhs[pos].sc == msc_keyword);
00250 }
00251
00252 bool isInitialHole(size_t pos) {
00253 return (pos == 0) && isHole(pos);
00254 }
00255
00256 bool isFinalHole(size_t pos) {
00257 return ((pos == rhs.size() - 1) && isHole(pos));
00258 }
00259
00260 bool hasLeadingHole()
00261 {
00262 return (fixity == infix) || (fixity == postfix);
00263 }
00264 bool hasTrailingHole()
00265 {
00266 return (fixity == infix) || (fixity == prefix);
00267 }
00268
00269 private:
00271 void extract();
00272
00273 public:
00274 MixRule(SyntacticCategory _sc, const std::string& _nm, int _prec,
00275 Associativity _assoc = assoc_none)
00276 {
00277 sc = _sc;
00278 name = _nm;
00279 prec = _prec;
00280 assoc = _assoc;
00281 extract();
00282 }
00283
00284 static shared_ptr<MixRule>
00285 make(SyntacticCategory _sc, const std::string& _nm, int _prec,
00286 Associativity _assoc = assoc_none)
00287 {
00288 MixRule *tmp = new MixRule(_sc, _nm, _prec, _assoc);
00289 return boost::shared_ptr<MixRule>(tmp);
00290 }
00291
00292 void PrettyPrint(INOstream& out) const;
00293 };
00294 typedef shared_ptr<MixRule> MixRulePtr;
00295
00296 INOstream& operator<<(INOstream& out, MixRule& rule)
00297 {
00298 rule.PrettyPrint(out);
00299 return out;
00300 }
00301
00302
00303 struct MixFixNode {
00305 ASTPtr ast;
00306
00308 MixRulePtr rule;
00309
00310 MixFixNode(ASTPtr _ast, MixRulePtr _rule)
00311 {
00312 ast = _ast;
00313 rule = _rule;
00314 }
00315
00316 bool matchesKwd(const MixRuleElement& elem) const {
00317 assert(ast);
00318 return (elem.sc == msc_keyword && ast->s == elem.name);
00319 }
00320
00321 void PrettyPrint(sherpa::INOstream& out, PrettyPrintFlags flags)
00322 {
00323 if (ast->astType != at_ident)
00324 out << '{';
00325
00326 ast->PrettyPrint(out, flags & ~pp_FinalNewline);
00327
00328 if (ast->astType != at_ident)
00329 out << '}';
00330
00331 if (flags & pp_FinalNewline)
00332 out << endl;
00333 }
00334
00335 bool isKwd() const
00336 { return (!rule); }
00337
00338 bool isExpr() const
00339 { return rule && rule->sc == msc_expr; }
00340
00341 bool isType() const
00342 { return rule && rule->sc == msc_type; }
00343 };
00344
00345 typedef std::vector<MixFixNode> MixInput;
00346
00347 struct MixContext {
00348 typedef std::set<MixRulePtr> RuleSet;
00349 RuleSet rules;
00350 QuasiKeywordMap kwMap;
00351
00352 void add(MixRulePtr rule);
00353 void remove(MixRulePtr rule);
00354
00355 MixRulePtr
00356 ParseOneMixFix(sherpa::INOstream& errStream, MixInput& origInput,
00357 MixRulePtr parentRule);
00358
00359 MixRulePtr
00360 ParseMixFix(sherpa::INOstream& errStream, MixInput& origInput,
00361 MixRulePtr parentRule);
00362
00363 bool isKwd(const MixFixNode& mixNode);
00364
00371 bool cannotPossiblyMatch(sherpa::INOstream& errStream,
00372 MixRulePtr rule,
00373 const MixInput& mixExpr);
00374
00375 } TheMixContext;
00376
00377 void
00378 MixRule::PrettyPrint(INOstream& out) const
00379 {
00380 switch(fixity) {
00381 case infix:
00382 out << "infix";
00383
00384 switch(assoc) {
00385 case assoc_left: out << 'l'; break;
00386 case assoc_right: out << 'r'; break;
00387 case assoc_none: out << 'n'; break;
00388 }
00389
00390 break;
00391 case prefix:
00392 out << "prefix";
00393 break;
00394 case postfix:
00395 out << "postfix";
00396 break;
00397 case closed:
00398 out << "closed";
00399 break;
00400 }
00401
00402 out << " "
00403 << name
00404 << "("
00405 << prec
00406 << ")";
00407 }
00408
00410 void
00411 MixRule::extract()
00412 {
00413 std::string rule = name;
00414
00415 while(rule.size()) {
00416 if (rule[0] == '_') {
00417 rhs.push_back(MixRuleElement(sc));
00418 rule = rule.substr(1);
00419 }
00420 else if (rule[0] == '#') {
00421 SyntacticCategory sc;
00422
00423 switch (rule[1]) {
00424 case 'e':
00425 sc = msc_expr;
00426 break;
00427 case 't':
00428 sc = msc_type;
00429 break;
00430 case 'k':
00431 sc = msc_kind;
00432 break;
00433 default:
00434 assert(false);
00435 }
00436
00437 MixRuleElement elem(sc);
00438
00439 rule = rule.substr(2);
00440 while (rule[0] != '_') {
00441 switch(rule[0]) {
00442 case 'T':
00443 elem.mods |= MEMV_THUNK;
00444 break;
00445 default:
00446 assert(false);
00447 }
00448
00449 rule = rule.substr(1);
00450 }
00451
00452 rhs.push_back(elem);
00453 rule = rule.substr(1);
00454 }
00455 else {
00456 if (rule[0] == '@')
00457 rule = rule.substr(1);
00458
00459
00460 size_t nxt = rule.find_first_of("#_@");
00461
00462 if (nxt == string::npos) {
00463 rhs.push_back(MixRuleElement(rule));
00464 rule.clear();
00465 }
00466 else {
00467 rhs.push_back(MixRuleElement(rule.substr(0, nxt)));
00468 rule = rule.substr(nxt);
00469 }
00470 }
00471 }
00472
00473 if (isHole(0) && isHole(rhs.size()-1))
00474 fixity = infix;
00475 else if (isHole(0))
00476 fixity = postfix;
00477 else if (isHole(rhs.size()-1))
00478 fixity = prefix;
00479 else
00480 fixity = closed;
00481 }
00482
00483 bool
00484 MixContext::isKwd(const MixFixNode& node)
00485 {
00486 if (node.ast->astType != at_ident)
00487 return false;
00488
00489 return kwMap.contains(node.ast->s);
00490 }
00491
00492 bool
00493 MixContext::cannotPossiblyMatch(sherpa::INOstream& errStream,
00494 MixRulePtr rule,
00495 const MixInput& input)
00496 {
00497 MixElemVec& rhs = rule->rhs;
00498
00499
00500 if (input.size() < rhs.size())
00501 return true;
00502
00503
00504
00505 if (rule->hasLeadingHole()) {
00506 bool might = (top(input).isExpr()
00507 && ((rule->rhs.size() == 1)
00508 || topNext(input).matchesKwd(rule->rhs[1])));
00509
00510 MIXDEBUG(might ? 4 : 5)
00511 errStream << (*rule)
00512 << (might ? " might" : " cannot") << " match."
00513 << endl;
00514
00515 if (might)
00516 return false;
00517
00518 return true;
00519 }
00520
00521
00522
00523
00524 bool might = top(input).matchesKwd(rule->rhs[0]);
00525 if (might)
00526 return false;
00527
00528 MIXDEBUG(might ? 4 : 5)
00529 errStream << (*rule)
00530 << (might ? " might" : " cannot") << " match."
00531 << endl;
00532
00533 return true;
00534 }
00535
00537 void
00538 QuasiKeywordMap::add(std::string qkwd)
00539 {
00540 if (!contains(qkwd)) {
00541 QuasiKeyword qks;
00542 theMap.insert(std::pair<std::string, QuasiKeyword>(qkwd,qks));
00543 }
00544
00545 theMap[qkwd].nOccur++;
00546 }
00547
00550 void
00551 QuasiKeywordMap::remove(std::string qkwd)
00552 {
00553 if (!contains(qkwd))
00554 return;
00555
00556 theMap[qkwd].nOccur--;
00557
00558 if (theMap[qkwd].nOccur == 0)
00559 theMap.erase(qkwd);
00560 }
00561
00563 void
00564 MixContext::add(MixRulePtr rule)
00565 {
00566 MixElemVec& rhs = rule->rhs;
00567
00568 for (size_t i = 0; i < rhs.size(); i++)
00569 if (rule->isKwd(i))
00570 kwMap.add(rhs[i].name);
00571
00572
00573 if (!rule->hasLeadingHole())
00574 kwMap[rhs[0].name].nFirst++;
00575
00576
00577 if (rule->hasTrailingHole())
00578 kwMap[rhs[rhs.size()-2].name].nPre++;
00579
00580
00581 if (rule->hasLeadingHole())
00582 kwMap[rhs[1].name].nPost++;
00583
00584 rules.insert(rule);
00585 }
00586
00588 void
00589 MixContext::remove(MixRulePtr rule)
00590 {
00591 MixElemVec& rhs = rule->rhs;
00592
00593
00594 if (!rule->hasLeadingHole())
00595 kwMap[rhs[0].name].nFirst--;
00596
00597
00598 if (rule->hasTrailingHole())
00599 kwMap[rhs[rhs.size()-2].name].nPre--;
00600
00601
00602 if (rule->hasLeadingHole())
00603 kwMap[rhs[1].name].nPost--;
00604
00605 for (size_t i = 0; i < rhs.size(); i++)
00606 if (rule->isKwd(i))
00607 kwMap.remove(rhs[i].name);
00608
00609 rules.erase(rule);
00610 }
00611
00614 static ASTPtr
00615 CleanMixFix(INOstream& errStream, ASTPtr ast)
00616 {
00617
00618
00619
00620
00621
00622 if (ast->astType == at_apply) {
00623 std::string fn = ast->child(0)->s;
00624
00625
00626 if (fn == "_") {
00627 return CleanMixFix(errStream, ast->child(1));
00628 }
00629 else if (fn == "_._") {
00630 ast = AST::make(at_select, ast->loc, ast->child(1), ast->child(2));
00631 }
00632 else if (fn == "_,_") {
00633 LToken pair(tk_BlkIdent, ast->child(0)->loc, ast->child(0)->endLoc(), "pair");
00634 ast->children[0] = AST::make(at_ident, pair);
00635 }
00636 else if (fn == "(_)") {
00637 return CleanMixFix(errStream, ast->child(1));
00638 }
00639 else if (fn == "_(_)") {
00640 shared_ptr<AST> argAst = ast->child(2);
00641
00642
00643 ast->children[0] = ast->children[1];
00644 ast->children.erase(ast->children.begin()+1, ast->children.end());
00645
00646 while((argAst->astType == at_apply) && (argAst->child(0)->s == "_,_")) {
00647 ast->addChild(argAst->child(1));
00648 argAst = argAst->child(2);
00649 }
00650 ast->addChild(argAst);
00651 }
00652 else if (fn == "_(@)") {
00653
00654 ast->children[0] = ast->children[1];
00655 ast->children.erase(ast->children.begin()+1, ast->children.end());
00656 }
00657 else if (fn == "(@)") {
00658 ast->astType = at_unit;
00659 ast->children.clear();
00660 return ast;
00661 }
00662 else if (fn == "_[_]") {
00663 ast = AST::make(at_nth, ast->loc, ast->child(1), ast->child(2));
00664 }
00665
00666 #if 0
00667
00668
00669 else if (fn == "(_)") {
00670 if ((ast->child(1)->astType == at_apply) &&
00671 (ast->child(1)->child(0)->s == "[_]")) {
00672
00673 ast = argListToConsList(ast->child(1)->child(1));
00674
00675
00676 shared_ptr<AST> argAst = inAST->child(1)->child(1);
00677 while((argAst->astType == at_apply) && (argAst->child(0)->s == "_,_")) {
00678 argAst->children[0] =
00679 argAst = argAst->child(2);
00680 }
00681 ast->addChild(argAst);
00682 }
00683 else {
00684 return CleanMixFix(ast->child(1));
00685 }
00686 }
00687 #endif
00688 else if (fn == "[_]") {
00689 ast = AST::make(at_nth, ast->loc, ast->child(1), ast->child(2));
00690 }
00691 if (fn == "_and_" || fn == "_&&_") {
00692 ast->astType = at_and;
00693 ast->children.erase(ast->children.begin());
00694 }
00695 if (fn == "_or_" || fn == "_||_") {
00696 ast->astType = at_or;
00697 ast->children.erase(ast->children.begin());
00698 }
00699 }
00700
00701 for (size_t c = 0; c < ast->children.size(); c++)
00702 ast->children[c] = CleanMixFix(errStream, ast->children[c]);
00703
00704 return ast;
00705 }
00706
00707 static ASTPtr
00708 CheckMixFix(INOstream& errStream, ASTPtr ast)
00709 {
00710 return ast;
00711 }
00712
00713 static MixRulePtr MixNoRuleFound = MixRule::make(msc_expr, "_", INT_MIN, assoc_none);
00714 static MixRulePtr MixStartRule = MixRule::make(msc_expr, "_", INT_MIN, assoc_none);
00715 static MixRulePtr MixInputRule = MixRule::make(msc_expr, "(_)", INT_MIN, assoc_none);
00716
00722 shared_ptr<AST>
00723 ProcessMixFix(std::ostream& err, shared_ptr<AST> mixAST)
00724 {
00725 INOstream errStream(err);
00726
00727 if (TheMixContext.rules.empty())
00728 errStream << "Error! No Rules!" << endl;
00729
00730 ASTVec& children = mixAST->children;
00731
00732 MixInput input;
00733 for(ASTVec::reverse_iterator itr = children.rbegin();
00734 itr != children.rend();
00735 itr++) {
00736 push(input, MixFixNode(*itr, MixStartRule));
00737
00738
00739 if (TheMixContext.isKwd(top(input)))
00740 top(input).rule = GC_NULL;
00741 }
00742
00743 MIXDEBUG(1) {
00744 errStream << "Processing mixfix expression at "
00745 << mixAST->loc << endl;
00746 errStream.more();
00747 for(MixInput::reverse_iterator itr = input.rbegin();
00748 itr != input.rend();
00749 itr++) {
00750 if (itr != input.rbegin()) errStream << " ";
00751 (*itr).PrettyPrint(errStream, pp_NONE);
00752 }
00753 errStream << endl;
00754 errStream.less();
00755 }
00756
00757
00758 while( input.size() > 1
00759 && TheMixContext.ParseMixFix(errStream, input, MixStartRule))
00760 ;
00761
00762 if (input.size() != 1) {
00763 MIXDEBUG(1)
00764 errStream << "Yields Incomplete Parse" << endl;
00765 return GC_NULL;
00766 }
00767
00768 MIXDEBUG(2) {
00769 errStream << "Produced: ";
00770 input[0].PrettyPrint(errStream, pp_FinalNewline);
00771 }
00772
00773 shared_ptr<AST> result = CleanMixFix(errStream, input[0].ast);
00774 result = CheckMixFix(errStream, result);
00775
00776 MIXDEBUG(1) {
00777 errStream << "Giving: ";
00778 result->PrettyPrint(errStream, pp_FinalNewline);
00779 }
00780
00781 return result;
00782 }
00783
00784 static MixFixNode
00785 reduce(INOstream& errStream, MixInput& shunt, MixRulePtr rule)
00786 {
00787
00788
00789
00790
00791
00792 shared_ptr<AST> result = shunt[0].ast;
00793
00794 shared_ptr<AST> fnName =
00795 AST::make(at_ident, LToken(tk_BlkIdent, rule->name));
00796
00797 if (rule->sc == msc_expr) {
00798 result = AST::make(at_apply, shunt[0].ast->loc, fnName);
00799 }
00800 else if (rule->sc == msc_type) {
00801 result = AST::make(at_typeapp, shunt[0].ast->loc, fnName);
00802 }
00803
00804 assert(rule->rhs.size() == shunt.size());
00805
00806 for(size_t i = 0; i < shunt.size(); i++) {
00807 if (rule->rhs[i].isHole()) {
00808 assert(!shunt[i].isKwd());
00809
00810 shared_ptr<AST> tree = shunt[i].ast;
00811
00812 if (rule->rhs[i].mods & MEMV_THUNK) {
00818 shared_ptr<AST> iRetBody =
00819 AST::make(at_labeledBlock, tree->loc,
00820 AST::make(at_ident, LToken(tk_BlkIdent, "__return")),
00821 tree);
00822
00823 tree =
00824 AST::make(at_lambda, tree->loc,
00825 AST::make(at_argVec, tree->loc),
00826 iRetBody);
00827 }
00828
00829 result->addChild(tree);
00830 }
00831 }
00832
00833 MIXDEBUG(2) {
00834 errStream << "Reduced " << rule->name << " giving ";
00835 result->PrettyPrint(errStream, pp_FinalNewline);
00836 }
00837
00838 return MixFixNode(result, rule);
00839 }
00840
00871 MixRulePtr
00872 MixContext::ParseOneMixFix(INOstream& errStream, MixInput& origInput,
00873 MixRulePtr parentRule)
00874 {
00875 errStream.more();
00876
00877 MixInput shunt;
00878
00879 struct BestRule {
00880 MixRulePtr rule;
00881 MixInput result;
00882 bool tie;
00883 } best = { GC_NULL, MixInput(), false };
00884
00885 MIXDEBUG(4) {
00886 errStream << "Parsing:";
00887
00888 for(MixInput::reverse_iterator itr = origInput.rbegin();
00889 itr != origInput.rend();
00890 itr++) {
00891 errStream << " ";
00892 (*itr).PrettyPrint(errStream, pp_NONE);
00893 }
00894 errStream << " in context of "<< (*parentRule);
00895 errStream << endl;
00896 }
00897
00898
00899
00900
00901
00902
00903 for(RuleSet::iterator itr = rules.begin();
00904 itr != rules.end();
00905 ++itr) {
00906 MixRulePtr rule = *itr;
00907
00908
00909 if (rule->prec < parentRule->prec) {
00910 MIXDEBUG(5)
00911 errStream << (*rule)
00912 << "rejected (below required precedence)"
00913 << endl;
00914 continue;
00915 }
00916
00917 if (rule->prec == parentRule->prec) {
00918 if ((rule->assoc != assoc_right) ||
00919 (parentRule->assoc != assoc_right)) {
00920 MIXDEBUG(5)
00921 errStream << (*rule)
00922 << "rejected (prec OK, not right-assoc)"
00923 << endl;
00924 continue;
00925 }
00926 }
00927
00928
00929
00930 if (best.rule && rule->prec < best.rule->prec)
00931 continue;
00932
00933 if (cannotPossiblyMatch(errStream, rule, origInput))
00934 continue;
00935
00936
00937
00938 MixInput input = origInput;
00939 shunt = MixInput();
00940
00941 MIXDEBUG(4) {
00942 errStream << "Attempting rule " << rule->name
00943 << " on";
00944
00945 for(MixInput::reverse_iterator itr = input.rbegin();
00946 itr != input.rend();
00947 itr++) {
00948 errStream << " ";
00949 (*itr).PrettyPrint(errStream, pp_NONE);
00950 }
00951 errStream << endl;
00952 }
00953
00954 errStream.more();
00955
00956
00957
00958 MIXDEBUG(3) {
00959 errStream << "Shifting first element: ";
00960 top(input).PrettyPrint(errStream, pp_FinalNewline);
00961 }
00962 push(shunt, pop(input));
00963
00964 for (size_t pos = 1; pos < rule->rhs.size(); pos++) {
00965
00966
00967
00968 if (input.size() < (rule->rhs.size() - pos))
00969 break;
00970
00971
00972
00973
00974
00975
00976
00977
00978
00979
00980 if (rule->isKwd(pos) && top(input).matchesKwd(rule->rhs[pos])) {
00981 MIXDEBUG(3) {
00982 errStream << "Shifting: ";
00983 top(input).PrettyPrint(errStream, pp_FinalNewline);
00984 }
00985
00986 push(shunt, pop(input));
00987 }
00988
00989
00990 else if (rule->isHole(pos) &&
00991 ParseMixFix(errStream, input,
00992 rule->isFinalHole(pos) ? rule : MixInputRule)) {
00993 MIXDEBUG(3) {
00994 errStream << "Shifting: ";
00995 top(input).PrettyPrint(errStream, pp_FinalNewline);
00996 }
00997
00998 push(shunt, pop(input));
00999 }
01000 else if(rule->isHole(pos) && top(input).isExpr()) {
01001
01002
01003 MIXDEBUG(3) {
01004 errStream << "Shifting: ";
01005 top(input).PrettyPrint(errStream, pp_FinalNewline);
01006 }
01007
01008 push(shunt, pop(input));
01009 }
01010 else {
01011
01012 break;
01013 }
01014 }
01015
01016
01017
01018 MIXDEBUG(4) {
01019 errStream << "Rule " << rule->name
01020 << " (size " << rule->rhs.size()
01021 << ")";
01022 if (rule->rhs.size() == shunt.size()) {
01023 errStream << " matched stack " << shunt.size();
01024
01025 if (best.rule) {
01026 if (rule->prec > best.rule->prec)
01027 errStream << " and is preferred";
01028 else
01029 errStream << " but existing rule is better";
01030 }
01031 }
01032 else
01033 errStream << " did not match stack " << shunt.size();
01034
01035 errStream << endl;
01036 }
01037
01038 errStream.less();
01039
01040 if (rule->rhs.size() == shunt.size()) {
01041 MixFixNode nd = reduce(errStream, shunt, rule);
01042
01043 assert(nd.ast);
01044
01045 if (best.rule && rule->prec == best.rule->prec) {
01046
01047
01048 best.tie = true;
01049 continue;
01050 }
01051
01052 push(input, nd);
01053 best.rule = rule;
01054 best.result = input;
01055 best.tie = false;
01056 }
01057 }
01058
01059 errStream.less();
01060
01063 if (best.tie)
01064 return GC_NULL;
01065
01066 if (!best.rule)
01067 return GC_NULL;
01068
01069 origInput = best.result;
01070 return best.rule;
01071 }
01072
01079 MixRulePtr
01080 MixContext::ParseMixFix(INOstream& errStream, MixInput& origInput,
01081 MixRulePtr parentRule)
01082 {
01083 MixRulePtr best = GC_NULL;
01084 MixRulePtr p = GC_NULL;
01085
01086 while (p = ParseOneMixFix(errStream, origInput, parentRule)) {
01087 best = p;
01088 }
01089
01090 return best;
01091 }
01092
01103 MixRulePtr MixRules[] = {
01105
01107
01108 MixRule::make(msc_expr, "_or_", 0, assoc_left),
01109 MixRule::make(msc_expr, "_||_", 0, assoc_left),
01110 MixRule::make(msc_expr, "_and_", 1, assoc_left),
01111 MixRule::make(msc_expr, "_&&_", 1, assoc_left),
01112 MixRule::make(msc_expr, "_!=_", 2, assoc_left),
01113 MixRule::make(msc_expr, "_==_", 2, assoc_left),
01114 MixRule::make(msc_expr, "_<_", 3, assoc_left),
01115 MixRule::make(msc_expr, "_<=_", 3, assoc_left),
01116 MixRule::make(msc_expr, "_>_", 3, assoc_left),
01117 MixRule::make(msc_expr, "_>=_", 3, assoc_left),
01118 MixRule::make(msc_expr, "_::_", 4, assoc_left),
01119 MixRule::make(msc_expr, "_|_", 5, assoc_left),
01120 MixRule::make(msc_expr, "_^_", 6, assoc_left),
01121 MixRule::make(msc_expr, "_&_", 7, assoc_left),
01122 MixRule::make(msc_expr, "_<<_", 8, assoc_left),
01123 MixRule::make(msc_expr, "_>>_", 8, assoc_left),
01124 MixRule::make(msc_expr, "_+_", 9, assoc_left),
01125 MixRule::make(msc_expr, "_-_", 9, assoc_left),
01126 MixRule::make(msc_expr, "_%_", 10, assoc_left),
01127 MixRule::make(msc_expr, "_*_", 10, assoc_left),
01128 MixRule::make(msc_expr, "_/_", 10, assoc_left),
01129
01130 MixRule::make(msc_expr, "_**_", 11, assoc_left),
01131 MixRule::make(msc_expr, "_**_+_", 11, assoc_left),
01132
01133 MixRule::make(msc_expr, "-_", 12, assoc_right),
01134 MixRule::make(msc_expr, "!_", 13, assoc_right),
01135 MixRule::make(msc_expr, "not_", 13, assoc_right),
01136 MixRule::make(msc_expr, "~_", 14, assoc_right),
01137
01139
01141
01143
01144
01145
01146
01148
01149
01150
01151
01152
01153
01154 MixRule::make(msc_expr, "(_)", 128, assoc_none),
01155
01156
01157 MixRule::make(msc_expr, "[_]", 128, assoc_none),
01158
01159
01160
01161
01162
01163
01164
01165
01166 MixRule::make(msc_expr, "_,_", -1, assoc_right),
01167
01168 MixRule::make(msc_expr, "(@)", 129, assoc_left),
01169
01170 MixRule::make(msc_expr, "_(@)", 130, assoc_left),
01171 MixRule::make(msc_expr, "_(_)", 130, assoc_left),
01172 MixRule::make(msc_expr, "_[_]", 130, assoc_left),
01173 MixRule::make(msc_expr, "_._", 130, assoc_left),
01174
01175
01176 };
01177 static size_t nMixRules = sizeof(MixRules) / sizeof(MixRules[0]);
01178
01179 void
01180 mixfix_init()
01181 {
01182 for (size_t i = 0; i < nMixRules; i++) {
01183 TheMixContext.add(MixRules[i]);
01184 }
01185 }
01186
01187 static bool
01188 HandleMixFix(std::ostream& errStream, shared_ptr<AST> ast)
01189 {
01190 bool errFree = true;
01191
01192
01193 for (size_t c = 0; c < ast->children.size(); c++)
01194 errFree = errFree && HandleMixFix(errStream, ast->child(c));
01195
01196 if (ast->astType == at_mixfix) {
01197 shared_ptr<AST> newAst = ProcessMixFix(errStream, ast);
01198
01199 if (!newAst)
01200 errFree = false;
01201
01202 if (newAst && newAst != ast) {
01203
01204 ast->s = newAst->s;
01205 ast->astType = newAst->astType;
01206 ast->identType = newAst->identType;
01207 ast->litValue = newAst->litValue;
01208 ast->litBase = newAst->litBase;
01209 ast->flags = newAst->flags;
01210 ast->children = newAst->children;
01211 ast->fqn = newAst->fqn;
01212 }
01213 }
01214
01215 return errFree;
01216 }
01217
01218 bool
01219 UocInfo::fe_mixfix(std::ostream& errStream,
01220 bool init, unsigned long flags)
01221 {
01222 return HandleMixFix(errStream, uocAst);
01223 }