2 This file is part of libmspparser
3 Copyright © 2006 Mikko Rasa, Mikkosoft Productions
4 Distributed under the LGPL
6 #ifndef MSP_PARSER_LOADER_H_
7 #define MSP_PARSER_LOADER_H_
13 #include "statement.h"
25 virtual void execute(Loader &, const Statement &) const=0;
26 virtual ~LoaderAction() { }
32 class LoaderFunc0: public LoaderAction
35 typedef void (L::*FuncType)();
37 LoaderFunc0(FuncType f): func(f) { }
38 void execute(Loader &l, const Statement &st) const
40 if(st.args.size()!=0) throw TypeError(st.get_location()+": Wrong number of arguments");
41 (dynamic_cast<L &>(l).*func)();
47 template<typename L, typename A0>
48 class LoaderFunc1: public LoaderAction
51 typedef void (L::*FuncType)(A0);
53 LoaderFunc1(FuncType f): func(f) { }
54 void execute(Loader &l, const Statement &st) const
56 if(st.args.size()!=1) throw TypeError(st.get_location()+": Wrong number of arguments");
57 (dynamic_cast<L &>(l).*func)(st.args[0].get<A0>());
63 template<typename L, typename A0, typename A1>
64 class LoaderFunc2: public LoaderAction
67 typedef void (L::*FuncType)(A0, A1);
69 LoaderFunc2(FuncType f): func(f) { }
70 void execute(Loader &l, const Statement &st) const
72 if(st.args.size()!=2) throw TypeError(st.get_location()+": Wrong number of arguments");
73 (dynamic_cast<L &>(l).*func)(st.args[0].get<A0>(), st.args[1].get<A1>());
79 template<typename L, typename A0, typename A1, typename A2>
80 class LoaderFunc3: public LoaderAction
83 typedef void (L::*FuncType)(A0, A1, A2);
85 LoaderFunc3(FuncType f): func(f) { }
86 void execute(Loader &l, const Statement &st) const
88 if(st.args.size()!=3) throw TypeError(st.get_location()+": Wrong number of arguments");
89 (dynamic_cast<L &>(l).*func)(st.args[0].get<A0>(), st.args[1].get<A1>(), st.args[2].get<A2>());
95 template<typename L, typename A0, typename A1, typename A2, typename A3>
96 class LoaderFunc4: public LoaderAction
99 typedef void (L::*FuncType)(A0, A1, A2, A3);
101 LoaderFunc4(FuncType f): func(f) { }
102 void execute(Loader &l, const Statement &st) const
104 if(st.args.size()!=4) throw TypeError(st.get_location()+": Wrong number of arguments");
105 (dynamic_cast<L &>(l).*func)(st.args[0].get<A0>(), st.args[1].get<A1>(), st.args[2].get<A2>(), st.args[3].get<A3>());
111 template<typename L, typename T>
112 class LoadValue: public LoaderAction
115 typedef T L::*PointerType;
117 LoadValue(PointerType p): ptr(p) { }
118 void execute(Loader &l, const Statement &st) const
120 if(st.args.size()!=1) throw TypeError(st.get_location()+": Wrong number of arguments");
121 dynamic_cast<typename L::Loader &>(l).get_object().*ptr=st.args[0].get<T>();
130 void load(const Statement &st)
132 for(std::list<Statement>::const_iterator i=st.sub.begin(); i!=st.sub.end(); ++i)
139 Statement st=p.parse();
146 for(ActionMap::iterator i=actions.begin(); i!=actions.end(); ++i)
150 Loader(): cur_st(0) { }
153 void add(const std::string &k, void (L::*func)())
154 { actions.insert(typename ActionMap::value_type(k, new LoaderFunc0<L>(func))); }
156 template<typename L, typename A0>
157 void add(const std::string &k, void (L::*func)(A0))
158 { actions.insert(typename ActionMap::value_type(k, new LoaderFunc1<L, A0>(func))); }
160 template<typename L, typename A0, typename A1>
161 void add(const std::string &k, void (L::*func)(A0, A1))
162 { actions.insert(typename ActionMap::value_type(k, new LoaderFunc2<L, A0, A1>(func))); }
164 template<typename L, typename A0, typename A1, typename A2>
165 void add(const std::string &k, void (L::*func)(A0, A1, A2))
166 { actions.insert(typename ActionMap::value_type(k, new LoaderFunc3<L, A0, A1, A2>(func))); }
168 template<typename L, typename A0, typename A1, typename A2, typename A3>
169 void add(const std::string &k, void (L::*func)(A0, A1, A2, A3))
170 { actions.insert(typename ActionMap::value_type(k, new LoaderFunc4<L, A0, A1, A2, A3>(func))); }
172 template<typename L, typename T>
173 void add(const std::string &k, T L::*p)
174 { actions.insert(typename ActionMap::value_type(k, new LoadValue<L, T>(p))); }
176 void add(const std::string &k)
177 { actions.insert(ActionMap::value_type(k, 0)); }
181 { load_sub<S, typename S::Loader>(s); }
183 template<typename S, typename L>
187 throw Exception("load_sub called without current statement");
189 loader.load(*cur_st);
192 typedef std::map<std::string, LoaderAction *> ActionMap;
195 const Statement *cur_st;
197 void load_statement(const Statement &st)
200 ActionMap::iterator j=actions.find(st.keyword);
202 throw Exception(st.get_location()+": Unknown keyword '"+st.keyword+"'");
204 j->second->execute(*this, st);
210 void load(T &obj, const std::string &fn)
212 std::ifstream in(fn.c_str());
214 throw Exception("Couldn't open "+fn);
216 Parser parser(in, fn);
217 typename T::Loader loader(obj);
221 } // namespace Parser