]> git.tdb.fi Git - libs/datafile.git/blob - source/parser.cpp
Move all exception classes to a common header
[libs/datafile.git] / source / parser.cpp
1 #include <msp/strings/format.h>
2 #include "binaryparser.h"
3 #include "except.h"
4 #include "parser.h"
5 #include "statement.h"
6 #include "textparser.h"
7
8 using namespace std;
9
10 namespace Msp {
11 namespace DataFile {
12
13 Parser::Parser(IO::Base &i, const string &s):
14         in(i),
15         main_src(s),
16         src(s),
17         good(true),
18         mode(new TextParser(in, src))
19 { }
20
21 Parser::~Parser()
22 {
23         delete mode;
24 }
25
26 Statement Parser::parse(bool raw)
27 {
28         if(!good)
29                 throw logic_error("Parser::parse() !good");
30
31         try
32         {
33                 while(1)
34                 {
35                         Statement st = mode->parse();
36                         if(!st.keyword.compare(0, 2, "__"))
37                         {
38                                 st.control = true;
39                                 process_control_statement(st);
40                         }
41
42                         if(raw || !st.control)
43                                 return st;
44                         else if(!good)  // This will occur with an __end statement
45                                 return Statement();
46                 }
47         }
48         catch(const exception &e)
49         {
50                 good = false;
51                 if(dynamic_cast<const data_error *>(&e))
52                         throw;
53                 else
54                         throw data_error(src, in.get_line_number(), e);
55         }
56 }
57
58 void Parser::process_control_statement(const Statement &st)
59 {
60         if(st.keyword=="__bin")
61         {
62                 delete mode;
63                 mode = new BinaryParser(in, src);
64
65                 while(in.peek()=='\n')
66                         in.get();
67         }
68         else if(st.keyword=="__text")
69         {
70                 delete mode;
71                 mode = new TextParser(in, src);
72         }
73         else if(st.keyword=="__z")
74                 in.set_decompress();
75         else if(st.keyword=="__src")
76         {
77                 string s = st.args[0].get<string>();
78                 if(s.empty())
79                         src = main_src;
80                 else
81                         src = format("%s[%s]", main_src, s);
82         }
83         else if(st.keyword=="__end")
84                 good = false;
85         else
86                 mode->process_control_statement(st);
87 }
88
89 const StatementKey *Parser::peek(unsigned level)
90 {
91         while(good)
92         {
93                 const StatementKey *key = mode->peek(level);
94                 if(key && !key->keyword.compare(0, 2, "__"))
95                         process_control_statement(mode->parse());
96                 else
97                         return key;
98         }
99
100         return 0;
101 }
102
103 bool Parser::parse_and_load(unsigned level, Loader &ldr, const LoaderAction &act)
104 {
105         // Peek first to get any control statements processed
106         peek(level);
107         return mode->parse_and_load(level, ldr, act);
108 }
109
110 } // namespace DataFile
111 } // namespace Msp