/*****
*
*	Michael Riff
*	Object software version 1.0  Okto 2013.
*
*	Diese Datei enthält die Funktionnen die das Durchlesen der Berechnugen der Eingabe erfüllen :
*	Eine Prozedur die den gesammten control Struktur einliest. Dazu ruft diese weitere
*	Routinen die eine arithmetischen Ausdruck einliest, oder einen Test.
*
*	Version 1.2 : 08 Feb 2014
*	Use decimal separator from UX_StdLib.c when USE_ITL is defined in ParseOperand.
*
*	Version 1.4:  2 Sept 2014
*	Bug: Null terminate TextBuffer in ParseComparison to suppress values from uninitialisation.
*
*	Version 1.6: 06 June 2016
*	Implemented handling of additional routines that can be called out of the text code. As example
*	we used the following: print(<variable name>) and print("constant string") that print out
*	the value of a variable or a string.
*	Adaptations to compile the code with CodeWarrior and suppress warnings.
*
*	Version 1.7: 23 July 2016
*	ParseComparison and ParseOperand:
*	NULL termination of TextBuffer only done when necessary. Incrementation of counter suppressed when NULL
*	terminating, so that the counter gives the length of the string now also used for identification.
*	String buffer TextBuffer and counter put global instead of local in several routines.
*
*	Reworked string identification in ParseOperand and ParseComparison to also check missing string length
*	that could lead to wrong function call or comparison oprator call.
*****/

#include <math.h>

#include "Parser.h"
//#include "OperandClasses.h"

#define BUFFER_SIZE 10


#ifdef MAC_UI

#include "UX_StdDefs.h"
#define bool Boolean

#endif


#define SUPP_BLANC	while ((Entry[IndxEntry] == ' ') || Entry[IndxEntry] == '\n' || Entry[IndxEntry] == '\r' || Entry[IndxEntry] == '\t') { \
				if (Entry[IndxEntry] == '\n' || Entry[IndxEntry] == '\r') currLine++; \
				IndxEntry++; \
			}


/*
Copié des fichiers .h pour appeler Debugger sans inclure <Types.h>
*/
#ifdef DEBUG_SUPP
/*
	This file sets up the following compiler independent conditionals:
	CFMSYSTEMCALLS			- No A-traps.  Systems calls are made using CFM and UPP's
	There are some invariants among the conditionals:
	GENERATINGPOWERPC => CFMSYSTEMCALLS
	CFMSYSTEMCALLS => GENERATINGCFM
	PRAGMA_IMPORT_SUPPORTED => CFMSYSTEMCALLS
*/

/*

	Set up GENERATINGCFM and  CFMSYSTEMCALLS

*/
#if GENERATINGPOWERPC || defined(__CFM68K__)
#define GENERATINGCFM 1
#define CFMSYSTEMCALLS 1
#else
#define GENERATINGCFM 0
#define CFMSYSTEMCALLS 0
#endif


//#ifndef __CONDITIONALMACROS__
//#include <ConditionalMacros.h>
//#endif

#if CFMSYSTEMCALLS
#define ONEWORDINLINE(trapNum)
#else
#define ONEWORDINLINE(trapNum) = trapNum
#endif

extern pascal void Debugger(void)
 ONEWORDINLINE(0xA9FF);
#endif


extern Grph_struct	*Graphs;

extern VarTableType	*VarTable;
extern int NumVars;


extern char	*Entry;
extern int 	IndxEntry;


/* Calculation of the line number */
extern int currLine;



extern Type_Erreur *Conversion;

#ifdef USE_ITL
/*
	Decimal separator read from itl0 or itl4 resource in UX_StdLib.c
*/
extern char decSeparat;
#endif

/*

		ARITHMETIC EXPRESSIONS

Function prototypes: in order of expression inclusion
*/
GeneralOperand *ParseArithmetic();
GeneralOperand *ParseAddSub(GeneralOperand *leftOperand);
GeneralOperand *ParseMultDiv();
GeneralOperand *ParsePow();
GeneralOperand *ParseOperand();

/*

		BOOLEAN EXPRESSIONS

Function prototypes: in order of expression inclusion
*/
GeneralBoolOperand *ParseBool(bool *stoppedOnParenth);
GeneralBoolOperand	*ParseAnds(bool *stoppedOnParenth);
GeneralBoolOperand *ParseComparison(bool *stoppedOnParenth);


/* Temporary buffer to identify strings or to convert to numeric value */
char TextBuffer[BUFFER_SIZE];
int indxBuffer = 0;

/*******************************************

		ARITHMETIC EXPRESSIONS

********************************************/
/*
Parsing routines
Structure build up:
Arithmetic expressions are a suite of control flow structures, in each branch of which
we find an arithmetic expression.

Preconditions:
IndxEntry must indicate the starting  character of the control block, or
the starting { of the arithmetic control bloc.

After the call:
IndxEntry points to the  character after the ending character of a control structure
branch that is the or the ending  ) or } of the whole structure if it read in a control
structure as if else, for, while or do-while.
Otherwhise, if it read in an arithmetic expression ("code line") ended by a ;, it points
to the next character after this ;.
*/
GeneralOperand *ParseArithmetic() {
	GeneralOperand	*tmpOperand;
	OperatorIf	*tmpIf;
	OperatorFor	*tmpFor;
	OperatorWhile	*tmpWhile;
	OperatorDo	*tmpDo;
	bool dummy;

	// Suppress eventual blancs
	SUPP_BLANC
	tmpOperand = NULL;
	tmpIf = NULL;
	tmpFor = NULL;
	tmpFor = NULL;
	tmpWhile = NULL;
	tmpDo = NULL;

#ifdef ADD_FUNCT
	int varPos;
#endif

	// The complete entry is a suite of control flow blocks for or while or do-while (!!! For a succression of control blocs we have to handle arrays of GeneralOperand)
	while (!strncmp("if",Entry+IndxEntry,2) || !strncmp("for",Entry+IndxEntry,3) 
		|| !strncmp("while",Entry+IndxEntry,5) || !strncmp("do",Entry+IndxEntry,2) || Entry[IndxEntry]== '{') { 
		// First check for if for or while control block

		if (!strncmp("if",Entry+IndxEntry,2)) {
#ifdef DEBUG
			printf("If control block\n");
#endif
			IndxEntry +=2; // jump over if
			// Control flow bloc is made of a boolean expression, an if arithmetic expression,
			// and an optional else arithmeric expression
			SUPP_BLANC

			// Jump over starting ( here, to prevent unecesssary call at beginning of ParseBool)
			IndxEntry++;
			
			tmpIf = new OperatorIf(ParseBool(&dummy));
			
			// IndxEntry must point to the ending ) of the if test
			if (Entry[IndxEntry] != ')') {
				printf("%d Pb at %s, ending ) not found\n", (Graphs + numGraphs)->GraphicID, Entry+IndxEntry-5);
				return new ErrorOperand();
			}
			IndxEntry++; SUPP_BLANC
			// Jump over the {
			if (Entry[IndxEntry] != '{') 
				printf("%d No {} enclosing if branch\n", (Graphs + numGraphs)->GraphicID);
			else
				IndxEntry++;

//			tmpIf->SetIf(ParseArithmetic());
while (Entry[IndxEntry] != '}') {
	tmpIf->SetIf(ParseArithmetic());
	// Routine jumped over ; character. Only stops on ending }
	SUPP_BLANC
}

			// IndxEntry must point to the ending } of the arithmetic expression
			if (Entry[IndxEntry] != '}') {
				printf("%d Pb at %s, ending } not found\n", (Graphs + numGraphs)->GraphicID, Entry+IndxEntry-5);
				return new ErrorOperand();
			}
			IndxEntry++; SUPP_BLANC

			// Check for optional else branch
			if (!strncmp("else",Entry+IndxEntry,4)) {	
#ifdef DEBUG
				printf("Else control block\n");
#endif
				IndxEntry +=4; // jump over if
				// Control bloc is made of a { and an arithmetic expression followd by a }
				SUPP_BLANC
				// Jump over the {
				if (Entry[IndxEntry] != '{') 
					printf("%d No {} enclosing if branch\n", (Graphs + numGraphs)->GraphicID);
				else
					IndxEntry++;

//				tmpIf->SetElse(ParseArithmetic());
while (Entry[IndxEntry] != '}') {
	tmpIf->SetElse(ParseArithmetic());
	// Routine jumped over ; character. Only stops on ending }
	SUPP_BLANC
}

				if (Entry[IndxEntry] != '}') {
					printf("%d Pb at %s, ending } not found\n", (Graphs + numGraphs)->GraphicID, Entry+IndxEntry-5);
					return new ErrorOperand();
				}
				IndxEntry++;
			}
			return tmpIf;


		} else if (!strncmp("for",Entry+IndxEntry,3)) {
#ifdef DEBUG
			printf("For control block\n");
#endif
			IndxEntry +=3; // jump over if
			// Control flow bloc is made of a boolean expression, an if arithmetic expression,
			// and an optional else arithmeric expression
			SUPP_BLANC
			// Jump over starting ( here
			IndxEntry++;
			SUPP_BLANC
			// Parse starting assignment of loop (if present
			if (Entry[IndxEntry] != ';') {
				tmpFor = new OperatorFor(ParseOperand());
			} else {
				// No start command to be run
				tmpFor = new OperatorFor(NULL);
			}
			// Jump over ;
			IndxEntry++;
			tmpFor->SetCondition(ParseBool(&dummy));

			// Jump over ;
			IndxEntry++;
			tmpFor->SetIncrement(ParseAddSub(ParseMultDiv()));
			// We should have closing ) and go until next {
			if (Entry[IndxEntry] != ')') {
				printf("%d Pb no closing ) in for structure", (Graphs + numGraphs)->GraphicID);
			} else {
				// Jump over closing ) of for instruction
				IndxEntry++;
			}
#ifdef DEBUG
printf("\n");
#endif
			// Go to opening { and and jump over it
			SUPP_BLANC
			IndxEntry++;

//			tmpFor->SetLoop(ParseArithmetic());
while (Entry[IndxEntry] != '}') {
	tmpFor->SetLoop(ParseArithmetic());
	// Routine jumped over ; character. Only stops on ending }
	SUPP_BLANC
}

if (Entry[IndxEntry] != '}') {
	printf("%d Pb at %s, ending } not found\n", (Graphs + numGraphs)->GraphicID, Entry+IndxEntry-5);
	return new ErrorOperand();
}
IndxEntry++;

			// Here IndxEntry points on the charater following the closing }
			return tmpFor;


		} else if (!strncmp("while",Entry+IndxEntry,5)) {
#ifdef DEBUG
			printf("While control block\n");
#endif
			IndxEntry += 5;
			SUPP_BLANC

			// Jump over starting ( here, to prevent unecesssary call at beginning of ParseBool)
			IndxEntry++;

			tmpWhile = new OperatorWhile(ParseBool(&dummy));
			// IndxEntry must point to the ending ) of the if test
			if (Entry[IndxEntry] != ')') {
				printf("%d Pb at %s, ending ) not found\n", (Graphs + numGraphs)->GraphicID, Entry+IndxEntry-5);
				return new ErrorOperand();
			}
			// Go to opening { and and stay on it
			IndxEntry++; SUPP_BLANC


//			tmpWhile->SetLoop(ParseArithmetic());
while (Entry[IndxEntry] != '}') {
	tmpWhile->SetLoop(ParseArithmetic());
	// Routine jumped over ; character. Only stops on ending }
	SUPP_BLANC
}

if (Entry[IndxEntry] != '}') {
	printf("%d Pb at %s, ending } not found\n", (Graphs + numGraphs)->GraphicID, Entry+IndxEntry-5);
	return new ErrorOperand();
}
IndxEntry++;

			// Here IndxEntry points on the charater following the closing }
			return tmpWhile;


		} else if (!strncmp("do",Entry+IndxEntry,2)) {
#ifdef DEBUG
			printf("Do while control block\n");
#endif
			IndxEntry += 2;
			tmpDo = new OperatorDo();

//			tmpDo->SetLoop(ParseArithmetic());
while (Entry[IndxEntry] != '}') {
	tmpDo->SetLoop(ParseArithmetic());
	// Routine jumped over ; character. Only stops on ending }
	SUPP_BLANC
}

			if (Entry[IndxEntry] != '}') {
				printf("%d Pb at %s, ending } not found\n", (Graphs + numGraphs)->GraphicID, Entry+IndxEntry-5);
				return new ErrorOperand();
			}
			IndxEntry++; SUPP_BLANC

			if (strncmp("while",Entry+IndxEntry,5)) {
				// Pb while instruction not found
				printf("%d Do command without corresponding while\n", (Graphs + numGraphs)->GraphicID);
				return new ErrorOperand();
			}
			IndxEntry += 5;
			SUPP_BLANC
			// Jump over starting ( here, to prevent unecesssary call at beginning of ParseBool)
			IndxEntry++;

			tmpDo->SetCondition(ParseBool(&dummy));
			// IndxEntry must point to the ending ) of the if test
			if (Entry[IndxEntry] != ')') {
				printf("%d Pb at %s, ending ) not found\n", (Graphs + numGraphs)->GraphicID, Entry+IndxEntry-5);
				return new ErrorOperand();
			}
			IndxEntry++;
			SUPP_BLANC

// IndxEntry points now on the ; character finishing the do while(); control structure. Jump over it
if (Entry[IndxEntry] != ';') {
			printf("%d Missing ending ; after do while()\n", (Graphs + numGraphs)->GraphicID, Entry+IndxEntry-5);
} else {
		IndxEntry++;
}

			SUPP_BLANC

			// Here IndxEntry points on the charater following the closing )
			return tmpDo;


		} else {

			IndxEntry++;
			
			// Suppress eventual blancs
			SUPP_BLANC

// ToDo In case of a succession of control blocs or arithmetic expressions write the next entry into the array here
// in a while loop. Presently the loop is in the top parsing routine

			// Only on arithmetic expression to be parsed
			// Parse arithmetic expression
			tmpOperand = ParseArithmetic();

		}
		// Suppress eventual blancs
		SUPP_BLANC

	}

	// ToDo review if not better as else beanch of check for existant of control structure
	if (NULL == tmpOperand) {
		// Case of arithmetic expression outside any control structure

// ToDo In case of a succession of control blocs or arithmetic expressions write the next entry into the array here
// in a while loop. Presently the loop is in the top parsing routine

#ifdef ADD_FUNCT
/*
	Additional routines are positioned on the same level as control structures as if else / while ...
	or full arithmetic expression because they may only be used as single command:
		print(" ");
	and not be embedded in an expression
		sin(x) + printf(" ") - ...
	as they do not return a value.
	They are therefore parsed in the top level routine. Attention must be payed that the postcondition is:
	IndxEntry indicates the ';' or '}' so that the calling routine stack returns immediately.

	Additional potential check: nothing may have been parsed before :
	this does happen in this solution, as the.
*/

	/* First check for the special routines that may only be called as one single command:
		print();
	   and not within an arithmetic expression.
	*/
		SUPP_BLANC
		if (!strncmp("print",Entry+IndxEntry,5))
		{
			IndxEntry+=5;
			SUPP_BLANC
			if (Entry[IndxEntry]  != '(') {
				// Error
				return  new ErrorOperand();		// Global object may be used! Pb when cleanup
			}

			IndxEntry++;
			SUPP_BLANC
			if (Entry[IndxEntry]  == '"') {
				// Constant string:
				// Read out rest of string
				IndxEntry++;
				indxBuffer = 0;
				do {
					TextBuffer[indxBuffer++] = Entry[IndxEntry++];
				} while (indxBuffer<BUFFER_SIZE-1 && Entry[IndxEntry]  != '"');
				TextBuffer[indxBuffer] = '\0';


// Go to next ; or }
				IndxEntry++;
				SUPP_BLANC
				if(Entry[IndxEntry]  != ')') {
					printf("%d Print call not ended with a )\n", (Graphs + numGraphs)->GraphicID);
				}
				IndxEntry++;
				SUPP_BLANC

/*
	Stand: IndxEntry steht auf ; oder }

*/
				tmpOperand = new PrintMsgOperat(TextBuffer);

			} else {
				// After this we can only have an already defined variable
				indxBuffer = 0;
				do {
					TextBuffer[indxBuffer++] = Entry[IndxEntry++] ;
				} while (indxBuffer<BUFFER_SIZE-1 && (Entry[IndxEntry] >= 'a' && Entry[IndxEntry] <= 'z' || Entry[IndxEntry] >= 'A' && Entry[IndxEntry] <= 'Z' || Entry[IndxEntry] == '_' || Entry[IndxEntry] >= '0' && Entry[IndxEntry] <= '9'));
				TextBuffer[indxBuffer] = '\0';


				// Variable. Look for it in the variable table
				for (varPos=0; varPos<NumVars && 0!=strcmp(VarTable[varPos].VarName,TextBuffer);varPos++);
				if (varPos==NumVars) {
					printf("%d Error inc/dec of not initialised variable\n", (Graphs + numGraphs)->GraphicID);
					return new ErrorOperand();
				}

// Check if we have a ) ?
// Go to next ; or }
				IndxEntry++;
				SUPP_BLANC

/*
	Stand: IndxEntry steht auf ; oder }

*/
				tmpOperand = new PrintVarOperat(varPos);

			}

		} else {
#endif

		// Only on arithmetic expression to be parsed
		// Parse arithmetic expression
		tmpOperand = ParseAddSub(ParseMultDiv());

#ifdef ADD_FUNCT
		}
#endif

		// Here we have the postconditions of ParseOperand (calld by ParseMultDiv itself called by ParseAddSub)
		if (Entry[IndxEntry] == ';') {
			IndxEntry++;
			SUPP_BLANC
		} else {
			if ('\0' !=Entry[IndxEntry] && '}'!=Entry[IndxEntry]) {
				// Pb
				printf("%d Arithmeric code not ended with ; or }\n", (Graphs + numGraphs)->GraphicID);
				Debugger();
			}
		}
	}


	return tmpOperand;
	
}



/*
This routine parses an addition or substraction operation (or several consecutive ones).
For the operands it calls the parsing routine for multiplication or division operations.
That way, the precedence of those operations is assured.

Preconditions:
The left operand must have been read out (is passed in parameter)
IndexEntry must indicate first character of the operation.
In case of a recursive call (case of an arithmetic expression between brackets) as for
the first operation in the expression,  parseOperand
has been called before.

Postconditions
Same as ParseOperand for the right operand.

*/
GeneralOperand *ParseAddSub(GeneralOperand *leftOperand)
{
	BinaryOperat	*tmpOperator;

	tmpOperator = (BinaryOperat*)leftOperand;
	while (Entry[IndxEntry] == '+' || Entry[IndxEntry] == '-') {
		if (Entry[IndxEntry] == '+') {
#ifdef DEBUG
printf(" + ");
#endif
			tmpOperator = new BinaryOperat(bPlus,tmpOperator);
		} else if (Entry[IndxEntry] == '-') {
#ifdef DEBUG
printf(" - ");
#endif
			tmpOperator = new BinaryOperat(bMoins, tmpOperator);
		} else {
			printf("Non fitting char %c in ParseAddSub\n", Entry[IndxEntry]);
		}

		IndxEntry++;
		// Read in right operand
		tmpOperator->SetRight(ParseMultDiv());

		// Suppress blancs
		SUPP_BLANC
	}
	return tmpOperator;
}

/*
This routine parses a multiplication or division operation (or several consecutive ones).
For the operands it calls the parsing routine for operands (values or funtion call or arithmetic
expression between ()).

Preconditions:
The left operand must not have been read out.
IndexEntry must indicate the first character of the left operand or a preceeding
blanc character.

Postconditions
Same as ParseOperand for the right operand.

*/
GeneralOperand *ParseMultDiv()
{
	BinaryOperat	*tmpOperator;

	tmpOperator = (BinaryOperat*)ParsePow();
	while (Entry[IndxEntry] == '*' || Entry[IndxEntry] == '/') {
		if (Entry[IndxEntry] == '*') {
#ifdef DEBUG
printf(" * ");
#endif
			tmpOperator = new BinaryOperat(bMult, tmpOperator);
		} else if (Entry[IndxEntry] == '/') {
#ifdef DEBUG
printf(" / ");
#endif
			tmpOperator = new BinaryOperat(bDiv,tmpOperator);
		} else {
			// Generally we will have a + or - operation
			printf("Non fitting char %c in ParseMultDiv\n", Entry[IndxEntry]);
			return tmpOperator;
		}

		IndxEntry++;
		// Read in right operand
		tmpOperator->SetRight(ParsePow());

		// Suppress blancs
		SUPP_BLANC
	}
	return tmpOperator;
}



/*
This routine parses a power raise operation (or several consecutive ones).
For the operands it calls the parsing routine for operands (values or function call or arithmetic
expression between ()).

Preconditions:
The left operand must not have been read out
IndexEntry must indicate the first character of the left operand or a preceeding
blanc character.

Postconditions
Same as ParseOperand for the right operand.

*/
GeneralOperand *ParsePow() {

	BinaryOperat	*tmpOperator;

	tmpOperator = (BinaryOperat*)ParseOperand();
	while (Entry[IndxEntry] == '^') {
#ifdef DEBUG
printf(" ^ ");
#endif
		tmpOperator = new BinaryOperat(bPow, tmpOperator);

		IndxEntry++;
		// Read in right operand
		tmpOperator->SetRight(ParseOperand());

		// Suppress blancs
		SUPP_BLANC
	}
	return tmpOperator;

}

/*
This routine parses an operand either in for of a constant float values, or a function call
or a variable, with the optional unary preceding sign, or the incrementation/decrementation
operator -- ++.

Preconditions:
IndexEntry must indicate the first character of the operand or a blanc preceeding the operand.

After the call:
IndxEntry indicates the next character != ' ' after the operand. A closing ) is part of the operand in
case of a function call or an arithmetic expression between ().
*/
GeneralOperand *ParseOperand() {
	GeneralOperand	*aktArg = NULL;
	OperatorIncDec	*forOperat = NULL;
	bool	chgSign = false;

#ifdef OPERAT_EQ
/* Implémentation des opérateurs += -= *= /= */
	BinaryOperat	*tmpOperator = NULL;
#endif

/*

	double ValErr;	* To handle errors when reading in code *

	Conversion = (Type_Erreur*)(&ValErr);
	Conversion->Brut[0] = 0x7FF00000;
	Conversion->Brut[1] = 0x00000001;

*/

	SUPP_BLANC
	indxBuffer = 0;

#ifdef MIT_FOROP
	/*
		First check for pre-inc/decrementation operator
	*/
	if(!strncmp(Entry+IndxEntry, "++",2)) {
		int varPos;

		forOperat = new OperatorIncDec(-1, 1);
		IndxEntry +=2;
		// After this we can only have an already defined variable
		do {
			TextBuffer[indxBuffer++] = Entry[IndxEntry++] ;
		} while (Entry[IndxEntry]  >= 'a' && Entry[IndxEntry]  <= 'z' || Entry[IndxEntry]  >= 'A' && Entry[IndxEntry]  <= 'Z' || Entry[IndxEntry]  == '_' || Entry[IndxEntry]  >= '0' && Entry[IndxEntry]  <= '9');
		TextBuffer[indxBuffer] = '\0';
#ifdef DEBUG
printf("Pre inc for %s\n", TextBuffer);
#endif
		// Suppress blancs
		SUPP_BLANC

		// Variable. Look for it in the variable table
		for (varPos=0; varPos<NumVars && 0!=strcmp(VarTable[varPos].VarName,TextBuffer);varPos++);
		if (varPos==NumVars) {
			printf("Error inc/dec of not initialised variable\n");
			return new ErrorOperand();
		}
		forOperat->SetPosition(varPos);
		return forOperat;
	}
	if(!strncmp(Entry+IndxEntry, "--",2)) {
		int varPos;

		forOperat = new OperatorIncDec(-1, -1);
		IndxEntry +=2;
		// After this we can only have an already defined variable
		do {
			TextBuffer[indxBuffer++] = Entry[IndxEntry++] ;
		} while (Entry[IndxEntry]  >= 'a' && Entry[IndxEntry]  <= 'z' || Entry[IndxEntry]  >= 'A' && Entry[IndxEntry]  <= 'Z' || Entry[IndxEntry]  == '_' || Entry[IndxEntry]  >= '0' && Entry[IndxEntry]  <= '9');
		TextBuffer[indxBuffer] = '\0';
#ifdef DEBUG
printf("Pre dec for %s\n", TextBuffer);
#endif
		// Suppress blancs
		SUPP_BLANC

		// Variable. Look for it in the variable table
		for (varPos=0; varPos<NumVars && 0!=strcmp(VarTable[varPos].VarName,TextBuffer);varPos++);
		if (varPos==NumVars) {
			printf("Error inc/dec of not initialised variable\n");
			return new ErrorOperand();
		}
		forOperat->SetPosition(varPos);
		return forOperat;
	}
#endif

	/*
		Check for leading unary sign
	*/
	if (Entry[IndxEntry] == '+') {
		// Nothing to do just drop it
		IndxEntry++;
SUPP_BLANC
/*		// Check if no illegal blancs are there
		if (Entry[IndxEntry]  == ' ')
		{
			Entry[IndxEntry+10] = '\0';
			printf("Error, illegal blanc in expression %s\n", Entry+IndxEntry-3);
			return new ErrorOperand();
		}
*/
/* Problem
if operator for is not compiled in. readinf ++ will leave aktArg = NULL and
this routine will return taht value. Execution or display of code will cause the SW to crash.
*/
	}

	if (Entry[IndxEntry]  == '-') {
#ifdef DEBUG
printf(" -");
#endif
		chgSign = true;
		IndxEntry++;
SUPP_BLANC
/*		// Check if no illegal blancs are there
		if (Entry[IndxEntry]  == ' ')
		{
			Entry[IndxEntry+10] = '\0';
			printf("Error, illegal blanc in expression %s\n", Entry+IndxEntry-3);
			return new ErrorOperand();
		}
*/
/* Problem
if operator for is not compiled in. readinf -- will leave aktArg = NULL and
this routine will return that value. Execution or display of code will cause the SW to crash.
*/
	}

//	SUPP_BLANC

	if (Entry[IndxEntry]  >= 'a' && Entry[IndxEntry]  <= 'z' || Entry[IndxEntry]  >= 'A' && Entry[IndxEntry]  <= 'Z' || Entry[IndxEntry]  == '_') {
		// Function name or variable name (variable would be uninitialised !!!)
		// Read out rest of string
		do {
			TextBuffer[indxBuffer++] = Entry[IndxEntry++] ;
		} while (Entry[IndxEntry]  >= 'a' && Entry[IndxEntry]  <= 'z' || Entry[IndxEntry]  >= 'A' && Entry[IndxEntry]  <= 'Z' || Entry[IndxEntry]  == '_' || Entry[IndxEntry]  >= '0' && Entry[IndxEntry]  <= '9');

/*
	State: IndxEntry points to the character next to the string read in.
*/

#ifdef DEBUG
// Null terminate to suppress values from memory
TextBuffer[indxBuffer] = '\0';
printf("%s ", TextBuffer);
#endif

		// Suppress blancs
		SUPP_BLANC

		/*
			First check for input parameter
		*/
		if(!strncmp(TextBuffer, "p_",2)) {
				int param_idx;

				// NULL termination needed here
				TextBuffer[indxBuffer] = '\0';
				param_idx = atoi(TextBuffer+2);
				
				if (param_idx<0 || param_idx>MAX_PARAM) {
					printf("Illegal parameter index p_%d\n", param_idx);
					// Generate code that return a NAN value
					return new ErrorOperand();
				} else {
#ifdef DEBUG
printf(" P_%d ", param_idx);
#endif
					/* Auslesen der Globalen variable speichern */
					aktArg = new ParamOperand(param_idx);
					// Add eventual sign change
					if (chgSign) {
//						aktArg = new UnaryOperat(-, aktArg);
						aktArg = new UnaryOperat(uMoins, aktArg);
					}
					return aktArg;
				}
		}

		if (Entry[IndxEntry]  == '(') {
#ifdef DEBUG
printf("%s(", TextBuffer);
#endif
			// Function call or for while loop
			IndxEntry++;
			SUPP_BLANC

			switch(indxBuffer) {
				case 4:
				if (0 == strncmp("sqrt",TextBuffer,4)) {
					// Per recursive call read out expression in the ()
					aktArg = new FunctOperat(sqrt, ParseAddSub(ParseMultDiv()));

				} else if (0 == strncmp("sinh",TextBuffer,4)) {
					aktArg = new FunctOperat(sinh, ParseAddSub(ParseMultDiv()));
				} else if (0 == strncmp("cosh",TextBuffer,4)) {
					aktArg = new FunctOperat(cosh, ParseAddSub(ParseMultDiv()));
				} else if (0 == strncmp("tanh",TextBuffer,4)) {
					aktArg = new FunctOperat(tanh, ParseAddSub(ParseMultDiv()));

				} else if (0 == strncmp("asin",TextBuffer,4)) {
					aktArg = new FunctOperat(asin, ParseAddSub(ParseMultDiv()));
				} else if (0 == strncmp("acos",TextBuffer,4)) {
					aktArg = new FunctOperat(acos, ParseAddSub(ParseMultDiv()));
				} else if (0 == strncmp("atan",TextBuffer,4)) {
					aktArg = new FunctOperat(atan, ParseAddSub(ParseMultDiv()));

				} else {
					printf("%d Error unimplemented function %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
				}
				break;

				case 3:
				if (0 == strncmp("exp",TextBuffer,3)) {
					aktArg = new FunctOperat(exp, ParseAddSub(ParseMultDiv()));
				} else if (0 == strncmp("sin",TextBuffer,3)) {
					aktArg = new FunctOperat(sin, ParseAddSub(ParseMultDiv()));
				} else if (0 == strncmp("cos",TextBuffer,3)) {
					aktArg = new FunctOperat(cos, ParseAddSub(ParseMultDiv()));
				} else if (0 == strncmp("tan",TextBuffer,3)) {
					aktArg = new FunctOperat(tan, ParseAddSub(ParseMultDiv()));

				} else {
					printf("%d Error unimplemented function %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
				}
				break;

				case 2:
				if (0 == strncmp("ln",TextBuffer,2)) {
					aktArg = new FunctOperat(log, ParseAddSub(ParseMultDiv()));

				} else {
					printf("%d Error unimplemented function %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
				}
				break;

				default:
				printf("%d Error unimplemented function %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
			}

			if (Entry[IndxEntry] == ')') {
#ifdef DEBUG
printf(")\n");
#endif
				IndxEntry++;
				SUPP_BLANC
			} else {
				// Pb
				printf("Error corresponding ) not found %s\n", Entry+IndxEntry-4);
			}
		} else {
			int varPos;

			// NULL termination needed in this case
			TextBuffer[indxBuffer] = '\0';
#ifdef DEBUG
printf("%s ", TextBuffer);
#endif
			// Variable. Look for it in the variable table
			for (varPos=0; varPos<NumVars && 0!=strcmp(VarTable[varPos].VarName,TextBuffer);varPos++);
			if (varPos==NumVars) {
				// Variable name not found in table. Check if we have a value assigned
				if (Entry[IndxEntry]  == '=') {
#ifdef DEBUG
printf("= ");
#endif
					// Generate new variable assignment object, and register new variable 
					aktArg = new VarAssign(NumVars++);
					strcpy(VarTable[varPos].VarName,TextBuffer);
					// Jump over the =
					IndxEntry++;
					// Parse the arithmetic expression and generate code for the value assignment to the variable
					SUPP_BLANC
					((VarAssign*)aktArg)->SetArithmetic(ParseAddSub(ParseMultDiv()));
				} else {
					// If not found then it has not been initialised
					printf("Error uninitialised variable %s\n",TextBuffer);
					return new ErrorOperand();
				}
			} else {

				// Variable already created. Check if its value is read or a new value is assigned
				SUPP_BLANC
				if (Entry[IndxEntry]  == '=') {
#ifdef DEBUG
printf("= ");
#endif
					// Generate new variable assignment object 
					aktArg = new VarAssign(varPos);
					// Jump over the =
					IndxEntry++;
					// Parse the arithmetic expression and generate code for the value assignment to the variable
					SUPP_BLANC
					((VarAssign*)aktArg)->SetArithmetic(ParseAddSub(ParseMultDiv()));

#ifdef OPERAT_EQ
/* Implémentation des opérateurs += -= *= /= */

				} else if ((Entry[IndxEntry] =='+' || Entry[IndxEntry] =='-' || Entry[IndxEntry] =='*' || Entry[IndxEntry] =='/') && Entry[IndxEntry+1]  == '=') {
#ifdef DEBUG
printf(" %c= ", Entry[IndxEntry]);
#endif
					// Generate operator with left operand being the variable
					switch(Entry[IndxEntry]) {
						case '+':
							tmpOperator = new BinaryOperat(bPlus, new VarOperand(varPos));
							break;
						case '-':
							tmpOperator = new BinaryOperat(bMoins, new VarOperand(varPos));
							break;
						case '*':
							tmpOperator = new BinaryOperat(bMult, new VarOperand(varPos));
							break;
						case '/':
							tmpOperator = new BinaryOperat(bDiv, new VarOperand(varPos));
							break;
						case '^':
							tmpOperator = new BinaryOperat(bPow, new VarOperand(varPos));
							break;
						}

					// Jump over <operat>=
					IndxEntry += 2;
					
					// Parser the right operand and store it
					tmpOperator->SetRight(ParseAddSub(ParseMultDiv()));
					
					// Then generate the assignment operation
					aktArg = new VarAssign(varPos);
					((VarAssign*)aktArg)->SetArithmetic(tmpOperator);
#endif

#ifdef MIT_FOROP
				// Check for post inc/decrementation
				} else if (!strncmp(Entry+IndxEntry, "--",2)) {
#ifdef DEBUG
printf("--");
#endif
					// Post decrementation
					forOperat = new OperatorIncDec(1, -1);
					forOperat->SetPosition(varPos);
					IndxEntry +=2;
					SUPP_BLANC
					return forOperat;					
				} else if (!strncmp(Entry+IndxEntry, "++",2)) {
#ifdef DEBUG
printf("++");
#endif
					// Post incrementation
					forOperat = new OperatorIncDec(1, 1);
					forOperat->SetPosition(varPos);
					IndxEntry +=2;
					SUPP_BLANC
					return forOperat;					
#endif
				} else {
					aktArg = new VarOperand(varPos);
				}
			}
		}

#ifndef USE_ITL
	} else if (Entry[IndxEntry] >= '0' && Entry[IndxEntry] <= '9' || Entry[IndxEntry] == '.') {
#else
	} else if (Entry[IndxEntry] >= '0' && Entry[IndxEntry] <= '9' || Entry[IndxEntry] == decSeparat) {
#endif
		// Constant operand. Read out complete value
		do {
			TextBuffer[indxBuffer++] = Entry[IndxEntry++];
#ifndef USE_ITL
		} while (Entry[IndxEntry] >= '0' && Entry[IndxEntry] <= '9' || Entry[IndxEntry] == '.');
#else
		} while (Entry[IndxEntry] >= '0' && Entry[IndxEntry] <= '9' || Entry[IndxEntry] == decSeparat);
#endif
		TextBuffer[indxBuffer] = '\0';
#ifdef DEBUG
printf(" %s\n", TextBuffer);
#endif
		// Suppress blancs
		SUPP_BLANC

		aktArg	= new ConstOperand(atof(TextBuffer));

	} else if (Entry[IndxEntry] == '(') {
#ifdef DEBUG
printf("\n(");
#endif
		IndxEntry++;
		// Parse expression to the corresponding )
		SUPP_BLANC
		aktArg = ParseAddSub(ParseMultDiv());
		if (Entry[IndxEntry] == ')') {
#ifdef DEBUG
printf(")\n");
#endif
			IndxEntry++;
			SUPP_BLANC
		} else {
			// Pb
			printf("Error corresponding ) not found %s\n", Entry+IndxEntry-4);
		}
	}

//#ifndef MIT_FOROP
	if (!aktArg && Entry[IndxEntry])
		aktArg = new ErrorOperand();
//#endif

	// Add eventual sign change
	if (chgSign) {
//		aktArg = new UnaryOperat(-, aktArg);
		aktArg = new UnaryOperat(uMoins, aktArg);
	}

	return aktArg;
}







/*******************************************

		BOOLEAN EXPRESSIONS

********************************************/



/*
This routine is provided to build up the object structure to evaluate a boolean expression as given
as parameter to an if call. Such an expression is made of comparison expressions linked with
boolean operators and or xor.
As for the arithmentic expressions, we build the object chain with regards to the precedence
of the oprators:
The structure is as follows : we have the logical combinations with or or xor operations between
arguments that are the result of and operations, that have arguments that are the result of
comparison operations.

Preconditions:
IndxEntry indicates the starting ( of the expression. or the

Postconditions : 
see ParseOperand
IndxEntry indicates the ending ) of the expression.

*/
GeneralBoolOperand *ParseBool(bool *stoppedOnParenth) {
	GeneralBoolOperand	*tmpBool = NULL;
	BinaryBoolOperat	*tmpBinBool = NULL;

	*stoppedOnParenth = false;

	if ('(' == Entry[IndxEntry]) {
		IndxEntry++;
		// parseBool calls parseAnds, parsComparison and parseOperand that stops when a ) is found with no corresponding (.
		tmpBool = ParseBool(stoppedOnParenth);
		if (')' != Entry[IndxEntry] && !(*stoppedOnParenth)) {
			// Pb
			Debugger();
			return new ErrorBoolOperand();
		}
		if (!(*stoppedOnParenth)) {
			// Suppress the ) that corresponds to the ( read in just before recursive call.
			IndxEntry++; SUPP_BLANC
		}
		
	} else {

		// Parse first comparison
		tmpBool = ParseAnds(stoppedOnParenth);
	}

	// Parse boolean operators until ) found
	while (!strncmp("xor",Entry+IndxEntry,3) || !strncmp("or",Entry+IndxEntry,2)) {

		if (!strncmp("or",Entry+IndxEntry,2)) {
			IndxEntry += 2;
//			tmpBool = new BinaryBoolOperat(||, tmpBool);
			tmpBinBool = new BinaryBoolOperat(_or, tmpBool);
		} else if (!strncmp("xor",Entry+IndxEntry,3)) {
			IndxEntry += 3;
//			tmpBool = new BinaryBoolOperat(^, LowPrioEnd);
			tmpBinBool = new BinaryBoolOperat(_xor, tmpBool);
		}

		// Suppress eventual blancs after operator
		SUPP_BLANC
#ifdef DEBUG
printf(" or / xor\n");
#endif

		if ('(' == Entry[IndxEntry]) {
			IndxEntry++;
			// parseBool calls parseAnds, parsComparison and parseOperand that stops when a ) is found with no corresponding (.
			tmpBool = ParseBool(stoppedOnParenth);
			if (')' != Entry[IndxEntry] && !stoppedOnParenth) {
				// Pb
				Debugger();
			}
			tmpBinBool->SetRight(tmpBool);
		} else {

			tmpBinBool->SetRight(ParseAnds(stoppedOnParenth));
		}
	}

	if (NULL == tmpBinBool) {
		return tmpBool;
	} else {
		return tmpBinBool;
	}
		
}

/*
This routine is provided to parse an and expression between two
arithmetic comparison expressions. It is done in a separate routine
from, the or/xor instructions in order to respect the priority of the
and instruction over the or/xor.

Preconditions:
IndxEntry points to the start of the boolean expression, if first call after the opening (
or see ParseComparison

Postconditions:
see parseOperand
*/
GeneralBoolOperand	*ParseAnds(bool *stoppedOnParenth) {
	BinaryBoolOperat	*tmpBool = NULL;
	bool dummy;

	*stoppedOnParenth = false;

	// Parse left argument
	tmpBool = (BinaryBoolOperat*)ParseComparison(stoppedOnParenth);
	
	// Here we must have  the and instruction
	while (!strncmp("and",Entry+IndxEntry,3)) {
		tmpBool = new BinaryBoolOperat(_and, tmpBool);
		// read out right argument
		IndxEntry += 3;
#ifdef DEBUG
printf(" and\n");
#endif
		
		tmpBool->SetRight(ParseComparison(&dummy));
	}

	return tmpBool;

}




/*
This routine is provided to parse a comparison expression between two
arithmetic expressions.

Preconditions:
IndxEntry points to the first character of the comparison expression, or a preceeding blanc,
or the starting ( character of a boolean expression).

Postconditions:
see ParseOperand
*/
GeneralBoolOperand *ParseComparison(bool *stoppedOnParenth) {
	GeneralOperand	*tmpOperand;
	BinaryCompOperator	*tmpOperator;
	bool notExp = false;

	*stoppedOnParenth = false;

	// Suppress eventual blancs after operator
	SUPP_BLANC

	// Parse first boolean argument (left operand of first binary operator)
	if (Entry[IndxEntry] == '!') {
		notExp = true;
		IndxEntry++;
		// Check if no illegal blancs are there
		if (Entry[IndxEntry]  == ' ')
		{
			Entry[IndxEntry+10] = '\0';
			printf("Error, illegal blanc in expression %s\n", Entry+IndxEntry-3);
			return new ErrorBoolOperand();
		}
	}

	// Parse first operand
	tmpOperand = ParseAddSub(ParseMultDiv());	// Final appel à ParseAddSub() !!!

	/* If parseOperand stopped because of a ), for which it has not read in a corresponding (, IndxEntry points to this ) after the call.
	*/
	if (')' == Entry[IndxEntry]) {
		*stoppedOnParenth = true;
		IndxEntry++; SUPP_BLANC
	}

	// Parse comparison operator
	indxBuffer = 0;
	
	while (Entry[IndxEntry]=='=' || Entry[IndxEntry]=='>' || Entry[IndxEntry]=='<' || Entry[IndxEntry]=='!') {
		TextBuffer[indxBuffer++] = Entry[IndxEntry++];;
	}
	
	if (indxBuffer>0) {
#ifdef DEBUG
// Null terminate to suppress values from memory
TextBuffer[indxBuffer] = 0;
printf("%s\n", TextBuffer);
#endif
	
		switch(indxBuffer) {
			case 2:
				if (!strncmp("!=",TextBuffer,2)) {
//					tmpOperator = new BinaryCompOperator(!=, tmpOperand);
					tmpOperator = new BinaryCompOperator(neq, tmpOperand);
				} else if (!strncmp(">=",TextBuffer,2)) {
//					tmpOperator = new BinaryCompOperator(>=, tmpOperand);
					tmpOperator = new BinaryCompOperator(get, tmpOperand);
				} else if (!strncmp("<=",TextBuffer,2)) {
//					tmpOperator = new BinaryCompOperator(<=, tmpOperand);
					tmpOperator = new BinaryCompOperator(let, tmpOperand);
				} else if (!strncmp("==",TextBuffer,2)) {
//					tmpOperator = new BinaryCompOperator(==, tmpOperand);
					tmpOperator = new BinaryCompOperator(eq, tmpOperand);
				} else {
					TextBuffer[indxBuffer] = 0;
					printf("%d Error, undefined operator %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
					return new ErrorBoolOperand();
				}
				break;

			case 1:
				if (!strncmp("<",TextBuffer,1)) {
//					tmpOperator = new BinaryCompOperator(<, tmpOperand);
					tmpOperator = new BinaryCompOperator(lt, tmpOperand);
				} else if (!strncmp(">",TextBuffer,1)) {
//					tmpOperator = new BinaryCompOperator(>, tmpOperand);
					tmpOperator = new BinaryCompOperator(gt, tmpOperand);
				} else {
					TextBuffer[indxBuffer] = 0;
					printf("%d Error, undefined operator %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
					return new ErrorBoolOperand();
				}
				break;
			default:
				TextBuffer[indxBuffer] = 0;
				printf("%d Error, no operator with lgth %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
				return new ErrorBoolOperand();
		}
	
	} else {

		while (Entry[IndxEntry]>='a' && Entry[IndxEntry]<='z') {
			TextBuffer[indxBuffer++] = Entry[IndxEntry++];;
		}
#ifdef DEBUG
TextBuffer[indxBuffer] = 0;
printf("%s\n", TextBuffer);
#endif

		switch(indxBuffer) {
			case 4:
				if (!strncmp("geth",TextBuffer,4)) {
//					tmpOperator = new BinaryCompOperator(>=, tmpOperand);
					tmpOperator = new BinaryCompOperator(get, tmpOperand);
				} else if (!strncmp("leth",TextBuffer,4)) {
//					tmpOperator = new BinaryCompOperator(<=, tmpOperand);
					tmpOperator = new BinaryCompOperator(let, tmpOperand);
				} else {
					TextBuffer[indxBuffer] = 0;
					printf("%d Error, undefined operator %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
					return new ErrorBoolOperand();
				}
				break;
			case 3:
				if (!strncmp("neq",TextBuffer,3)) {
//					tmpOperator = new BinaryCompOperator(!=, tmpOperand);
					tmpOperator = new BinaryCompOperator(neq, tmpOperand);
				} else if (!strncmp("lth",TextBuffer,3)) {
//					tmpOperator = new BinaryCompOperator(<, tmpOperand);
					tmpOperator = new BinaryCompOperator(lt, tmpOperand);
				} else if (!strncmp("gth",TextBuffer,3)) {
//					tmpOperator = new BinaryCompOperator(>, tmpOperand);
					tmpOperator = new BinaryCompOperator(gt, tmpOperand);
				} else {
					TextBuffer[indxBuffer] = 0;
					printf("%d Error, undefined operator %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
					return new ErrorBoolOperand();
				}
				break;
			case 2:
				if (!strncmp("eq",TextBuffer,2)) {
//					tmpOperator = new BinaryCompOperator(==, tmpOperand);
					tmpOperator = new BinaryCompOperator(eq, tmpOperand);
				} else {
					TextBuffer[indxBuffer] = 0;
					printf("%d Error, undefined operator %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
					return new ErrorBoolOperand();
				}
				break;
			default:
				TextBuffer[indxBuffer] = 0;
				printf("%d Error, no operator with lgth %s\n", (Graphs + numGraphs)->GraphicID, TextBuffer);
				return new ErrorBoolOperand();
		}
	}

	// Suppress eventual blancs
	SUPP_BLANC

	tmpOperator->SetRight(ParseAddSub(ParseMultDiv()));	// Final appel à ParseAddSub() !!!
	/* If parseOperand stopped because of a ), IndxEntry points to this ) )
	*/

	return tmpOperator;
}