parser.cpp
author insilmaril
Tue, 19 Jun 2007 14:20:29 +0000
changeset 513 5f576e56ad99
parent 447 72afe12da1c8
child 514 497fab7d1404
permissions -rw-r--r--
Exports can (partly) be scripted
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@432
    51
	//cout << "  s="<<s.ascii()<<endl;
insilmaril@432
    52
	//cout << "com="<<com.ascii()<<"  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@432
   101
int Parser::paramCount()
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@432
   144
bool Parser::checkParamCount (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@432
   150
		if (checkParamCount (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@432
   162
bool Parser::checkParamCount (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@432
   173
bool Parser::checkParamIsInt(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@432
   194
int Parser::parInt (bool &ok,const uint &index)
insilmaril@432
   195
{
insilmaril@432
   196
	if (checkParamIsInt (index))
insilmaril@432
   197
		return paramList[index].toInt (&ok, 10);
insilmaril@432
   198
	ok=false;
insilmaril@432
   199
	return 0;
insilmaril@432
   200
}
insilmaril@432
   201
insilmaril@432
   202
QString Parser::parString (bool &ok,const int &index)
insilmaril@432
   203
{
insilmaril@432
   204
	// return the string at index, this could be also stored in
insilmaril@432
   205
	// a variable later
insilmaril@432
   206
	QString r;
insilmaril@432
   207
	QRegExp re("\"(.*)\"");
insilmaril@432
   208
	int pos=re.search (paramList[index]);
insilmaril@432
   209
	if (pos>=0)
insilmaril@432
   210
		r=re.cap (1);
insilmaril@432
   211
	else	
insilmaril@432
   212
		r="";
insilmaril@432
   213
	ok=true;
insilmaril@432
   214
	return r;
insilmaril@432
   215
}
insilmaril@432
   216
insilmaril@432
   217
bool Parser::parBool (bool &ok,const int &index)
insilmaril@432
   218
{
insilmaril@432
   219
	// return the bool at index, this could be also stored in
insilmaril@432
   220
	// a variable later
insilmaril@432
   221
	QString r;
insilmaril@432
   222
	ok=true;
insilmaril@432
   223
	QString p=paramList[index];
insilmaril@432
   224
	if (p=="true" || p=="1")
insilmaril@432
   225
		return true;
insilmaril@432
   226
	else if	(p=="false" || p=="0")
insilmaril@432
   227
		return false;
insilmaril@432
   228
	ok=false;
insilmaril@432
   229
	return ok;
insilmaril@432
   230
}
insilmaril@432
   231
insilmaril@432
   232
QColor Parser::parColor(bool &ok,const int &index)
insilmaril@432
   233
{
insilmaril@432
   234
	// return the QColor at index
insilmaril@445
   235
	ok=false;
insilmaril@445
   236
	QString r;
insilmaril@445
   237
	QColor c;
insilmaril@445
   238
	QRegExp re("\"(.*)\"");
insilmaril@445
   239
	int pos=re.search (paramList[index]);
insilmaril@445
   240
	if (pos>=0)
insilmaril@445
   241
	{
insilmaril@445
   242
		r=re.cap (1);
insilmaril@445
   243
		c.setNamedColor(r);
insilmaril@445
   244
		ok=c.isValid();
insilmaril@445
   245
	}	
insilmaril@445
   246
	return c;
insilmaril@432
   247
}
insilmaril@432
   248
insilmaril@432
   249
void Parser::setScript(const QString &s)
insilmaril@432
   250
{
insilmaril@432
   251
	script=s;
insilmaril@432
   252
}	
insilmaril@432
   253
insilmaril@432
   254
QString Parser::getScript()
insilmaril@432
   255
{
insilmaril@432
   256
	return script;
insilmaril@432
   257
}	
insilmaril@432
   258
insilmaril@445
   259
void Parser::runScript()
insilmaril@432
   260
{
insilmaril@447
   261
	current=0;
insilmaril@432
   262
}	
insilmaril@432
   263
insilmaril@447
   264
bool Parser::next()
insilmaril@445
   265
{
insilmaril@447
   266
	int start=current;
insilmaril@447
   267
	if (current<0) runScript();
insilmaril@447
   268
	if (current>=script.length()-1) return false;
insilmaril@447
   269
insilmaril@447
   270
	bool inBracket=false;
insilmaril@447
   271
	while (true)
insilmaril@447
   272
	{
insilmaril@447
   273
		//cout <<"current="<<current<< "   start="<<start<<"  length="<<script.length()<<endl;
insilmaril@447
   274
insilmaril@447
   275
		// Check if we are inside a string
insilmaril@447
   276
		if (script.at(current)=='"')
insilmaril@447
   277
		{
insilmaril@447
   278
			if (inBracket)
insilmaril@447
   279
				inBracket=false;
insilmaril@447
   280
			else	
insilmaril@447
   281
				inBracket=true;
insilmaril@447
   282
		}
insilmaril@447
   283
insilmaril@447
   284
		// Check if we are in a comment
insilmaril@447
   285
		if (!inBracket && script.at(current)=='#')
insilmaril@447
   286
		{
insilmaril@447
   287
			while (script.at(current)!='\n')
insilmaril@447
   288
			{
insilmaril@447
   289
				current++;
insilmaril@447
   290
				if (current>=script.length()) 
insilmaril@447
   291
					return false;
insilmaril@447
   292
			}
insilmaril@447
   293
			start=current;
insilmaril@447
   294
		}
insilmaril@447
   295
insilmaril@447
   296
		// Check for end of atom
insilmaril@447
   297
		if (!inBracket && script.at(current)==';')
insilmaril@447
   298
		{
insilmaril@447
   299
			atom=script.mid(start,current-start);
insilmaril@447
   300
			current++;
insilmaril@447
   301
			return true;
insilmaril@447
   302
		}
insilmaril@447
   303
		
insilmaril@447
   304
		// Check for end of script
insilmaril@447
   305
		if (current==script.length() )
insilmaril@447
   306
		{
insilmaril@447
   307
			if (inBracket)
insilmaril@447
   308
			{
insilmaril@447
   309
				setError (Aborted,"Runaway string");
insilmaril@447
   310
				return false;
insilmaril@447
   311
			} else
insilmaril@447
   312
			{
insilmaril@447
   313
				atom=script.mid(start);
insilmaril@447
   314
				return true;
insilmaril@447
   315
			}
insilmaril@447
   316
		}
insilmaril@447
   317
		current++;
insilmaril@447
   318
	}
insilmaril@445
   319
}	
insilmaril@445
   320