1 |
/* |
2 |
* This file is a part of EZC -- Easy templating in C++ |
3 |
* and is distributed under the (new) BSD licence. |
4 |
* Author: Tomasz Sowa <t.sowa@slimaczek.pl> |
5 |
*/ |
6 |
|
7 |
/* |
8 |
* Copyright (c) 2007-2010, Tomasz Sowa |
9 |
* All rights reserved. |
10 |
* |
11 |
* Redistribution and use in source and binary forms, with or without |
12 |
* modification, are permitted provided that the following conditions are met: |
13 |
* |
14 |
* * Redistributions of source code must retain the above copyright notice, |
15 |
* this list of conditions and the following disclaimer. |
16 |
* |
17 |
* * Redistributions in binary form must reproduce the above copyright |
18 |
* notice, this list of conditions and the following disclaimer in the |
19 |
* documentation and/or other materials provided with the distribution. |
20 |
* |
21 |
* * Neither the name Tomasz Sowa nor the names of contributors to this |
22 |
* project may be used to endorse or promote products derived |
23 |
* from this software without specific prior written permission. |
24 |
* |
25 |
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
26 |
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
27 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
28 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
29 |
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
30 |
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
31 |
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
32 |
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
33 |
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
34 |
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF |
35 |
* THE POSSIBILITY OF SUCH DAMAGE. |
36 |
*/ |
37 |
|
38 |
|
39 |
#ifndef headerfileezc |
40 |
#define headerfileezc |
41 |
|
42 |
#include <string> |
43 |
#include <sstream> |
44 |
#include <fstream> |
45 |
#include <vector> |
46 |
#include <map> |
47 |
#include <cstdlib> |
48 |
#include <cstring> |
49 |
|
50 |
|
51 |
namespace Ezc |
52 |
{ |
53 |
|
54 |
void CreateMsg(std::ostringstream & o, const char * type, const char * arg = 0); |
55 |
std::string CreateMsg(const char * type, const char * arg = 0); |
56 |
void SplitUnixDirectory(const char * name, std::string & dir, std::string & file); |
57 |
void SplitUnixDirectory(const std::string & name, std::string & dir, std::string & file); |
58 |
|
59 |
|
60 |
|
61 |
|
62 |
|
63 |
class Pattern |
64 |
{ |
65 |
public: |
66 |
Pattern(); |
67 |
|
68 |
void ParseFile(const std::string & file_name); |
69 |
void ParseFile(const char * file_name); |
70 |
void ParseString(const std::string & str); |
71 |
void ParseString(const char * str); |
72 |
|
73 |
// first we're trying to read a file from directory dir |
74 |
// if there is no such a file there then we try read from dir2 |
75 |
// (the second dir2 can be empty - it will not be used) |
76 |
void Directory(const char * dir, const char * dir2 = 0); |
77 |
void Directory(const std::string & dir); |
78 |
void Directory(const std::string & dir, const std::string & dir2); |
79 |
|
80 |
void Clear(); |
81 |
|
82 |
struct Item |
83 |
{ |
84 |
// change the name to 'Type' |
85 |
enum ItemType |
86 |
{ |
87 |
item_none, item_container, item_text, item_ifany, item_ifno, item_for, |
88 |
item_else, item_end, item_err, item_normal, item_ifindex, |
89 |
item_include, item_is, item_isno, item_ifone, item_comment, item_def |
90 |
}; |
91 |
|
92 |
struct Directive |
93 |
{ |
94 |
bool is_text; // if true that means a directive in quotes "static text" |
95 |
std::string name; |
96 |
}; |
97 |
|
98 |
|
99 |
ItemType type; |
100 |
std::string text; |
101 |
std::vector<Item*> item_table; |
102 |
std::vector<Directive> directives; |
103 |
|
104 |
Item(); |
105 |
Item(const Item & i); |
106 |
Item & operator=(const Item & i); |
107 |
void CopyItemTable(const Item & i); |
108 |
~Item(); |
109 |
|
110 |
Item * AddItem(const Item * porg = 0); |
111 |
Item * AddItem(const Item & porg); |
112 |
void ClearItems(); |
113 |
ItemType LastItemType(); |
114 |
void DeleteLastItem(); |
115 |
void Clear(); |
116 |
}; |
117 |
|
118 |
Item item_root; |
119 |
|
120 |
// allowing include tag |
121 |
// default: true |
122 |
bool allow_include; |
123 |
|
124 |
// if true all text-items which have only white characters (with new lines as well) |
125 |
// will be deleted - useful in *.txt templates |
126 |
// this not actually delete the whole item but only the string |
127 |
// the item will be present with an empty string |
128 |
// default: false |
129 |
bool delete_all_white; |
130 |
|
131 |
private: |
132 |
const char * itext; |
133 |
|
134 |
// first we're trying to read a file from 'directory' |
135 |
// if there is no such a file there then we try read from 'directory2' |
136 |
// we read from these directories only if they are not empty |
137 |
std::string directory, directory2; |
138 |
|
139 |
int include_level; |
140 |
|
141 |
bool CheckFileName(const char * name); |
142 |
std::string ReadFile(const std::string & name); |
143 |
std::string ReadFile(const char * name); |
144 |
bool ReadFileFromDir(const std::string & dir, const char * name, std::string & result); |
145 |
|
146 |
int ReadCharInText(); |
147 |
bool IsWhite(int c); |
148 |
void SkipWhiteCharacters(); |
149 |
void CheckWhiteAndDelete(std::string & s); |
150 |
|
151 |
Item::Directive ReadDirective(); |
152 |
Item::Directive ReadString(); |
153 |
Item::Directive ReadDirectiveOrString(); |
154 |
|
155 |
void CreateTreeReadItemDirectiveCheckEnding(Item & item); |
156 |
|
157 |
void ReadDirectiveIfany(Item & item); |
158 |
void ReadDirectiveIfno(Item & item); |
159 |
void ReadDirectiveIfone(Item & item); |
160 |
void ReadDirectiveIs(Item & item); |
161 |
void ReadDirectiveIsno(Item & item); |
162 |
void ReadDirectiveIfindex(Item & item); |
163 |
void ReadDirectiveFor(Item & item); |
164 |
void ReadDirectiveComment(Item & item); |
165 |
void ReadDirectiveInclude(Item & item); |
166 |
void ReadDirectiveDef(Item & item); |
167 |
void ReadDirectiveNormal(Item::Directive & directive, Item & item); |
168 |
|
169 |
void CreateTreeReadItemDirective(Item & item); |
170 |
|
171 |
void CreateTreeReadItemText(Item & item); |
172 |
bool CreateTreeReadItem(Item & item); |
173 |
|
174 |
void CreateTreeReadIf(Item & item); |
175 |
void CreateTreeReadFor(Item & item); |
176 |
void CreateTree(Item & item); |
177 |
|
178 |
void CreateTreeReadInclude(Item & item); |
179 |
void CreateTreeReadIncludeSkipAllowFlag(Item & item); |
180 |
|
181 |
}; // Pattern |
182 |
|
183 |
|
184 |
|
185 |
|
186 |
|
187 |
struct Info |
188 |
{ |
189 |
// output stream |
190 |
std::ostringstream & out; |
191 |
|
192 |
// an optional string parameter in a normal statement [user_function "parameter"] |
193 |
// or in "is" statement [is user_function "parameter"] |
194 |
// or in "for" statement [for user_function "parameter"] |
195 |
const std::string & par; |
196 |
|
197 |
// this is set by Generator |
198 |
// normally is 0 |
199 |
// in a [for] statement it indicates the number of the current iteration (the first is 0) |
200 |
int iter; |
201 |
|
202 |
// return value from a user function (default false if not set directly by the user function) |
203 |
// for a variable it is set to true if the variable is not empty |
204 |
bool res; |
205 |
|
206 |
// arguments: output_stream, string_parameter |
207 |
Info(std::ostringstream & o, const std::string & p); |
208 |
void Clear(); |
209 |
}; |
210 |
|
211 |
|
212 |
|
213 |
|
214 |
// functions or variables |
215 |
class Functions |
216 |
{ |
217 |
public: |
218 |
|
219 |
typedef void (*UserFunction)(Info &); |
220 |
enum Type { function, variable }; |
221 |
|
222 |
struct Function |
223 |
{ |
224 |
Type type; |
225 |
|
226 |
UserFunction user_function; |
227 |
std::string variable; |
228 |
|
229 |
int iter; |
230 |
bool is_for; // true if is used by a [for] statement |
231 |
bool is_running; // true if this function (if is) is currently running |
232 |
|
233 |
Function(); |
234 |
}; |
235 |
|
236 |
void Insert(const std::string & key, UserFunction ufunction); // inserting a function |
237 |
void Insert(const std::string & key, const char * var); // inserting a variable |
238 |
void Insert(const std::string & key, const std::string & var); // inserting a variable |
239 |
|
240 |
bool Find(const std::string & key, Function ** fun); |
241 |
void Clear(); |
242 |
|
243 |
|
244 |
private: |
245 |
typedef std::map<std::string, Function> FunctionsTable; |
246 |
FunctionsTable functions_table; |
247 |
}; |
248 |
|
249 |
|
250 |
|
251 |
|
252 |
|
253 |
|
254 |
|
255 |
class Generator |
256 |
{ |
257 |
public: |
258 |
|
259 |
Generator(); |
260 |
Generator(std::ostringstream & o, Pattern & p, Functions & f); |
261 |
|
262 |
void SetOutStream(std::ostringstream & o); |
263 |
void SetPattern(Pattern & p); |
264 |
void SetFunctions(Functions & f); |
265 |
void SetMax(int max_items_, int max_for_items_); |
266 |
|
267 |
void Generate(); |
268 |
|
269 |
private: |
270 |
|
271 |
std::ostringstream * output_stream; |
272 |
Pattern * pattern; |
273 |
Functions * functions; |
274 |
|
275 |
int current_item; |
276 |
int max_items; |
277 |
int max_for_items; |
278 |
|
279 |
// an empty string for info objects |
280 |
const std::string empty; |
281 |
|
282 |
bool Find(const std::string & key, Functions::Function ** function); |
283 |
|
284 |
|
285 |
void Call(Functions::Function * function, Info & info); |
286 |
bool Call(const std::string & name, Info & info, Functions::Function ** pfun = 0); |
287 |
|
288 |
void CallUserFunction(Functions::Function * function, Info & info); |
289 |
void CallVariable(Functions::Function * function, Info & info); |
290 |
|
291 |
void MakeTextIf_go(Pattern::Item & item, bool result); |
292 |
bool MakeTextIfindexnumber(Pattern::Item & item, Functions::Function * function, bool & result); |
293 |
void MakeTextIfany(Pattern::Item & item); |
294 |
void MakeTextIfno(Pattern::Item & item); |
295 |
void MakeTextIfone(Pattern::Item & item); |
296 |
void MakeTextIfindex(Pattern::Item & item); |
297 |
void MakeTextForLoop(Pattern::Item & item, Functions::Function * function); |
298 |
void MakeTextFor(Pattern::Item & item); |
299 |
void MakeTextContainer(Pattern::Item & item); |
300 |
void MakeTextNormal(Pattern::Item & item); |
301 |
bool MakeTextIsFunText(const std::string & fun_name, const std::string & text, bool & res); |
302 |
bool MakeTextIsFunFun(const std::string & fun_name1, const std::string & fun_name2, bool & res); |
303 |
void MakeTextIs(Pattern::Item & item, bool isno = false); |
304 |
void MakeTextDefine(Pattern::Item & item); |
305 |
void MakeText(Pattern::Item & item); |
306 |
|
307 |
}; // Generator |
308 |
|
309 |
} // namespace Ezc |
310 |
|
311 |
|
312 |
#endif |