`RandomChance` type, and two new item fields: `MagicEffectChance`, `MagicEffectDuration`
[k8-i-v-a-n.git] / src / felib / feparse.h
blob69ee150de38d663c099cef6d6ec3d4b0e3fe5984
1 /*
3 * Iter Vehemens ad Necem (IVAN)
4 * Copyright (C) Timo Kiviluoto
5 * Released under the GNU General
6 * Public License
8 * See LICENSING which should be included
9 * along with this file for more details
12 #ifndef __FELIB_PARSE_H__
13 #define __FELIB_PARSE_H__
15 #include "feerror.h"
16 #include "festring.h"
17 #include "fearray.h"
18 #include "fesave.h"
19 #include "femath.h"
22 // ////////////////////////////////////////////////////////////////////////// //
23 class TextInput;
24 class TextInputFile;
25 class MemTextFile;
26 struct InputFileSaved;
29 using valuemap = std::map<festring, sLong>;
30 using InputFileGetVarFn = festring (*) (TextInput *fl, cfestring &name);
33 // ////////////////////////////////////////////////////////////////////////// //
34 class TextInput {
35 protected:
36 TextInput (const valuemap *aValueMap=0);
38 void setup (const valuemap *aValueMap);
40 public:
41 virtual ~TextInput ();
43 virtual cfestring &GetFileName () const = 0;
44 virtual truth IsOpen () = 0;
45 truth Eof ();
46 virtual void Close (); // for dtor
48 int GetChar ();
49 void UngetChar (int ch);
51 festring ReadWord (truth abortOnEOF=true);
52 truth ReadWord (festring &str, truth abortOnEOF=true); // returns `false` on EOF
53 char ReadLetter (truth abortOnEOF=true);
54 sLong ReadNumber (int CallLevel=HIGHEST, truth PreserveTerminator=false, truth *wasCloseBrc=0);
55 festring ReadStringOrNumber (sLong *num, truth *isString, truth PreserveTerminator=false, truth *wasCloseBrc=0);
56 sLong ReadNumberKeepStr (int CallLevel=HIGHEST, truth PreserveTerminator=false, truth *wasCloseBrc=0);
57 festring ReadStringOrNumberKeepStr (sLong *num, truth *isString, truth PreserveTerminator=false, truth *wasCloseBrc=0);
58 v2 ReadVector2d ();
59 rect ReadRect ();
60 float ReadFloat ();
62 festring getVar (cfestring &name);
63 void setVar (cfestring &name, cfestring &value);
64 truth delVar (cfestring &name);
66 void setGetVarCB (InputFileGetVarFn cb) { mGetVar = cb; }
68 void die (cfestring &msg);
70 void skipBlanks (); // comments too
72 int countArrayItems (char echar);
74 inline int TokenLine () const { return mTokenLine; }
75 inline int CurrentLine () const { return mCurrentLine; }
77 // when reading a number, and `mCollectingNumStr` flag is set, this will be filled
78 inline cfestring& numStr () const { return mNumStr; }
80 int gotCharSkipComment (int ch, truth allowSingleLineComments=true); // just read `ch`, skip possible comment; returns `ch` or -1
82 protected:
83 template<typename numtype> festring ReadNumberIntr (int CallLevel, numtype *num, truth *isString, truth allowStr, truth PreserveTerminator, truth *wasCloseBrc, truth allowFloats);
85 festring findVar (cfestring &name, truth *found) const;
86 truth readWordIntr (festring &String, truth abortOnEOF); // returns `false` on EOF
88 festring readCondition (festring &token, int prio, truth skipIt);
90 protected:
91 virtual int realGetChar () = 0;
92 virtual truth isRealEof () = 0;
94 // used to save/restore parsing positions
95 virtual sLong realGetPos () = 0;
96 virtual void realSetPos (sLong apos) = 0;
98 protected:
99 enum { MaxUngetChars = 4 };
100 typedef std::map<festring, festring> VarMap;
102 protected:
103 const valuemap *ValueMap;
104 truth lastWasNL;
105 truth lastWordWasString;
106 VarMap mVars;
107 InputFileGetVarFn mGetVar;
108 std::stack<int> mIfStack;
109 int mCharBuf[MaxUngetChars];
110 int mCharBufPos;
111 int mCurrentLine;
112 int mTokenLine;
113 festring mNumStr; // when reading a number, and `mCollectingNumStr` flag is set, this will be filled
114 truth mCollectingNumStr;
115 truth mAllowFloatNums;
117 friend InputFileSaved;
121 // ////////////////////////////////////////////////////////////////////////// //
122 class TextInputFile : public TextInput {
123 public:
124 TextInputFile (cfestring &FileName, const valuemap *aValueMap=0, truth AbortOnErr=true);
125 virtual ~TextInputFile ();
127 virtual cfestring &GetFileName () const override;
128 virtual truth IsOpen () override;
129 virtual void Close () override;
131 protected:
132 virtual int realGetChar () override;
133 virtual truth isRealEof () override;
135 virtual sLong realGetPos () override;
136 virtual void realSetPos (sLong apos) override;
138 protected:
139 inputfile ifile;
143 // ////////////////////////////////////////////////////////////////////////// //
144 class MemTextFile : public TextInput {
145 public:
146 MemTextFile (cfestring &afname, cfestring &str, const valuemap *aValueMap=0);
147 MemTextFile (cfestring &afname, int stline, cfestring &str, const valuemap *aValueMap=0);
148 virtual ~MemTextFile ();
150 virtual cfestring &GetFileName () const override;
151 virtual truth IsOpen () override;
152 virtual void Close () override;
154 protected:
155 virtual int realGetChar () override;
156 virtual truth isRealEof () override;
158 virtual sLong realGetPos () override;
159 virtual void realSetPos (sLong apos) override;
161 protected:
162 unsigned char *buf;
163 int bufSize;
164 int bufPos;
165 festring tfname;
169 // ////////////////////////////////////////////////////////////////////////// //
170 // `rand()` returns `add+RAND_N(rnd)`
171 // `inRange()` returns `true` if `rand()` is in [rmin..rmax] (inclusive!)
172 // script syntax:
173 // RCField = { add: num; rnd: num; rmin: num; rmax: num; }
174 // any field may absent
175 // or simplified:
176 // RCField == rnd;
177 struct RandomChance {
178 sLong add = 0;
179 sLong rnd = 0;
180 sLong rmin = 0, rmax = 0;
182 inline void clear () { add = rnd = rmin = rmax = 0; }
183 inline sLong rand () const { return add+RAND_N(rnd); }
184 // if `rnd` is zero, assume "no chances"
185 inline truth inRange () const { if (rnd > 0) { auto v = rand(); return (v >= rmin && v <= rmax); } return false; }
189 inline void ReadData (char &Type, TextInput &infile) { Type = infile.ReadNumber(); }
190 inline void ReadData (uChar &Type, TextInput &infile) { Type = infile.ReadNumber(); }
191 inline void ReadData (short &Type, TextInput &infile) { Type = infile.ReadNumber(); }
192 inline void ReadData (uShort &Type, TextInput &infile) { Type = infile.ReadNumber(); }
193 //inline void ReadData (sLong &Type, inputfile &SaveFile) { Type = SaveFile.ReadNumber(); } //k8:64
194 inline void ReadData (feuLong &Type, TextInput &infile) { Type = infile.ReadNumber(); }
195 inline void ReadData (int &Type, TextInput &infile) { Type = infile.ReadNumber(); }
196 inline void ReadData (packv2 &Type, TextInput &infile) { Type = infile.ReadVector2d(); }
197 inline void ReadData (v2 &Type, TextInput &infile) { Type = infile.ReadVector2d(); }
198 inline void ReadData (rect &Type, TextInput &infile) { Type = infile.ReadRect(); }
199 inline void ReadData (float &Type, TextInput &infile) { Type = infile.ReadFloat(); }
201 void ReadData (festring &, TextInput &);
202 void ReadData (fearray<sLong> &, TextInput &);
203 void ReadData (fearray<festring> &, TextInput &);
204 void ReadData (RandomChance &rc, TextInput &fl);
206 template <class type> void ReadData (fearray<type> &Array, TextInput &infile) {
207 Array.Clear();
208 festring Word;
209 infile.ReadWord(Word);
210 // one element?
211 if (Word == "==") {
212 Array.Allocate(1);
213 ReadData(Array.Data[0], infile);
214 return;
216 // more than one element
217 typedef typename fearray<type>::sizetype sizetype;
218 sizetype Size;
219 // unknown number of elements?
220 if (Word == ":=") {
221 infile.ReadWord(Word);
222 if (Word != "{") ABORT("Array syntax error \"%s\" found in file %s, line %d!", Word.CStr(), infile.GetFileName().CStr(), infile.TokenLine());
223 //fprintf(stderr, "counting array items; file: '%s'; line: %u\n", SaveFile.GetFileName().CStr(), SaveFile.TokenLine());
224 int count = infile.countArrayItems('}');
225 // HACK
226 if (count < 1) ABORT("Array count error found in file %s, line %d!", infile.GetFileName().CStr(), infile.TokenLine());
227 Size = count;
228 //fprintf(stderr, "counted %u array items; file: '%s'; line: %u\n", Size, SaveFile.GetFileName().CStr(), SaveFile.TokenLine());
229 } else {
230 if (Word != "=") ABORT("Array syntax error: '=', '==' or ':=' expected in file %s, line %u!", infile.GetFileName().CStr(), infile.TokenLine());
231 infile.ReadWord(Word);
232 if (Word != "{") ABORT("Array syntax error \"%s\" found in file %s, line %u!", Word.CStr(), infile.GetFileName().CStr(), infile.TokenLine());
233 Size = infile.ReadNumber();
234 int count = infile.countArrayItems('}');
235 if (count < 1) ABORT("Array count error found in file %s, line %d!", infile.GetFileName().CStr(), infile.TokenLine());
236 //HACK: 2 for vectors, 4 for rects
237 //if ((sizetype)count != Size && (sizetype)count/2 != Size && (sizetype)count/4 != Size) ABORT("Array count error (%u != %d) found in file %s, line %d!", Size, count, SaveFile.GetFileName().CStr(), SaveFile.TokenLine());
238 if ((sizetype)count != Size) ABORT("Array count error (%u != %d) found in file %s, line %d!", Size, count, infile.GetFileName().CStr(), infile.TokenLine());
240 Array.Allocate(Size);
241 for (sizetype c = 0; c < Size; ++c) ReadData(Array.Data[c], infile);
242 if (infile.ReadWord() != "}") ABORT("Illegal array terminator \"%s\" encountered in file %s, line %u!", Word.CStr(), infile.GetFileName().CStr(), infile.TokenLine());
246 // ////////////////////////////////////////////////////////////////////////// //
247 struct EventHandlerSource {
248 festring type;
249 int startline;
250 festring text;
251 festring fname;
255 struct EventHandlerMap {
256 private:
257 //EventHandlerMap (const EventHandlerMap &); // disable copying
259 public:
260 EventHandlerMap ();
261 virtual ~EventHandlerMap ();
263 void clear ();
265 // "on" skipped, expecting type
266 void collectSource (std::stack<TextInput *> &infStack, TextInput **iff);
268 // "on" skipped, expecting type
269 void collectSource (TextInput &iff);
271 // can return `nullptr`
272 TextInput *openHandler (cfestring &atype, const valuemap *aValueMap=0) const;
274 private:
275 std::map<festring, EventHandlerSource> mMap;
279 festring collectSourceCode (std::stack<TextInput *> &infStack, TextInput **iff);
280 EventHandlerSource collectEventHandlerSource (std::stack<TextInput *> &infStack, TextInput **iff);
283 #endif