]> git.tdb.fi Git - libs/datafile.git/blob - tool/compiler.cpp
Rewrite the type system
[libs/datafile.git] / tool / compiler.cpp
1 /* $Id$
2
3 This file is part of libmspdatafile
4 Copyright © 2008, 2010  Mikko Rasa, Mikkosoft Productions
5 Distributed under the LGPL
6 */
7
8 #include <msp/datafile/parser.h>
9 #include <msp/fs/dir.h>
10 #include <msp/fs/utils.h>
11 #include <msp/strings/regex.h>
12 #include "compiler.h"
13
14 using namespace std;
15 using namespace Msp;
16
17 Compiler::Compiler(DataFile::Writer &w):
18         writer(w),
19         reset_src(false)
20 {
21         add("file",     &Compiler::file);
22         add("for_each", &Compiler::for_each);
23         add("write",    &Compiler::write);
24 }
25
26 void Compiler::file(const string &fn)
27 {
28         File fl(*this, FS::dirname(get_source())/fn);
29         load_sub_with(fl);
30 }
31
32 void Compiler::for_each(const vector<string> &patterns)
33 {
34         ForEach fe(*this, FS::dirname(get_source()), list<string>(patterns.begin(), patterns.end()));
35         load_sub_with(fe);
36 }
37
38 void Compiler::write(const DataFile::Statement &st)
39 {
40         if(reset_src)
41         {
42                 writer.write((DataFile::Statement("__src"), string()));
43                 reset_src = false;
44         }
45
46         for(list<DataFile::Statement>::const_iterator i = st.sub.begin(); i!=st.sub.end(); ++i)
47                 writer.write(*i);
48 }
49
50 bool Compiler::process_statement(const FS::Path &fn, DataFile::Statement &st)
51 {
52         if(st.keyword=="_content")
53                 return true;
54
55         for(vector<DataFile::Value>::iterator i = st.args.begin(); i!=st.args.end(); ++i)
56                 if(i->get_signature()==DataFile::StringType::signature)
57                 {
58                         string value = i->get<string>();
59                         if(value=="$filename")
60                                 *i = DataFile::Value(FS::basename(fn.str()));
61                         else if(value=="$content")
62                         {
63                                 IO::File in(fn.str());
64                                 string data;
65                                 while(!in.eof())
66                                 {
67                                         char buf[4096];
68                                         unsigned len = in.read(buf, sizeof(buf));
69                                         data.append(buf, len);
70                                 }
71                                 *i = DataFile::Value(data);
72                         }
73                 }
74
75         for(list<DataFile::Statement>::iterator i = st.sub.begin(); i!=st.sub.end();)
76         {
77                 if(process_statement(fn, *i))
78                 {
79                         IO::File in(fn.str());
80                         IO::Buffered buf(in);
81
82                         DataFile::Parser parser(in, fn.str());
83                         while(parser)
84                         {
85                                 DataFile::Statement ss = parser.parse();
86                                 if(ss.valid)
87                                         st.sub.insert(i, ss);
88                         }
89                         i = st.sub.erase(i);
90                 }
91                 else
92                         ++i;
93         }
94
95         return false;
96 }
97
98 void Compiler::process_file(const FS::Path &fn, const list<DataFile::Statement> &st)
99 {
100         writer.write((DataFile::Statement("__src"), FS::basename(fn.str())));
101         reset_src = true;
102
103         if(st.empty())
104                 process_file(fn);
105         else
106         {
107                 for(list<DataFile::Statement>::const_iterator i = st.begin(); i!=st.end(); ++i)
108                 {
109                         if(i->keyword=="_content")
110                                 process_file(fn);
111                         else
112                         {
113                                 DataFile::Statement s = *i;
114                                 process_statement(fn, s);
115                                 writer.write(s);
116                         }
117                 }
118         }
119 }
120
121 void Compiler::process_file(const FS::Path &fn)
122 {
123         IO::File in(fn.str());
124         IO::Buffered buf(in);
125
126         DataFile::Parser parser(in, fn.str());
127         while(parser)
128         {
129                 DataFile::Statement st = parser.parse();
130                 if(st.valid)
131                         writer.write(st);
132         }
133 }
134
135
136 File::File(Compiler &c, const FS::Path &fn):
137         compiler(c),
138         filename(fn)
139 {
140         add("write", &File::write);
141 }
142
143 void File::finish()
144 {
145         compiler.process_file(filename, write_st);
146 }
147
148 void File::write(const DataFile::Statement &st)
149 {
150         write_st.insert(write_st.end(), st.sub.begin(), st.sub.end());
151 }
152
153
154 ForEach::ForEach(Compiler &c, const FS::Path &b, const list<string> &p):
155         compiler(c),
156         base(b),
157         patterns(p)
158 {
159         add("exclude", &ForEach::exclude);
160         add("pattern", &ForEach::pattern);
161         add("write",   &ForEach::write);
162 }
163
164 void ForEach::finish()
165 {
166         list<string> files = FS::list_files(base);
167         for(list<string>::iterator i = files.begin(); i!=files.end(); ++i)
168         {
169                 bool match = false;
170                 for(list<string>::const_iterator j = patterns.begin(); (j!=patterns.end() && !match); ++j)
171                         match = Regex(*j).match(*i);
172                 for(list<string>::const_iterator j = excludes.begin(); (j!=excludes.end() && match); ++j)
173                         match = !Regex(*j).match(*i);
174                 if(match)
175                         compiler.process_file(base / *i, write_st);
176         }
177 }
178
179 void ForEach::exclude(const string &p)
180 {
181         excludes.push_back(p);
182 }
183
184 void ForEach::pattern(const string &p)
185 {
186         patterns.push_back(p);
187 }
188
189 void ForEach::write(const DataFile::Statement &st)
190 {
191         write_st.insert(write_st.end(), st.sub.begin(), st.sub.end());
192 }