]> git.tdb.fi Git - libs/datafile.git/commitdiff
Refactor exceptions
authorMikko Rasa <tdb@tdb.fi>
Wed, 6 Aug 2008 16:35:21 +0000 (16:35 +0000)
committerMikko Rasa <tdb@tdb.fi>
Wed, 6 Aug 2008 16:35:21 +0000 (16:35 +0000)
Attach statement location to exceptions thrown by loading handlers

source/binaryparser.cpp
source/collection.h
source/except.h
source/loader.cpp
source/loader.h
source/textparser.cpp
source/textparser.h

index 214c35e70d3793437e786f90d0f99fd60a1fbd66..40736896c01bf13aaa789b2033050cbda5b338fc 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -31,7 +31,7 @@ Statement BinaryParser::parse()
                if(st.keyword=="__kwd")
                {
                        if(st.args.size()!=3)
-                               throw TypeError(src+": Keyword definition must have three arguments");
+                               throw_at(TypeError("Keyword definition must have three arguments"), src);
 
                        const unsigned id=st.args[0].get<unsigned>();
                        const string &kw=st.args[1].get<const string &>();
@@ -41,7 +41,7 @@ Statement BinaryParser::parse()
                else if(st.keyword=="__str")
                {
                        if(st.args.size()!=2)
-                               throw TypeError(src+": String definition must have two arguments");
+                               throw_at(TypeError("String definition must have two arguments"), src);
 
                        const unsigned id=st.args[0].get<unsigned>();
                        strings[id]=st.args[1].get<const string &>();
@@ -63,7 +63,7 @@ Statement BinaryParser::parse_statement()
 
        Dictionary::const_iterator i=dict.find(id);
        if(i==dict.end())
-               throw ParseError(format("%s: Unknown statement ID %d", src, id), src, 0);
+               throw_at(KeyError("Unknown statement ID", lexical_cast(id)), src);
        const DictEntry &de=i->second;
 
        Statement result;
@@ -171,7 +171,7 @@ const string &BinaryParser::lookup_string(unsigned id) const
 {
        StringMap::const_iterator i=strings.find(id);
        if(i==strings.end())
-               throw KeyError("Unknown string", lexical_cast(id));
+               throw_at(KeyError("Unknown string", lexical_cast(id)), src);
        return i->second;
 }
 
index fa3a7de9dbe25441417f988fbe16a5235cbf638d..0bbc9fc34203aa10c8aa4d9ddec467fddd24ea78 100644 (file)
@@ -1,13 +1,14 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2008  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
 #ifndef MSP_DATAFILE_COLLECTION_H_
 #define MSP_DATAFILE_COLLECTION_H_
 
+#include <msp/core/meta.h>
 #include <msp/core/refptr.h>
 #include "loader.h"
 
@@ -31,14 +32,6 @@ struct NeedsCollection
        enum { result=(sizeof(f<T>(0))==sizeof(Yes)) };
 };
 
-template<typename T>
-struct RemoveConst
-{ typedef T Type; };
-
-template<typename T>
-struct RemoveConst<const T>
-{ typedef T Type; };
-
 /**
 A collection of objects that can be loaded from a datafile.  Each object is
 identified by a name, which must be unique across the entire collection.
index 4573e947297dedd3f8311b92842d7f62faa98aa4..7892db5be1c292a34ff9c239d0d309b937f708fb 100644 (file)
@@ -1,11 +1,12 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2008  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
-#ifndef MSP_DATAFILE_ERROR_H_
-#define MSP_DATAFILE_ERROR_H_
+
+#ifndef MSP_DATAFILE_EXCEPT_H_
+#define MSP_DATAFILE_EXCEPT_H_
 
 #include <msp/core/except.h>
 
@@ -15,19 +16,13 @@ namespace DataFile {
 class TypeError: public Exception
 {
 public:
-       TypeError(const std::string &w_): Exception(w_) { }
+       TypeError(const std::string &w): Exception(w) { }
 };
 
 class ParseError: public Exception
 {
 public:
-       ParseError(const std::string &w_, const std::string &s, unsigned l): Exception(w_), source(s), line(l) { }
-       const std::string &get_source() const { return source; }
-       unsigned          get_line() const    { return line; }
-       ~ParseError() throw() { }
-private:
-       std::string source;
-       unsigned    line;
+       ParseError(const std::string &w): Exception(w) { }
 };
 
 } // namespace DataFile
index e4993868ab3adfac95c385ef7c5d9e6a3c638a1c..8d4f2bea35b07f0cf485cbc50a8d22fe146b5cd1 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2008  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -61,9 +61,20 @@ void Loader::load_statement(const Statement &st)
        cur_st=&st;
        ActionMap::iterator j=actions.find(st.keyword);
        if(j==actions.end())
-               throw KeyError(st.get_location()+": Unknown keyword", st.keyword);
+               throw_at(KeyError("Unknown keyword", st.keyword), st.get_location());
        if(j->second)
-               j->second->execute(*this, st);
+       {
+               try
+               {
+                       j->second->execute(*this, st);
+               }
+               catch(Exception &e)
+               {
+                       if(!e.where()[0])
+                               e.at(st.get_location());
+                       throw;
+               }
+       }
        cur_st=0;
 }
 
index 5b39212e53c32beceda2cc3227109dc9eb4c9b6c..0c8118625918823ee2b5ebf6640bfd171a9d85fb 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2006  Mikko Rasa, Mikkosoft Productions
+Copyright © 2006-2008  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -50,7 +50,7 @@ public:
        LoaderFunc0(FuncType f): func(f) { }
        void execute(Loader &l, const Statement &st) const
        {
-               if(st.args.size()!=0) throw TypeError(st.get_location()+": Wrong number of arguments");
+               if(st.args.size()!=0) throw TypeError("Wrong number of arguments");
                (dynamic_cast<L &>(l).*func)();
        };
 private:
@@ -70,7 +70,7 @@ public:
        LoaderFunc1(FuncType f): func(f) { }
        void execute(Loader &l, const Statement &st) const
        {
-               if(st.args.size()!=1) throw TypeError(st.get_location()+": Wrong number of arguments");
+               if(st.args.size()!=1) throw TypeError("Wrong number of arguments");
                (dynamic_cast<L &>(l).*func)(st.args[0].get<A0>());
        }
 private:
@@ -110,7 +110,7 @@ public:
        LoaderFunc2(FuncType f): func(f) { }
        void execute(Loader &l, const Statement &st) const
        {
-               if(st.args.size()!=2) throw TypeError(st.get_location()+": Wrong number of arguments");
+               if(st.args.size()!=2) throw TypeError("Wrong number of arguments");
                (dynamic_cast<L &>(l).*func)(st.args[0].get<A0>(), st.args[1].get<A1>());
        }
 private:
@@ -127,7 +127,7 @@ public:
        LoaderFunc3(FuncType f): func(f) { }
        void execute(Loader &l, const Statement &st) const
        {
-               if(st.args.size()!=3) throw TypeError(st.get_location()+": Wrong number of arguments");
+               if(st.args.size()!=3) throw TypeError("Wrong number of arguments");
                (dynamic_cast<L &>(l).*func)(st.args[0].get<A0>(), st.args[1].get<A1>(), st.args[2].get<A2>());
        }
 private:
@@ -144,7 +144,7 @@ public:
        LoaderFunc4(FuncType f): func(f) { }
        void execute(Loader &l, const Statement &st) const
        {
-               if(st.args.size()!=4) throw TypeError(st.get_location()+": Wrong number of arguments");
+               if(st.args.size()!=4) throw TypeError("Wrong number of arguments");
                (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>());
        }
 private:
@@ -161,7 +161,7 @@ public:
        LoaderFunc5(FuncType f): func(f) { }
        void execute(Loader &l, const Statement &st) const
        {
-               if(st.args.size()!=5) throw TypeError(st.get_location()+": Wrong number of arguments");
+               if(st.args.size()!=5) throw TypeError("Wrong number of arguments");
                (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>(), st.args[4].get<A4>());
        }
 private:
@@ -178,7 +178,7 @@ public:
        LoadValue1(Pointer0Type p0): ptr0(p0) { }
        void execute(Loader &l, const Statement &st) const
        {
-               if(st.args.size()!=1) throw TypeError(st.get_location()+": Wrong number of arguments");
+               if(st.args.size()!=1) throw TypeError("Wrong number of arguments");
                dynamic_cast<typename L::Loader &>(l).get_object().*ptr0=st.args[0].get<T0>();
        }
 private:
@@ -195,7 +195,7 @@ public:
        LoadValue1(Pointer0Type p0): ptr0(p0) { }
        void execute(Loader &l, const Statement &st) const
        {
-               if(st.args.size()!=1) throw TypeError(st.get_location()+": Wrong number of arguments");
+               if(st.args.size()!=1) throw TypeError("Wrong number of arguments");
                typename L::Loader &ldr=dynamic_cast<typename L::Loader &>(l);
                ldr.get_object().*ptr0=ldr.get_collection().template get<T0>(st.args[0].get<std::string>());
        }
@@ -214,7 +214,7 @@ public:
        LoadValue2(Pointer0Type p0, Pointer1Type p1): ptr0(p0), ptr1(p1) { }
        void execute(Loader &l, const Statement &st) const
        {
-               if(st.args.size()!=2) throw TypeError(st.get_location()+": Wrong number of arguments");
+               if(st.args.size()!=2) throw TypeError("Wrong number of arguments");
                dynamic_cast<typename L::Loader &>(l).get_object().*ptr0=st.args[0].get<T0>();
                dynamic_cast<typename L::Loader &>(l).get_object().*ptr1=st.args[1].get<T1>();
        }
index f7c830d0030ebcf5428c3c0abf06c63ba043ce60..0f17d3f3cc79808a7659e291e406f6b7bb814137 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -47,7 +47,7 @@ Statement TextParser::parse_statement(const Token *t)
                        if(token.str.empty())
                                break;
                        else if(token.type!=Token::IDENTIFIER)
-                               throw ParseError(format("%s: Syntax error at token '%s' (expected an identifier)", get_location(), token.str), src, in.get_line_number());
+                               throw_at(ParseError(format("Syntax error at token '%s' (expected an identifier)", token.str)), get_location());
                        result.keyword=token.str;
                        result.valid=true;
                        result.source=src;
@@ -69,7 +69,7 @@ Statement TextParser::parse_statement(const Token *t)
                else if(finish)
                {
                        if(token.str!=";")
-                               throw ParseError(format("%s: Syntax error at token '%s' (Expected a ';')", get_location(), token.str), src, in.get_line_number());
+                               throw_at(ParseError(format("Syntax error at token '%s' (Expected a ';')", token.str)), get_location());
                        break;
                }
                else if(token.str=="{")
@@ -93,9 +93,9 @@ Statement TextParser::parse_statement(const Token *t)
                        //result.args.push_back(resolve_identifiertoken.str);
                }
                else if(token.str=="")
-                       throw ParseError(src+": Unexcepted end of input", src, in.get_line_number());
+                       throw_at(ParseError("Unexcepted end of input"), get_location());
                else
-                       throw ParseError(get_location()+": Syntax error", src, in.get_line_number());
+                       throw_at(ParseError("Syntax error"), get_location());
        }
 
        return result;
@@ -127,7 +127,7 @@ Token TextParser::parse_token()
        }
 
        if(comment>0)  // EOF while in comment
-               throw ParseError(src+": Unfinished comment at end of input", src, in.get_line_number());
+               throw_at(ParseError("Unfinished comment at end of input"), get_location());
        else if(comment==0)  // Didn't hit any non-whitespace
                return Token(Token::SPECIAL, "");
 
@@ -195,7 +195,7 @@ Token TextParser::parse_token()
                        else if(isalpha(c) || c=='_')
                                state=IDENTIFIER;
                        else
-                               parse_error(c, state);
+                               parse_error(c, "0-9A-Za-z_.\"{};+-");
                        break;
 
                case SIGN:
@@ -206,7 +206,7 @@ Token TextParser::parse_token()
                        else if(c=='.')
                                state=FLOAT;
                        else
-                               parse_error(c, state);
+                               parse_error(c, "0-9.");
                        break;
 
                case ZERO:
@@ -217,31 +217,31 @@ Token TextParser::parse_token()
                        else if(c=='.')
                                state=FLOAT;
                        else
-                               parse_error(c, state);
+                               parse_error(c, "0-9A-Fa-f.");
                        break;
 
                case DECIMAL:
                        if(c=='.')
                                state=FLOAT;
                        else if(!isdigit(c))
-                               parse_error(c, state);
+                               parse_error(c, "0-9.");
                        break;
 
                case HEXADECIMAL:
                        if(!isxdigit(c))
-                               parse_error(c, state);
+                               parse_error(c, "0-9A-Fa-f");
                        break;
 
                case OCTAL:
                        if(!isodigit(c))
-                               parse_error(c, state);
+                               parse_error(c, "0-7");
                        break;
 
                case FLOAT:
                        if(c=='e' || c=='E')
                                state=FLOATEXPINIT;
                        else if(!isdigit(c))
-                               parse_error(c, state);
+                               parse_error(c, "0-9Ee");
                        break;
 
                case FLOATEXPINIT:
@@ -250,19 +250,19 @@ Token TextParser::parse_token()
                        else if(isdigit(c))
                                state=FLOATEXP;
                        else
-                               parse_error(c, state);
+                               parse_error(c, "0-9+-");
                        break;
 
                case FLOATEXPSIGN:
                        if(isdigit(c))
                                state=FLOATEXP;
                        else
-                               parse_error(c, state);
+                               parse_error(c, "0-9");
                        break;
 
                case FLOATEXP:
                        if(!isdigit(c))
-                               parse_error(c, state);
+                               parse_error(c, "0-9");
                        break;
 
                case STRING:
@@ -274,9 +274,10 @@ Token TextParser::parse_token()
                                {
                                        return Token(Token::STRING, c_unescape(buf.substr(1, buf.size()-2)));
                                }
-                               catch(const Exception &e)
+                               catch(Exception &e)
                                {
-                                       throw ParseError(format("%s: %s", get_location(), e.what()), src, in.get_line_number());
+                                       e.at(get_location());
+                                       throw;
                                }
                        }
                        else
@@ -285,11 +286,11 @@ Token TextParser::parse_token()
 
                case IDENTIFIER:
                        if(!isalpha(c) && !isdigit(c) && c!='_')
-                               parse_error(c, state);
+                               parse_error(c, "0-9A-Za-z_");
                        break;
 
                default:
-                       throw Exception(get_location()+": Internal error (bad state)");
+                       throw_at(InvalidState("Internal error (bad state)"), get_location());
                }
 
                if(is_delimiter(next) && state>=ACCEPT)
@@ -316,9 +317,9 @@ string TextParser::get_location()
        return ss.str();
 }
 
-void TextParser::parse_error(int c, int state)
+void TextParser::parse_error(int c, const char *e)
 {
-       throw ParseError(format("%s: Parse error at '%c' (state %d)", get_location(), static_cast<char>(c), state), src, in.get_line_number());
+       throw_at(ParseError(format("Parse error at '%c', expected one of \"%s\"", static_cast<char>(c), e)), get_location());
 }
 
 } // namespace DataFile
index a260cd8f2e5d5a58df3f0156c552fa49c5ecaa18..bfae4af2e6389fd15203cfa13866bd32e8ebab9b 100644 (file)
@@ -1,7 +1,7 @@
 /* $Id$
 
 This file is part of libmspdatafile
-Copyright © 2007  Mikko Rasa, Mikkosoft Productions
+Copyright © 2007-2008  Mikko Rasa, Mikkosoft Productions
 Distributed under the LGPL
 */
 
@@ -26,7 +26,7 @@ protected:
        bool  is_delimiter(int);
        bool  isodigit(int);
        std::string get_location();
-       void  parse_error(int, int);
+       void  parse_error(int, const char *);
 };
 
 } // namespace DataFile