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 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 
00047 
00048 
00049 
00050 
00051 
00052 
00053 
00054 
00055 
00056 
00057 
00058 
00059 
00060 
00061 #ifndef ARCHON_UTILITIES_LR_PARSER_BASE_H
00062 #define ARCHON_UTILITIES_LR_PARSER_BASE_H
00063 
00064 #include <string>
00065 #include <vector>
00066 #include <typeinfo>
00067 
00068 #include <archon/util/exception.H>
00069 #include <archon/util/ref.H>
00070 #include <archon/util/cfg.H>
00071 #include <archon/util/lexer.H>
00072 #include <archon/util/logger.H>
00073 
00074 namespace Archon
00075 {
00076   namespace Utilities
00077   {
00078     using namespace std;
00079 
00086     class LrParserBase
00087     {
00088     public:
00089       struct Context
00090       {
00091         virtual ~Context() {}
00092         virtual void parserError() = 0;
00093       };
00094 
00095       struct Printer
00096       {
00097         virtual string print(const RefAnyConst &attribute) const = 0;
00098         virtual ~Printer() {}
00099       };
00100 
00101     protected:
00105       struct CallException: virtual Exception
00106       {
00107         int arg;
00108         const type_info &t;
00109         CallException(string l, int arg, const type_info &t): Exception(l), arg(arg), t(t) {}
00110       };
00111 
00112       struct AttributeTypeException: virtual Exception
00113       {
00114         AttributeTypeException(string l, string m): Exception(l, m) {}
00115       };
00116 
00117       struct Production
00118       {
00119         int rule;       
00120         int production; 
00121         vector<int> right; 
00122         int method; 
00123         vector<int> args;
00124 
00125         Production(int rule, int production):
00126           rule(rule), production(production), method(-4) {}
00127       };
00128 
00129       struct ActorBase: CFG::Actor
00130       {
00131         virtual bool verifyContext(const Context &) const = 0;
00132         virtual RefAnyConst call(int method, const vector<RefAnyConst> &args, Context &) const = 0;
00133       };
00134 
00135       CFG grammar;
00136       vector<Production> productions;
00137 
00138       LrParserBase(CFG &, const ActorBase *, const Printer *);
00139 
00149       virtual int getAction(int state, int terminal) const = 0;
00150 
00156       virtual int getGoto(int state, int nonterminal) const = 0;
00157 
00158     private:
00159       const ActorBase *actor;
00160       const Printer *printer;
00161 
00162       void attrTypeError(int arg, int rule, int production,
00163                          const type_info &actual,
00164                          const type_info &expected) const;
00165 
00166       RefAnyConst parse(LexerBase &, Context *, Logger *) const;
00167 
00168     public:
00169       template<class C>
00170       class Actor: public ActorBase
00171       {
00172         struct MethodBase: virtual RefObjectBase
00173         {
00174           virtual ~MethodBase() {}
00175           virtual string getName() const = 0;
00176           virtual int getArity() const = 0;
00177           virtual RefAnyConst call(C &context, const vector<RefAnyConst> &) const = 0;
00178         };
00179 
00180         vector<Ref<const MethodBase> > methods;
00181         map<string, int> methodMap;      
00182 
00183         bool verifyContext(const Context &c) const
00184         {
00185           return dynamic_cast<const C *>(&c);
00186         }
00187 
00188         RefAnyConst call(int method, const vector<RefAnyConst> &args, Context &c) const
00189         {
00190           return methods[method]->call(static_cast<C &>(c), args);
00191         }
00192 
00193         
00194 
00195 
00196 
00197 
00198 
00199 
00200 
00201 
00202 
00203         class MethodV0;
00204         template<class> class Method0;
00205         template<class> class MethodV1;
00206         template<class, class> class Method1;
00207         template<class, class> class MethodV2;
00208         template<class, class, class> class Method2;
00209 
00210         int registerMethod(string name, const MethodBase *m)
00211         {
00212           pair<map<string, int>::iterator, bool> r =
00213             methodMap.insert(make_pair(name, methods.size()));
00214           if(!r.second)
00215             ARCHON_THROW1(ArgumentException, "Redefinition of method '" + name + "'");
00216           methods.push_back(m);
00217           return methods.size()-1;
00218         }
00219 
00220       public:
00221         int getNumberOfMethods() const
00222         {
00223           return methods.size();
00224         }
00225 
00226         int getMethodArity(int i) const
00227         {
00228           
00229           return i < -2 ? 2 : i < -1 ? 1 : i < 0 ? 0 : methods[i]->getArity();
00230         }
00231 
00232         string getMethodName(int i) const
00233         {
00234           
00235           return i < -2 ? "<concat>" : i < -1 ? "<copy>" : i < 0 ? "<null>" : methods[i]->getName();
00236         }
00237 
00238         int registerMethod(string name, void (C::*method)())
00239         {
00240           return registerMethod(name, new MethodV0(name, method));
00241         }
00242 
00243         template<class R>
00244         int registerMethod(string name, Ref<const R> (C::*method)())
00245         {
00246           return registerMethod(name, new Method0<R>(name, method));
00247         }
00248 
00249         template<class A1>
00250         int registerMethod(string name,
00251                            void (C::*method)(const Ref<const A1> &))
00252         {
00253           return registerMethod(name, new MethodV1<A1>(name, method));
00254         }
00255 
00256         template<class R, class A1>
00257         int registerMethod(string name,
00258                            Ref<const R> (C::*method)(const Ref<const A1> &))
00259         {
00260           return registerMethod(name, new Method1<R, A1>(name, method));
00261         }
00262 
00263         template<class A1, class A2>
00264         int registerMethod(string name,
00265                            void (C::*method)(const Ref<const A1> &,
00266                                              const Ref<const A2> &))
00267         {
00268           return registerMethod(name, new MethodV2<A1, A2>(name, method));
00269         }
00270 
00271         template<class R, class A1, class A2>
00272         int registerMethod(string name,
00273                            Ref<const R> (C::*method)(const Ref<const A1> &,
00274                                                      const Ref<const A2> &))
00275         {
00276           return registerMethod(name, new Method2<R, A1, A2>(name, method));
00277         }
00278       };
00279 
00280       virtual ~LrParserBase();
00281 
00285       void parse(LexerBase &lexer, Logger *l=0) const
00286       {
00287         parse(lexer, 0, l);
00288       }
00289 
00294       void parse(LexerBase &lexer, Context &c, Logger *l=0) const
00295       {
00296         parse(lexer, &c, l);
00297       }
00298 
00305       template<class R>
00306       void parse(LexerBase &lexer, Context &c, Ref<const R> &result, Logger *l=0)
00307       {
00308         RefAnyConst r1 = parse(lexer, &c, l);
00309         const R *r2 = dynamic_cast<const R *>(r1.get());
00310         if(!r2 && r1)
00311           ARCHON_THROW1(AttributeTypeException, string("Parser result has type ") +
00312                         typeid(*r1.get()).name() + " but its type was "
00313                         "expected to be " + typeid(R).name());
00314         result = r2;
00315       }
00316     };
00317   }
00318 }
00319 
00320 #endif // ARCHON_UTILITIES_LR_PARSER_BASE_H