]> git.tdb.fi Git - libs/datafile.git/commitdiff
Exception rework for parser components
authorMikko Rasa <tdb@tdb.fi>
Mon, 25 Jul 2011 14:10:57 +0000 (17:10 +0300)
committerMikko Rasa <tdb@tdb.fi>
Mon, 25 Jul 2011 14:10:57 +0000 (17:10 +0300)
source/binaryparser.cpp
source/dataerror.cpp [new file with mode: 0644]
source/dataerror.h [new file with mode: 0644]
source/parser.cpp
source/textparser.cpp
source/textparser.h

index d2fca32ef3a2155eb78eec3034e67649336c3c0f..550319f46d0a7af21bd939b477adaac1047101c8 100644 (file)
@@ -9,6 +9,17 @@ using namespace std;
 namespace Msp {
 namespace DataFile {
 
+class bad_definition: public runtime_error
+{
+public:
+       bad_definition(const std::string &w):
+               runtime_error(w)
+       { }
+
+       virtual ~bad_definition() throw() { }
+};
+
+
 BinaryParser::BinaryParser(Input &i, const string &s):
        ParserMode(i, s),
        first(true)
@@ -25,7 +36,7 @@ Statement BinaryParser::parse()
                if(st.keyword=="__kwd")
                {
                        if(st.args.size()!=3)
-                               throw_at(TypeError("Keyword definition must have three arguments"), src);
+                               throw bad_definition("__kwd");
 
                        const unsigned id = st.args[0].get<unsigned>();
                        const string &kw = st.args[1].get<const string &>();
@@ -35,7 +46,7 @@ Statement BinaryParser::parse()
                else if(st.keyword=="__str")
                {
                        if(st.args.size()!=2)
-                               throw_at(TypeError("String definition must have two arguments"), src);
+                               throw bad_definition("__str");
 
                        const unsigned id = st.args[0].get<unsigned>();
                        strings[id] = st.args[1].get<const string &>();
diff --git a/source/dataerror.cpp b/source/dataerror.cpp
new file mode 100644 (file)
index 0000000..b21b84f
--- /dev/null
@@ -0,0 +1,32 @@
+#include <typeinfo>
+#include <msp/debug/demangle.h>
+#include <msp/strings/format.h>
+#include "dataerror.h"
+
+using namespace std;
+
+namespace Msp {
+namespace DataFile {
+
+data_error::data_error(const string &s, unsigned l, const string &w):
+       runtime_error(make_what(s, l, w)),
+       source(s),
+       line(l)
+{ }
+
+data_error::data_error(const string &s, unsigned l, const exception &e):
+       runtime_error(make_what(s, l, format("%s (%s)", Debug::demangle(typeid(e).name()), e.what()))),
+       source(s),
+       line(l)
+{ }
+
+string data_error::make_what(const string &s, unsigned l, const string &w)
+{
+       if(l)
+               return format("%s:%d: %s", s, l, w);
+       else
+               return format("%s: %s", s, w);
+}
+
+} // namespace DataFile
+} // namespace Msp
diff --git a/source/dataerror.h b/source/dataerror.h
new file mode 100644 (file)
index 0000000..7b53c65
--- /dev/null
@@ -0,0 +1,27 @@
+#ifndef MSP_DATAFILE_DATAERROR_H_
+#define MSP_DATAFILE_DATAERROR_H_
+
+#include <stdexcept>
+
+namespace Msp {
+namespace DataFile {
+
+class data_error: public std::runtime_error
+{
+private:
+       std::string source;
+       unsigned line;
+
+public:
+       data_error(const std::string &, unsigned, const std::string &);
+       data_error(const std::string &, unsigned, const std::exception &);
+       virtual ~data_error() throw() { }
+
+private:
+       std::string make_what(const std::string &, unsigned, const std::string &);
+};
+
+} // namespace DataFile
+} // namespace Msp
+
+#endif
index 99ece49a0375d57345cf1c905d4d395a37eeb167..443c3c8c3d72a4d0951e076f260b6262d511c25f 100644 (file)
@@ -1,5 +1,6 @@
 #include <msp/strings/format.h>
 #include "binaryparser.h"
+#include "dataerror.h"
 #include "parser.h"
 #include "statement.h"
 #include "textparser.h"
@@ -25,7 +26,7 @@ Parser::~Parser()
 Statement Parser::parse()
 {
        if(!good)
-               throw Exception("Parser is not good");
+               throw logic_error("Parser::parse() !good");
 
        try
        {
@@ -54,10 +55,13 @@ Statement Parser::parse()
                                return st;
                }
        }
-       catch(const Exception &e)
+       catch(const exception &e)
        {
                good = false;
-               throw;
+               if(dynamic_cast<const data_error *>(&e))
+                       throw;
+               else
+                       throw data_error(src, in.get_line_number(), e);
        }
 }
 
index 56c9bb2b07d75fbbdac9394b4edf42c314d6fdb2..c4eb03c7d91ef21e2b1af8d707e2f1363cc7fc4e 100644 (file)
@@ -9,6 +9,28 @@ using namespace std;
 namespace Msp {
 namespace DataFile {
 
+class parse_error: public runtime_error
+{
+public:
+       parse_error(const std::string &t):
+               runtime_error(t.empty() ? "at end of input" : format("after '%s'", t))
+       { }
+
+       virtual ~parse_error() throw() { }
+};
+
+
+class syntax_error: public runtime_error
+{
+public:
+       syntax_error(const std::string &t):
+               runtime_error(t.empty() ? "at end of input" : format("at '%s'", t))
+       { }
+
+       virtual ~syntax_error() throw() { }
+};
+
+
 TextParser::TextParser(Input &i, const string &s):
        ParserMode(i, s)
 { }
@@ -40,7 +62,7 @@ Statement TextParser::parse_statement(const Token *t)
                        if(token.str.empty())
                                break;
                        else if(token.type!=Token::IDENTIFIER)
-                               throw_at(ParseError(format("Syntax error at token '%s' (expected an identifier)", token.str)), get_location());
+                               throw syntax_error(token.str);
                        result.keyword = token.str;
                        result.valid = true;
                        result.source = src;
@@ -62,7 +84,7 @@ Statement TextParser::parse_statement(const Token *t)
                else if(finish)
                {
                        if(token.str!=";")
-                               throw_at(ParseError(format("Syntax error at token '%s' (Expected a ';')", token.str)), get_location());
+                               throw syntax_error(token.str);
                        break;
                }
                else if(token.str=="{")
@@ -84,10 +106,8 @@ Statement TextParser::parse_statement(const Token *t)
                        else
                                result.append(Symbol(token.str));
                }
-               else if(token.str=="")
-                       throw_at(ParseError("Unexcepted end of input"), get_location());
                else
-                       throw_at(ParseError("Syntax error"), get_location());
+                       throw syntax_error(token.str);
        }
 
        return result;
@@ -119,7 +139,7 @@ Token TextParser::parse_token()
        }
 
        if(comment>0)  // EOF while in comment
-               throw_at(ParseError("Unfinished comment at end of input"), get_location());
+               throw parse_error(string());
        else if(comment==0)  // Didn't hit any non-whitespace
                return Token(Token::SPECIAL, "");
 
@@ -189,7 +209,7 @@ Token TextParser::parse_token()
                        else if(isalpha(c) || c=='_' || c=='\\')
                                state = IDENTIFIER;
                        else
-                               parse_error(c, "0-9A-Za-z_\\.\"{};+-");
+                               throw parse_error(buf);
                        break;
 
                case SIGN:
@@ -200,7 +220,7 @@ Token TextParser::parse_token()
                        else if(c=='.')
                                state = FLOAT;
                        else
-                               parse_error(c, "0-9.");
+                               throw parse_error(buf);
                        break;
 
                case ZERO:
@@ -211,31 +231,31 @@ Token TextParser::parse_token()
                        else if(c=='.')
                                state = FLOAT;
                        else
-                               parse_error(c, "0-9A-Fa-f.");
+                               throw parse_error(buf);
                        break;
 
                case DECIMAL:
                        if(c=='.')
                                state = FLOAT;
                        else if(!isdigit(c))
-                               parse_error(c, "0-9.");
+                               throw parse_error(buf);
                        break;
 
                case HEXADECIMAL:
                        if(!isxdigit(c))
-                               parse_error(c, "0-9A-Fa-f");
+                               throw parse_error(buf);
                        break;
 
                case OCTAL:
                        if(!isodigit(c))
-                               parse_error(c, "0-7");
+                               throw parse_error(buf);
                        break;
 
                case FLOAT:
                        if(c=='e' || c=='E')
                                state = FLOATEXPINIT;
                        else if(!isdigit(c))
-                               parse_error(c, "0-9Ee");
+                               throw parse_error(buf);
                        break;
 
                case FLOATEXPINIT:
@@ -244,19 +264,19 @@ Token TextParser::parse_token()
                        else if(isdigit(c))
                                state = FLOATEXP;
                        else
-                               parse_error(c, "0-9+-");
+                               throw parse_error(buf);
                        break;
 
                case FLOATEXPSIGN:
                        if(isdigit(c))
                                state = FLOATEXP;
                        else
-                               parse_error(c, "0-9");
+                               throw parse_error(buf);
                        break;
 
                case FLOATEXP:
                        if(!isdigit(c))
-                               parse_error(c, "0-9");
+                               throw parse_error(buf);
                        break;
 
                case STRING:
@@ -270,14 +290,14 @@ Token TextParser::parse_token()
 
                case IDENTIFIER:
                        if(!isalpha(c) && !isdigit(c) && c!='_' && c!='-' && c!='/')
-                               parse_error(c, "0-9A-Za-z_/-");
+                               throw parse_error(buf);
                        break;
 
                case STRING_END:
-                       throw_at(ParseError("Garbage after string"), get_location());
+                       throw parse_error(buf);
 
                default:
-                       throw_at(InvalidState("Internal error (bad state)"), get_location());
+                       throw logic_error("bad parser state");
                }
 
                if(is_delimiter(next) && state>=ACCEPT)
@@ -285,17 +305,7 @@ Token TextParser::parse_token()
                        if(state==IDENTIFIER && buf[0]=='\\')
                                return Token(Token::IDENTIFIER, buf.substr(1));
                        else if(state==STRING_END)
-                       {
-                               try
-                               {
-                                       return Token(Token::STRING, c_unescape(buf.substr(1, buf.size()-2)));
-                               }
-                               catch(Exception &e)
-                               {
-                                       e.at(get_location());
-                                       throw;
-                               }
-                       }
+                               return Token(Token::STRING, c_unescape(buf.substr(1, buf.size()-2)));
                        else
                                return Token(token_type[state], buf);
                }
@@ -314,17 +324,5 @@ bool TextParser::isodigit(int c)
        return (c>='0' && c<='7');
 }
 
-string TextParser::get_location()
-{
-       ostringstream ss;
-       ss<<src<<':'<<in.get_line_number();
-       return ss.str();
-}
-
-void TextParser::parse_error(int c, const char *e)
-{
-       throw_at(ParseError(format("Parse error at '%c', expected one of \"%s\"", static_cast<char>(c), e)), get_location());
-}
-
 } // namespace DataFile
 } // namespace Msp
index eb452330136fa99d93535fed9d0cb0b194698cea..ef7d68e2eb706129558f26391fd374a3d2d2e851 100644 (file)
@@ -19,8 +19,6 @@ protected:
        Token parse_token();
        bool is_delimiter(int);
        bool isodigit(int);
-       std::string get_location();
-       void parse_error(int, const char *);
 };
 
 } // namespace DataFile