utils.hh

00001 // This file is a part of Aurelia.
00002 // Copyright (C) 2010  Valentin David
00003 // Copyright (C) 2010  University of Bergen
00004 //
00005 // This program is free software: you can redistribute it and/or modify
00006 // it under the terms of the GNU General Public License as published by
00007 // the Free Software Foundation, either version 3 of the License, or
00008 // (at your option) any later version.
00009 //
00010 // This program is distributed in the hope that it will be useful,
00011 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00012 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00013 // GNU General Public License for more details.
00014 //
00015 // You should have received a copy of the GNU General Public License
00016 // along with this program.  If not, see <http://www.gnu.org/licenses/>.
00017 
00018 #ifndef __UTILS_HH
00019 # define __UTILS_HH
00020 
00021 extern const unsigned char first[][32];
00022 extern const unsigned char empty_first[];
00023 extern const unsigned char follow[][32];
00024 
00025 bool is_first(const stream& s, state alpha) {
00026   char c = *s;
00027   return (first[alpha][c>>3]&(1<<(c&7)))?true:false;
00028 }
00029 
00030 bool is_empty_first(state alpha) {
00031   return (empty_first[alpha>>3]&(1<<(alpha&7)))?true:false;
00032 }
00033 
00034 bool is_follow(const stream& s, nonterm A) {
00035   if (s.eof())
00036     return true;
00037   char c = *s;
00038   return (follow[A][c>>3]&(1<<(c&7)))?true:false;
00039 }
00040 
00041 bool test(const stream& s, nonterm A, state alpha) {
00042   if ((is_empty_first(alpha)) && (is_follow(s, A)))
00043     return true;
00044   if (!s.eof())
00045     if (is_first(s, alpha))
00046       return true;
00047   return false;
00048 }
00049 
00050 template <typename T, int branch_num, int label_num>
00051 struct branch {
00052 };
00053 
00054 template <typename Label, typename Ret = void_return>
00055 struct drop_ret {
00056 public:
00057   void operator()(r_t& R, const frame& f, stream& s, const node& cu) const {
00058     ret_frame<Ret> t = f.as<ret_frame<Ret> >();
00059     Label l;
00060     l(R, t.parent, s, cu);
00061   }
00062 
00063   unsigned hash() const {
00064     Label l;
00065     unsigned ret = (0x8934931a ^ l.hash());
00066     ret = (ret << 11) | (ret >> 21);
00067     return ret;
00068   }
00069 };
00070 
00071 template <typename S, state C, typename Next>
00072 struct parse_symbol {
00073   void operator()(r_t& R, const frame& f, stream& s, const node& cu) const {
00074     //std::cerr << "Calling: " << C << ":" << s.get_pos() << " " << typeid(S).name() << "(" << f.toString() << ")" << std::endl;
00075     if (test(s, (nonterm)S::NT, C)) {
00076       node ncu = node::create(R, typename Next::res(), f, cu, s);
00077       S sym;
00078       sym(R, f, s, ncu);
00079     }
00080   }
00081 
00082   unsigned hash() const {
00083     return (unsigned)&typeid(parse_symbol);
00084   }
00085 };
00086 
00087 template <typename string, typename Next>
00088 struct parse_string {
00089   void operator()(r_t& R, const frame& f, stream& s, const node& cu) const {
00090     //std::cerr << "Eating: " << C << ":" << s.get_pos() << " " << string::str << std::endl;
00091     if (s.eat(string::str)) {
00092       //std::cerr << "Success: " << s.get_pos() << std::endl;
00093       typename Next::res n;
00094       n(R, f, s, cu);
00095     }
00096   }
00097 
00098   unsigned hash() const {
00099     return (unsigned)&typeid(parse_string);
00100   }
00101 };
00102 
00103 template <typename NT>
00104 struct nofollow {
00105   static bool check(stream&) {
00106     return false;
00107   }
00108 };
00109 
00110 template <typename S>
00111 struct pop {
00112   void operator()(r_t& R, const frame&, stream& s, const node& cu) const {
00113     //std::cout << "Pop: " << s.get_pos() << std::endl;
00114     cu.pop(R, void_return(), s);
00115   }
00116 
00117   unsigned hash() const {
00118     return (unsigned)&typeid(pop);
00119   }
00120 };
00121 
00122 template <typename S, typename Next>
00123 struct parse_set {
00124   void operator()(r_t& R, const frame& f, stream& s, const node& cu) const {
00125     if (!s.eof()) {
00126       if (S::set[((unsigned char)*s)/8]&(1<<(((unsigned char)*s)%8))) {
00127         ++s;
00128         typename Next::res r;
00129         r(R, f, s, cu);
00130       }
00131     }
00132   }
00133 
00134   unsigned hash() const {
00135     return (unsigned)&typeid(parse_set);
00136   }
00137 };
00138 
00139 #endif