/***************************************************************************
 *   Copyright (C) 2005 by Juergen Thies                                   *
 *   layout@juergenthies.de                                                *
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 *   This program is distributed in the hope that it will be useful,       *
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of        *
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the         *
 *   GNU General Public License for more details.                          *
 *                                                                         *
 *   You should have received a copy of the GNU General Public License     *
 *   along with this program; if not, write to the                         *
 *   Free Software Foundation, Inc.,                                       *
 *   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.             *
 ***************************************************************************/

#include "general/errorreport.h"
#include "variant.h"
#include "parservalue.h"
#include "keywords.h"
#include "includes.h"
#include <QFileInfo>
#include <QFile>
#include <QTextStream>
#include <QString>
/*
errorreport *generalHandler::error;
QString generalHandler::code;
QString generalHandler::fileName;
int generalHandler::tmpVarCounter=0;
int generalHandler::lastCounter;
bool generalHandler::returnState;
includes generalHandler::include[1000];
int generalHandler::includeCount;
keywords *generalHandler::globals;*/




parserValue macro::next(int *counter){
QString startKeyword="abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
QString allowedKeyword=startKeyword+"1234567890_öäüÜÄÖß";
QString numberChar="0123456789.";
QString hexnum="0123456789ABCDEFabcdef";
QString operatorChar="-+*/<>=!:.%&|";
QString ignoreChar=" \n\r\t";
QString lineChar="\n\r";
QString s;
bool newline=true;
int compilerCommandStart=0;
parserValue parser;
parser.type=unknown;
lastCounter=(*counter);
do {
  s=code.mid((*counter),1);
  switch (parser.type) {
  case keyword:
  	if (allowedKeyword.indexOf(s)>=0) {  
         parser.value+=s;
       	}
        else { //printf("%s\n",parser.value.latin1()); 
	       return parser;}
  	break;
  case number:
        if (numberChar.indexOf(s)>=0) {  
         parser.value+=s;
       	}
	else if ((s=="e")||(s=="E")) {
	 QString sh=code.mid((*counter)+1,1);
	 int plus=0;
	 if (sh=="-") {sh=code.mid((*counter)+2,1);plus++;}
	 if (numberChar.indexOf(sh)>=0) {
		(*counter)+=plus;
		parser.value+=s;
		if (plus==1) parser.value+="-";
		}
	  else {
	   parser.numValue=parser.value.toDouble();
	   return parser;
	   }
	}
        else {
	   parser.numValue=parser.value.toDouble();
	   return parser;
	   }
  	break;
  case op:
        {
	int pos=operatorChar.indexOf(s);
        if ((pos>0)||(pos==0 && (parser.value=="-") )) {  
         parser.value+=s;
       	}
	else if ((parser.value=="-")&&(numberChar.indexOf(s)>=0)) {
		parser.value+=s;
		parser.type=number;
		}
        else return parser;
  	break;
	}
  case string:
  	if (s=="\"") {(*counter)++;return parser;}
	else {
		if (s!="\\") parser.value+=s;
		else {
		(*counter)++;
		s=code.mid((*counter),1);
		if (s=="n") parser.value+="\n";
		else if (s=="r") parser.value+="\r";
		else if (s=="t") parser.value+="\t";
		else if (s=="\\") parser.value+="\\";
		else if (s=="\0") parser.value+="\0";
		else if (s=="0") parser.value+="\0";
		else if (s=="x") {
		    int num=0;
		    int pos=0;
		    do {
		    (*counter)++;
		    s=code.mid((*counter),1);
		    pos=hexnum.indexOf(s);
		    if (pos>=0) {
		      if (pos>15) pos-=6;
		      num=num*16+pos;
		    }}
		    while (pos>=0);
		    (*counter)--;
		    parser.value+=QString(QChar(num));
		}
		else parser.value+=s;
		}
	}
  	break;
  case compiler:
	/*if (row(counter)>3) error->addItem(tr("Compiler-Commands are not supported."),2,s.setNum(row(counter)));
		nextLine(counter);
		(*counter)--;*/
	//printf("compiler command: (%s)\n",parser.value.ascii());
	//printf("start: %d,%d\n",compilerCommandStart,(*counter));
	if (!(ignoreChar.indexOf(s)>=0)){parser.value+=s;} 
	else if (parser.value=="include") { 
		//printf("include\n");
		parser=next(counter);
		if (parser.type==string) {
			includeFile(compilerCommandStart, (*counter),parser.value);
			(*counter)=compilerCommandStart-1;
			compilerCommandStart=0;}
		else {error->addItem(tr("Filename expected."),1,message(*counter));}
		parser.type=unknown;
		newline=true;}
	else error->addItem(tr("Compiler-Command is not supported."),2,message(*counter));
	if (lineChar.indexOf(s)>=0){newline=true;parser.type=unknown;};
	break;
  case unknown:
  	if (startKeyword.indexOf(s)>=0) {
	  parser.value=s;
	  parser.type=keyword;
	  }
	else if (numberChar.indexOf(s)>=0) {
	  parser.value=s;
	  parser.type=number;
	  }
	else if (operatorChar.indexOf(s)>=0) {
	  parser.value=s;
	  parser.type=op;
	  }
	else if (s=="\"") {
	  parser.value="";
	  parser.type=string;
	  }
	else if (s=="{") {parser.type=braceOpen;(*counter)++; return parser;}
	else if (s=="}") {parser.type=braceClose;(*counter)++; return parser;}
	else if (s=="[") {parser.type=bracketOpen; (*counter)++;return parser;}
	else if (s=="]") {parser.type=bracketClose;(*counter)++; return parser;}
	else if (s=="(") {parser.type=parenOpen;(*counter)++; return parser;}
	else if (s==")") {parser.type=parenClose;(*counter)++; return parser;}
	else if (s==";") {parser.type=semicolon;(*counter)++; return parser;}
	else if (s==",") {parser.type=comma;(*counter)++; return parser;}
	else if (s=="#") {
		if (newline&&(row(counter)>3)) {parser.type=compiler;parser.value="";}
		else {
			nextLine(counter);
			(*counter)--;}
		compilerCommandStart=(*counter);
		}
	else if (ignoreChar.indexOf(s)>=0){};
	if (s=="/") {
		s=code.mid((*counter),2);
		if (s=="/*") {endComment(counter);(*counter)--;parser.type=unknown;}
		else if (s=="//") {nextLine(counter);(*counter)--;parser.type=unknown;}
    		}
	break;
  default:
  	break;
  }	
  if (lineChar.indexOf(s)>=0){newline=true;};
  if (ignoreChar.indexOf(s)<0){newline=false;};
  (*counter)++;
} while ((*counter)<=(int)code.length());
throw 4;
}
   

void macro::endComment(int *counter){
(*counter)=code.indexOf("*/",*counter)+2;
if (*counter<=0) throw 5;
} 
 
void macro::nextLine(int *counter){
*counter = code.indexOf('\n',*counter)+1;
if ((*counter) > int(code.length())) (*counter)=0;
if (*counter<=0) throw 4;
}



void macro::closeBrace(int *counter){
parserValue p;
int level=1;
QString s;
do {
   p=next(counter);
   if (p.type==braceOpen) level++;
   else if (p.type==braceClose) level--;
}while (level!=0);
}

void macro::closeParen(int *counter){
parserValue p;
int level=1;
QString s;
do {
   p=next(counter);
   if (p.type==parenOpen) level++;
   else if (p.type==parenClose) level--;
}while (level!=0);
}
QString macro::message(int ro){
    QString s,m;
    int r=row(&ro);
    s=getFileName(&r);
    m.setNum(r);
    if (s==fileName) {s=tr("row")+" "+m;}
    else {
    	s=s+" "+tr("row")+" "+m;}
   // m.setNum(ro);
   // s=s+"(counter:"+m+")";
    return s;
}

int macro::row (int *counter){
  int row=1;
  for (int i=1;i<=(*counter);i++){
	if (code.mid(i,1)=="\n") row++;	
	}
  return row;
}

QString macro::getFileName(int *row){
 // printf("search row %d %d\n",*row,includeCount);
  int num=0;
  int newrow=(*row);
  int altstart=0;
  for (int i=0;i<includeCount;i++){
	if ((include[i].start<=(*row))&&(include[i].start>altstart)){
		num=i;
		altstart=include[i].start;
		newrow=(*row)-include[i].start+include[i].offset+1;
		//printf("s i %d: row %d newrow %d\n",i,*row,newrow);
		}
	}
  (*row) = newrow;
 for (int i=0;i<includeCount;i++){
 //printf("include %d: name %s start %d offset %d\n",i,include[i].fileName.toLatin1().data(),include[i].start,include[i].offset );
 }

  return include[num].fileName;
}

void macro::includeFile(int start, int end, QString fn){
  int startrow=row(&start);
  int filerow=startrow;
  QString file=getFileName(&filerow);
  QFileInfo fi(file);
  QString s=fi.path();
  fn=s+"/"+fn;
  QFile f(fn);
   if ( !f.open( QIODevice::ReadOnly ) ){
	//error->addItem(tr("File not found."),2,message(start));
	throw 34; }
  QTextStream ts( &f );
  if (codec!="") ts.setCodec(QTextCodec::codecForName(codec.toAscii().data()));
  QString newcode="\n";
  newcode=ts.readAll();
  f.close();
  QString left=code.left(start);
  QString right=code.mid(end);
  code=left+newcode+"\n"+right;
  //printf("new Code:\n%s\n",code.toLatin1().data());
  //printf("code:\n%s\n",code.ascii());
  int help=start+newcode.length()+1;
  help=row(&help);
  int addrow=help-startrow;
  for (int i=0;i<includeCount;i++){
	if (include[i].start>(startrow)){include[i].start+=addrow-1;}
  }
  include[includeCount].start=help-1;
  include[includeCount].fileName=file;
  include[includeCount].offset=filerow-1;
  includeCount++;
  include[includeCount].start=startrow;
  include[includeCount].fileName=fn;
  include[includeCount].offset=0;
  includeCount++;
/*if (includeCount==7)printf("%s\n",code.toAscii().data());
  for (int i=0;i<includeCount;i++){
 printf("insert %d: name %s start %d offset %d\n",i,include[i].fileName.toLatin1().data(),include[i].start,include[i].offset );}*/
}

void macro::compute(returnValue *r,int *counter,keywords *keyword){
  //printf("vor compute:%d-,-%s\n",r->getInt(),r->getString().latin1());
  parserValue p=next(counter);
  QString s;
  if (p.type!=op )throw 6;
  if (p.value=="=") *r<<calculate(counter,keyword);
  else if (p.value=="+=") (*r)+=calculate(counter,keyword);
  else if (p.value=="-=") (*r)-=calculate(counter,keyword);
 // else if (p.value=="=-") {
//	returnValue r2; r2.setDouble(0);(*r)= r2-calculate(counter,keyword);}
  else if (p.value=="*=") (*r)*=calculate(counter,keyword);
  else if (p.value=="/=") (*r)/=calculate(counter,keyword);
  else if (p.value=="++") (*r) ++ ;
  else if (p.value=="--") (*r) --;
  else throw 7;
  p=next(counter);
  if ((p.type!=semicolon)&& (p.type!=parenClose)) {throw 15;}	
  //printf("compute:%d--%d\n",r->getInt(),r->data);
 //printf("compute:%d-,-%s\n",r->getInt(),r->getString().latin1());
}

variant macro::calculate(int *counter,keywords *keyword_){
  QString exp=" ";
  QString s;
  parserValue p;
  keywords *keywordLocal = keyword_;
  int lastCounter=*counter;
  int parenLevel=0;
  parserType lastType=op;
  do {
 	lastCounter=*counter;
 	p=next(counter);
	switch (p.type){
	case op:
		//printf("operator\n");
		exp+=p.value+" ";
		lastType=op;
		break;
	case keyword:
		{ 
		//printf("keyword %s\n",p.value.toAscii().data());
		keywords *help=keywordLocal;
		bool found=false;
		int hCounter=*counter;
		bool noType = checkStaticClass(counter);
		*counter=hCounter;
		while ((help!=NULL)&&(found==false)){
		 if (help->keyword==p.value) 
			if (noType && (help->type==type)) help=help->next;
			else found=true;
		 else help=help->next;
		}
		if (found) {
			if (help->type==type) {
				(this->*help->typeHandler)(counter,&keywordLocal,false);
				}
			if (help->type==intClass) {
				variant r;
				int hcounter=(*counter);
				r=(this->*help->classHandler)(counter,keywordLocal,(help->r),false);
				if (hcounter!=(*counter)){
					exp+=addTmpKeyword(&keywordLocal,r)+" ";}
				else { exp+=help->keyword+" "; }
				}
			if (help->type==func) {
				variant r;
				r=funcHandler(counter,&help->counter,&help->parameter,keywordLocal,help->r->type);
				exp+=addTmpKeyword(&keywordLocal,r)+" ";
				}
			if (help->type==var) {exp+=help->keyword+" ";}
		}
		else {	 if (error!=NULL) error->addItem(tr("Unknown identifier ")+p.value,1,message(*counter));throw 0;}
		lastType=keyword;
		}
		break;
	case number:{
		//printf("number %f\n",p.numValue);
		returnValue r;
		if ((lastType!=op)&&(exp.size()>1)&&(p.numValue<0)){
			exp+="- ";
			r.setDouble( - p.numValue);
		}
		else
		 r.setDouble(p.numValue);
		//printf("number%f\n",r.getDouble());
		exp+=addTmpKeyword(&keywordLocal,r)+" ";
		//printf("n:%s\n",exp.toLatin1().data());
		lastType=number;
		}
		break;
	case string:{
		//printf("string\n");
		returnValue r;
		r.setString(p.value);
		exp+=addTmpKeyword(&keywordLocal,r)+" ";
		//printf("s:%s\n",exp.toLatin1().data());
		lastType=string;
		}
		break;
	case parenClose:
		//printf("parenClose\n");
		parenLevel--;
		if (parenLevel>=0) exp+=") ";
		lastType=parenClose;
		break;
	case parenOpen:
		//printf("parenOpen\n");
		parenLevel++;
		exp+="( ";
		lastType=parenOpen;
		break;
	default:
		if ((p.type!=semicolon)&&(p.type!=comma)&&(p.type!=bracketClose)) throw 2;
	}
  } while ((p.type!=semicolon)&&(p.type!=bracketClose)&&(p.type!=comma)&&!((p.type==parenClose)&&(parenLevel==-1)));
  //printf("calc:%s\n",exp.toLatin1().data());
  //berechnen bis ;,)
  returnValue r;
  r=calculate(exp,&keywordLocal);
  *counter=lastCounter;
  cleanKeywords(&keywordLocal,keyword_);
  //printf("calculate%d-,-%s--%d\n",r.getInt(),r.getString().toLatin1().data(),r.DrawingField);
  //printf("calculate%d\n",r.data);
  return r;
} 


 returnValue  macro::calculate(QString s,keywords **keyword){
  returnValue r;
  int i,k,j;
  //printf("'%s'\n",s.toLatin1().data());
  if (s.length()==0) return r;
  i=s. lastIndexOf(")",-1);
  k=i;
  j=k;
  do {
  k=s. lastIndexOf("(",k-1);
  j=s. lastIndexOf(")",j-1);
  }
  while (j>k);
  if (k>0) {
  	QString vor,nach;
	vor=s.left(k-1)+" ";
	nach=s.mid(i+1);
  	if (vor.trimmed()=="") vor=" ";
	if (int(i+2)>=s.length()) nach=" ";
  	//printf("()%s---%s---%s---\n",vor.latin1(),s.mid(k+1,i-k-1).latin1(),nach.latin1());
	//return r;
  	return calculate(vor+addTmpKeyword(keyword,calculate(s.mid(k+1,i-k-1),keyword))+nach,keyword);
  }
  i=s.indexOf("&&",0);
  if (i>0) return (calculate(s.left(i),keyword)&&calculate(s.mid(i+2),keyword));
  i=s.indexOf("||",0);
  if (i>0) return (calculate(s.left(i),keyword)||calculate(s.mid(i+2),keyword));
  i=s.indexOf("==",0);
  if (i>0) return (calculate(s.left(i),keyword)==calculate(s.mid(i+2),keyword));
  i=s.indexOf("!=",0);
  if (i>0) return (calculate(s.left(i),keyword)!=calculate(s.mid(i+2),keyword));
  i=s.indexOf(">=",0);
  if (i>0) return (calculate(s.left(i),keyword)>=calculate(s.mid(i+2),keyword));
  i=s.indexOf("<=",0);
  if (i>0) return (calculate(s.left(i),keyword)<=calculate(s.mid(i+2),keyword));
  i=s.indexOf(">",0);
  if (i>0) return (calculate(s.left(i),keyword)>calculate(s.mid(i+2),keyword));
  i=s.indexOf("<",0);
  if (i>0) return (calculate(s.left(i),keyword)<calculate(s.mid(i+2),keyword));
  i=s.indexOf("+",0);
  if (i>0) return  calculate(s.left(i),keyword)+calculate(s.mid(i+1),keyword);
  i=s.lastIndexOf("-",-1);
  if (i>0) { 
	//printf("- %d\n",i);
  	if (s.left(i).trimmed()=="") {
		returnValue r3;
		r3.setInt(-1);
		return calculate(s.mid(i+1),keyword)*r3;
		}
  	else return calculate(s.left(i),keyword)-calculate(s.mid(i+1),keyword);
	}
  i=s.indexOf("*",0);
  if (i>0) {
  	if (s.left(i).trimmed()=="") {
		return calculate(s.mid(i+1),keyword).convertToVar();}
  	else return calculate(s.left(i),keyword)*calculate(s.mid(i+1),keyword);
	}
  i=s.lastIndexOf("/");
  if (i>0) return calculate(s.left(i),keyword)/calculate(s.mid(i+1),keyword);
  i=s.indexOf("%",0);
  if (i>0) return  calculate(s.left(i),keyword)%calculate(s.mid(i+1),keyword);
  i=s.indexOf("!",0);
  if (i>0) return !calculate(s.mid(i+1),keyword);
  i=s.indexOf("&",0);
  if (i>0) {
  	if (s.left(i).trimmed()=="") {
		keywords *help=*keyword;
  		bool found=false;
		QString s1=s.mid(i+1);
  		while ((help!=NULL)&&(found==false)){
   		if (help->keyword==s1.trimmed()) found=true;
  		else help=help->next;
  		}
  		if ((found)&&((help->type==var)||(help->type==intClass))) {
 		 	return (*(help->r)).convertToPtr();
 		 }
		else throw 2;
		}
  	else throw 2;
	}
  keywords *help=*keyword;
  bool found=false;
  while ((help!=NULL)&&(found==false)){
   if (help->keyword==s.trimmed()) found=true;
  else help=help->next;
  }
  if ((found)&&((help->type==var)||(help->type==intClass))) {
  	return (*(help->r));
  }
  //printf("%d,%d\n",r.getInt(),help->r->getInt());
  //if (r.type==varInt) printf("varint\n");
  //if (r.type==ptrInt) printf("ptrint\n");
  //printf("r%d--%d\n",r.getInt(),r.data);
  //printf("calculate2(%d,%s)\n",r.getInt(),r.getString().latin1());
  return r;
}

QString macro::addTmpKeyword(keywords **keyword_,returnValue r){
  tmpVarCounter++;
  QString s;
  (*keyword_)= new keywords(*keyword_);
  (*keyword_)->r=new returnValue(r);
  (*keyword_)->keyword="tmpVar"+s.setNum(tmpVarCounter);
  (*keyword_)->r->setClassHandler((*keyword_));
  return "tmpVar"+s.setNum(tmpVarCounter);
}

void macro::cleanKeywords(keywords **keywordLocal,keywords *keyword_){
    	keywords *help;
 	 while (*keywordLocal!=keyword_){
   		help=*keywordLocal;
   		(*keywordLocal) = help->next;
   		delete help;
  	 }
   }
void macro::generalTypeProcessing(int *counter,keywords **keyword_,varType ptrtype,varType t,bool single){
  parserValue p;
  varType typeVar;
  bool ende=false;
  QString s;
  (*keyword_)= new keywords(*keyword_);
  (*keyword_)->r=new returnValue;
  
 do {
  p=next(counter);
  if ((p.type==op)&&(p.value=="*")){typeVar=ptrtype;p=next(counter);}
  else {typeVar=t;}
  if (p.type==keyword) {(*keyword_)->keyword=p.value;}
  else throw 8;
  int last= *counter;
  p=next(counter);
  if (p.type==parenOpen) {
  	(*keyword_)->type=func;
	(*keyword_)->r->setType(typeVar);
	ende=true;
	(*keyword_)->parameter =(*counter);
	do {p=next(counter);}
	while (p.type!=parenClose);
	p=next(counter);
	if (p.type==braceOpen){
		(*keyword_)->counter =(*counter);
		closeBrace(counter);
		}
	else throw 2;
	}
  else {
	(*keyword_)->r->setType(typeVar);
	(*keyword_)->r->setClassHandler((*keyword_));
	if ((p.type==op)&&(p.value=="=")) {
		*((*keyword_)->r)<<calculate(counter,(*keyword_));
		last= *counter;
		p=next(counter);
		}
	if ((p.type==op)&&(p.value=="=-")) {
		returnValue r2;
  		r2.setDouble(0);
		*((*keyword_)->r)<<(r2-calculate(counter,(*keyword_)));
		last= *counter;
		p=next(counter);
		}
	if (single==true) {ende=true; *counter=last;}
	else if (p.type==semicolon) {ende=true;}
	else if (p.type==comma){
		(*keyword_)= new keywords(*keyword_);
  		(*keyword_)->r=new returnValue;
		}
	else throw 2;
  
  	}
  } while (ende==false);
}

returnValue macro::funcHandler (int *counter,int *funcCode,int *parameter, keywords *keyword_, varType typeVar){
  keywords *keywordLocal=keyword_;
  keywords *keywordFunc=globals;
  int para = *parameter;
  int func = *funcCode;
  QString s;
  parserValue parser;
  testParenOpen(counter);
  int help=(*counter);
  bool defaultParameter=checkParenClose(counter);
  if (defaultParameter) *counter=help;
  if (!checkParenClose(&para)) {
  	do {
  	parser=next(&para);
  	//printf("%s\n",parser.value.latin1());
  	if (parser.type==keyword) {
  		keywords *help=keywordLocal;
		bool found=false;
		int hCounter=*counter;
		bool noType = checkStaticClass(counter);
		*counter=hCounter;
		while ((help!=NULL)&&(found==false)){
		 if (help->keyword==parser.value) 
			if (noType && (help->type==type)) help=help->next;
			else found=true;
		 else help=help->next;
		}
		if (found) {
			if (type==help->type) {
				(this->*help->typeHandler)(&para,&keywordFunc,true);
				if (defaultParameter==false) {
					*(keywordFunc->r) << calculate(counter,keywordLocal);
					defaultParameter=(!(checkComma(counter)));
					}
				}
			else throw 26;
			} 
		else {  error->addItem("Unknown type "+parser.value,1,message(*counter));
		  		throw 0;}
			
		}
	else throw 2;}
  	while (checkComma(&para));
	testParenClose(&para);
	}
  testParenClose(counter);
  returnValue r;
  r.setInt(0);
  r.setType(typeVar);
  run(&func,&r,keywordFunc);
  cleanKeywords(&keywordFunc,globals);
  cleanKeywords(&keywordLocal,keyword_);
  returnState=false;
  return r;
}
void macro::run(int *counter,returnValue *r,keywords *keyword_,bool single,bool deleteKeywords){
  keywords *keywordLocal=keyword_;
  bool exit =false;
  bool convertToVar;
  returnState=false;
  parserValue parser;
  QString s;
  do {  //printf("counter->%d\n",(*counter));
  	convertToVar=false;
	parser=next(counter);
	switch (parser.type){
	case braceClose:
		exit=true;
		break;
	case braceOpen:
		run(counter,r,keywordLocal); 
		break;
	case semicolon:
		if (single==true) {exit=true;}
		break;
	case parenClose:
		if (single==true) {exit=true;}
		else {throw 2;}
		break;
	case op:
		if (parser.value=="*") {
			convertToVar=true;
			parser=next(counter);
			if (parser.type!=keyword) throw 2;
		}
	case keyword:{ 
		if ("return"==parser.value){
			exit=true;
			(*r) << calculate(counter,keywordLocal);
			returnState=true;
			}
		else if ("for"==parser.value){
			keywords *keywordFor=keywordLocal;
			testParenOpen(counter);
			run(counter,r,keywordFor,true,false);
			int condition,actor,command;
			condition= *counter;
			returnValue c;
			c=calculate(counter,keywordFor);
			testSemicolon(counter);
			actor=*counter;
			closeParen(counter);
			command= *counter;
			nextCommand(counter);
			while ((c.getBool()==true)&&(returnState==false)) { 
			 	int helpCounter;
				helpCounter=command;
				run(&helpCounter,r,keywordFor,true);
				helpCounter=actor;
				if (returnState==false) run(&helpCounter,r,keywordFor,true);
				helpCounter=condition;
				if (returnState==false) c=calculate(&helpCounter,keywordFor);
				};
			cleanKeywords(&keywordFor,keywordLocal);
			}
		else if ("if"==parser.value){
			testParenOpen(counter);
			returnValue c;
			c=calculate(counter,keywordLocal);
			testParenClose(counter);
			if ((c.getBool()==true)) 
				run(counter,r,keywordLocal,true);
			else nextCommand(counter);
			bool endIf=false;
			int help=*counter;
			while (!endIf){
			  help=*counter;
			  parser=next(counter);
			  if ((parser.type==keyword)&&("else"==parser.value)){
				if ((c.getBool()==true)) nextCommand(counter);
				else run(counter,r,keywordLocal,true);
				}
			  else endIf=true;
			}
			(*counter)=help;
			}
		else if ("while"==parser.value){
			int condition,command;
			testParenOpen(counter);
			condition= *counter;
			returnValue c;
			c=calculate(counter,keywordLocal);
			testParenClose(counter);
			command= *counter;
			nextCommand(counter);
			while ((c.getBool()==true)&&(returnState==false)) { 
			 	int helpCounter;
				helpCounter=command;
				run(&helpCounter,r,keywordLocal,true);
				helpCounter=condition;
				c=calculate(&helpCounter,keywordLocal);
				};
			}
		else if ("do"==parser.value){
			int condition,command;
			command= *counter;
			nextCommand(counter);
			parser=next(counter);
			if ((parser.type==keyword)&&("while"==parser.value)){
				testParenOpen(counter);
				condition= *counter;
				returnValue c;
				closeParen(counter);
				testSemicolon(counter);
				do {
				 	int helpCounter;
					helpCounter=command;
					run(&helpCounter,r,keywordLocal,true);
					helpCounter=condition;
					c=calculate(&helpCounter,keywordLocal);
				}
				while ((c.getBool()==true)&&(returnState==false));
				}
			else throw 3;
			}
		else{
		  keywords *help=keywordLocal;
		  bool found=false;
		  int hCounter=*counter;
		  bool noType = checkStaticClass(counter);
		  *counter=hCounter;
		  while ((help!=NULL)&&(found==false)){
		   if (help->keyword==parser.value) 
			if (noType && (help->type==type)) help=help->next;
			else found=true;
		   else help=help->next;
		  }
		  if (found) {
			if (help->type==type) {
				(this->*help->typeHandler)(counter,&keywordLocal,false);
				}
			if (help->type==intClass) {
				if (convertToVar) {
					returnValue r1=help->r->convertToVar();
					returnValue r;
					convertToVar=false;
					r=(this->*help->classHandler)(counter,keywordLocal,&r1,true);
					}
				else {
					returnValue r;
					r=(this->*help->classHandler)(counter,keywordLocal,(help->r),true);
					}
				}
			if (help->type==var) {
				if (convertToVar) {
					returnValue r=help->r->convertToVar();
					convertToVar=false;
					compute(&r,counter,keywordLocal);
					}
				else compute(help->r,counter,keywordLocal);
				}
			if (help->type==func) {
				returnValue r;
				r=funcHandler(counter,&help->counter,&help->parameter,keywordLocal,help->r->type);
				testSemicolon(counter);
				}
		  }
		  else {
			error->addItem("Unknown identifier "+parser.value,1,message(*counter));
		  	throw 0;}
		  }
		if (convertToVar) throw 2;
		}
		break;
	default:
		throw 2;
	}
   	if (single==true) exit=true;
	
  } while ((exit==false)&&(returnState==false));
 if (deleteKeywords==true) cleanKeywords(&keywordLocal,keyword_);
}

void macro::testParenOpen(int *counter){
 QString s;
 parserValue p;
 p=next(counter);
 if ((p.type==parenOpen)){return;}
 throw 9;
}

void macro::testParenClose(int *counter){
 parserValue p;
 QString s;
 p=next(counter);
 if ((p.type==parenClose)){return;}
 throw 10;
}
void macro::testBracketOpen(int *counter){
 QString s;
 parserValue p;
 p=next(counter);
//printf("[%d\n",*counter);
 if ((p.type==bracketOpen)){return;}
 throw 11;
}

void macro::testBracketClose(int *counter){
 parserValue p;
 QString s;
 p=next(counter);
//printf("]%d\n",*counter);
 if ((p.type==bracketClose)){return;}
 throw 12;
}

void macro::testDot(int *counter){
 parserValue p;
 QString s;
 p=next(counter);
//printf(".%d\n",*counter);
 if ((p.type==number)&&(p.value==".")){return;}
 throw 13;
}

void macro::testClassPointer(int *counter){
 parserValue p;
 QString s;
 p=next(counter);
 if ((p.type==op)&&(p.value=="->")){return;}
 throw 14;
}
void macro::testSemicolon(int *counter){
 parserValue p;
 QString s;
 p=next(counter);
 if ((p.type==semicolon)){return;}
 throw 15;
}
void macro::testComma(int *counter){
 parserValue p;
 QString s;
 p=next(counter);
 if ((p.type==comma)){return;}
 throw 16;
}

void macro::nextCommand(int *counter){
  parserValue p;
  int level=0;
  QString s;
  bool found=false;
  do {
   	p=next(counter);
   	if (p.type==braceOpen) level++;
   	else if (p.type==braceClose) level--;
   	if ((level==0)&&(p.type==braceClose)) found=true;
   	if ((level==0)&&(p.type==semicolon)) found=true;
  }while (found==false);
}

bool macro::checkClassPointer(int *counter){
 parserValue p;
 int help=(*counter);
 p=next(counter);
 if ((p.type==op)&&(p.value=="->")){return true;}
 (*counter)=help;
 return false;
}

bool macro::checkDot(int *counter){
 parserValue p;
 int help=(*counter);
 p=next(counter);
 if ((p.type==number)&&(p.value==".")){return true;}
 (*counter)=help;
 return false;
}

bool macro::checkComma(int *counter){
 parserValue p;
 int help=(*counter);
 p=next(counter);
 if (p.type==comma){return true;}
 (*counter)=help;
 return false;
}

bool macro::checkStaticClass(int *counter){
 parserValue p;
 int help=(*counter);
 p=next(counter);
 if ((p.type==op)&&(p.value=="::")){return true;}
 (*counter)=help;
 return false;
}

bool macro::checkParenOpen(int *counter){
 parserValue p;
 int help=(*counter);
 p=next(counter);
 if ((p.type==parenOpen)){return true;}
 (*counter)=help;
 return false;
}
bool macro::checkParenClose(int *counter){
 parserValue p;
 int help=(*counter);
 p=next(counter);
 if ((p.type==parenClose)){return true;}
 (*counter)=help;
 return false;
}

bool macro::checkBracketOpen(int *counter){
 parserValue p;
 int help=(*counter);
 p=next(counter);
 if ((p.type==bracketOpen)){return true;}
 (*counter)=help;
 return false;
}
bool macro::checkBracketClose(int *counter){
 parserValue p;
 int help=(*counter);
 p=next(counter);
 if ((p.type==bracketClose)){return true;}
 (*counter)=help;
 return false;
}

bool macro::checkSemicolon(int *counter){
 parserValue p;
 int help=(*counter);
 p=next(counter);
 if ((p.type==semicolon)){return true;}
 (*counter)=help;
 return false;
}
