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