initial import
[vym] / parser.cpp
1 #include "parser.h"
2
3 #include <QRegExp>
4 #include <iostream>
5
6 using namespace std;
7
8 Parser::Parser()
9 {
10         initParser();
11 }
12
13 void Parser::initParser()
14 {
15         initAtom();
16         current=-1;
17 }
18
19 void Parser::initAtom()
20 {
21         atom="";
22         com="";
23         paramList.clear();
24         resetError();
25 }
26
27 void Parser::parseAtom (QString s)
28 {
29         initAtom();
30         atom=s;
31         QRegExp re;
32         int pos;
33
34         // Strip WS at beginning
35         re.setPattern ("\\w");
36         re.setMinimal (true);
37         pos=re.search (atom);
38         if (pos>=0)
39                 s=s.right(s.length()-pos);
40
41         // Get command
42         re.setPattern ("\\b(.*)(\\s|\\()");
43         pos=re.search (s);
44         if (pos>=0)
45                 com=re.cap(1);
46
47         // Get parameters
48         paramList.clear();
49         re.setPattern ("\\((.*)\\)");
50         pos=re.search (s);
51         //cout << "  s="<<qPrintable(s)<<endl;
52         //cout << "com="<<qPrintable(com)<<"  pos="<<pos<<endl<<endl;
53         if (pos>=0)
54         {
55                 QString s=re.cap(1);
56                 QString a;
57                 bool inquote=false;
58                 pos=0;
59                 if (!s.isEmpty())
60                 {
61                         while (pos<s.length())
62                         {
63                                 if (s.at(pos)=='\"') 
64                                 {
65                                         if (inquote)
66                                                 inquote=false;
67                                         else    
68                                                 inquote=true;
69                                 }
70
71                                 if (s.at(pos)==',' && !inquote)
72                                 {
73                                         a=s.left(pos);
74                                         paramList.append(a);
75                                         s=s.right(s.length()-pos-1);
76                                         pos=0;
77                                 } else
78                                         pos++;
79                                 
80                         }
81                         paramList.append (s);
82                 }       
83         }       
84 }
85
86 QString Parser::getAtom()
87 {
88         return atom;
89 }
90
91 QString Parser::getCommand()
92 {
93         return com;
94 }
95
96 QStringList Parser::getParameters()
97 {
98         return paramList;
99 }
100
101 int Parser::parCount()
102 {
103         return paramList.count();
104 }
105
106
107 QString Parser::errorMessage()
108 {
109         QString l;
110         switch (errLevel)
111         {
112                 case NoError: l="No Error";
113                 case Warning: l="Warning";
114                 case Aborted: l="Aborted";
115         }
116         return QString ("Error Level: %1\n    Command: %2\nDescription: %3")
117                 .arg(l).arg(com).arg(errDescription);
118 }
119
120 QString Parser::errorDescription()
121 {
122         return errDescription;
123 }
124
125 ErrorLevel Parser::errorLevel()
126 {
127         return errLevel;
128 }
129
130 void Parser::setError(ErrorLevel level, const QString &description)
131 {
132         errDescription=description;
133         errLevel=level;
134 }
135
136 void Parser::resetError ()
137 {
138         errMessage="";
139         errDescription="";
140         errLevel=NoError;
141 }
142
143
144 bool Parser::checkParCount (QList <int> plist)
145 {
146         QStringList expList;
147         QString expected;
148         for (int i=0; i<plist.count();i++)
149         {
150                 if (checkParCount (plist[i])) 
151                 {
152                         resetError();
153                         return true;
154                 }
155                 expList.append(QString().setNum(plist[i]));
156         }       
157         expected=expList.join(",");     
158         errDescription=QString("Wrong number of parameters: Expected %1, but found %2").arg(expected).arg(paramList.count());
159         return false;
160 }
161
162 bool Parser::checkParCount (const int &expected)
163 {
164         if (paramList.count()!=expected)
165         {
166                 errLevel=Aborted;
167                 errDescription=QString("Wrong number of parameters: Expected %1, but found %2").arg(expected).arg(paramList.count());
168                 return false;
169         } 
170         return true;    
171 }
172
173 bool Parser::checkParIsInt(const int &index)
174 {
175         bool ok;
176         if (index > paramList.count())
177         {
178                 errLevel=Aborted;
179                 errDescription=QString("Parameter index %1 is outside of parameter list").arg(index);
180                 return false;
181         } else
182         {
183                 paramList[index].toInt (&ok, 10);
184                 if (!ok)
185                 {
186                         errLevel=Aborted;
187                         errDescription=QString("Parameter %1 is not an integer").arg(index);
188                         return false;
189                 } 
190         }       
191         return true;
192 }
193
194 bool Parser::checkParIsDouble(const int &index)
195 {
196         bool ok;
197         if (index > paramList.count())
198         {
199                 errLevel=Aborted;
200                 errDescription=QString("Parameter index %1 is outside of parameter list").arg(index);
201                 return false;
202         } else
203         {
204                 paramList[index].toDouble (&ok);
205                 if (!ok)
206                 {
207                         errLevel=Aborted;
208                         errDescription=QString("Parameter %1 is not double").arg(index);
209                         return false;
210                 } 
211         }       
212         return true;
213 }
214
215 int Parser::parInt (bool &ok,const uint &index)
216 {
217         if (checkParIsInt (index))
218                 return paramList[index].toInt (&ok, 10);
219         ok=false;
220         return 0;
221 }
222
223 QString Parser::parString (bool &ok,const int &index)
224 {
225         // return the string at index, this could be also stored in
226         // a variable later
227         QString r;
228         QRegExp re("\"(.*)\"");
229         int pos=re.search (paramList[index]);
230         if (pos>=0)
231                 r=re.cap (1);
232         else    
233                 r="";
234         ok=true;
235         return r;
236 }
237
238 bool Parser::parBool (bool &ok,const int &index)
239 {
240         // return the bool at index, this could be also stored in
241         // a variable later
242         QString r;
243         ok=true;
244         QString p=paramList[index];
245         if (p=="true" || p=="1")
246                 return true;
247         else if (p=="false" || p=="0")
248                 return false;
249         ok=false;
250         return ok;
251 }
252
253 QColor Parser::parColor(bool &ok,const int &index)
254 {
255         // return the QColor at index
256         ok=false;
257         QString r;
258         QColor c;
259         QRegExp re("\"(.*)\"");
260         int pos=re.search (paramList[index]);
261         if (pos>=0)
262         {
263                 r=re.cap (1);
264                 c.setNamedColor(r);
265                 ok=c.isValid();
266         }       
267         return c;
268 }
269
270 double Parser::parDouble (bool &ok,const int &index)
271 {
272         if (checkParIsDouble (index))
273                 return paramList[index].toDouble (&ok);
274         ok=false;
275         return 0;
276 }
277
278 void Parser::setScript(const QString &s)
279 {
280         script=s;
281 }       
282
283 QString Parser::getScript()
284 {
285         return script;
286 }       
287
288 void Parser::runScript()
289 {
290         current=0;
291 }       
292
293 bool Parser::next()
294 {
295         int start=current;
296         if (current<0) runScript();
297         if (current>=script.length()-1) return false;
298
299         bool inBracket=false;
300         while (true)
301         {
302                 //cout <<"current="<<current<< "   start="<<start<<"  length="<<script.length()<<endl;
303
304                 // Check if we are inside a string
305                 if (script.at(current)=='"')
306                 {
307                         if (inBracket)
308                                 inBracket=false;
309                         else    
310                                 inBracket=true;
311                 }
312
313                 // Check if we are in a comment
314                 if (!inBracket && script.at(current)=='#')
315                 {
316                         while (script.at(current)!='\n')
317                         {
318                                 current++;
319                                 if (current>=script.length()) 
320                                         return false;
321                         }
322                         start=current;
323                 }
324
325                 // Check for end of atom
326                 if (!inBracket && script.at(current)==';')
327                 {
328                         atom=script.mid(start,current-start);
329                         current++;
330                         return true;
331                 }
332                 
333                 // Check for end of script
334                 if (current==script.length() )
335                 {
336                         if (inBracket)
337                         {
338                                 setError (Aborted,"Runaway string");
339                                 return false;
340                         } else
341                         {
342                                 atom=script.mid(start);
343                                 return true;
344                         }
345                 }
346                 current++;
347         }
348 }       
349