From: Mikko Rasa Date: Wed, 6 Aug 2008 16:35:21 +0000 (+0000) Subject: Refactor exceptions X-Git-Tag: 1.0~1 X-Git-Url: http://git.tdb.fi/?p=libs%2Fdatafile.git;a=commitdiff_plain;h=256f7238bc60d6dcc31a564988f5cc02a60c4537 Refactor exceptions Attach statement location to exceptions thrown by loading handlers --- diff --git a/source/binaryparser.cpp b/source/binaryparser.cpp index 214c35e..4073689 100644 --- a/source/binaryparser.cpp +++ b/source/binaryparser.cpp @@ -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(); const string &kw=st.args[1].get(); @@ -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(); strings[id]=st.args[1].get(); @@ -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; } diff --git a/source/collection.h b/source/collection.h index fa3a7de..0bbc9fc 100644 --- a/source/collection.h +++ b/source/collection.h @@ -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 #include #include "loader.h" @@ -31,14 +32,6 @@ struct NeedsCollection enum { result=(sizeof(f(0))==sizeof(Yes)) }; }; -template -struct RemoveConst -{ typedef T Type; }; - -template -struct RemoveConst -{ 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. diff --git a/source/except.h b/source/except.h index 4573e94..7892db5 100644 --- a/source/except.h +++ b/source/except.h @@ -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 @@ -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 diff --git a/source/loader.cpp b/source/loader.cpp index e499386..8d4f2be 100644 --- a/source/loader.cpp +++ b/source/loader.cpp @@ -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; } diff --git a/source/loader.h b/source/loader.h index 5b39212..0c81186 100644 --- a/source/loader.h +++ b/source/loader.h @@ -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).*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).*func)(st.args[0].get()); } 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).*func)(st.args[0].get(), st.args[1].get()); } 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).*func)(st.args[0].get(), st.args[1].get(), st.args[2].get()); } 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).*func)(st.args[0].get(), st.args[1].get(), st.args[2].get(), st.args[3].get()); } 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).*func)(st.args[0].get(), st.args[1].get(), st.args[2].get(), st.args[3].get(), st.args[4].get()); } 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(l).get_object().*ptr0=st.args[0].get(); } 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(l); ldr.get_object().*ptr0=ldr.get_collection().template get(st.args[0].get()); } @@ -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(l).get_object().*ptr0=st.args[0].get(); dynamic_cast(l).get_object().*ptr1=st.args[1].get(); } diff --git a/source/textparser.cpp b/source/textparser.cpp index f7c830d..0f17d3f 100644 --- a/source/textparser.cpp +++ b/source/textparser.cpp @@ -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(c), state), src, in.get_line_number()); + throw_at(ParseError(format("Parse error at '%c', expected one of \"%s\"", static_cast(c), e)), get_location()); } } // namespace DataFile diff --git a/source/textparser.h b/source/textparser.h index a260cd8..bfae4af 100644 --- a/source/textparser.h +++ b/source/textparser.h @@ -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