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