/***** * * 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() 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. * *****/ #include #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 */ #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 //#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 (indxBufferGraphicID); } 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= '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; varPosGraphicID); 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; varPosSetPosition(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; varPosSetPosition(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 if (4 == indxBuffer && 0 == strncmp("sqrt",TextBuffer,4)) { // Per recursive call read out expression in the () aktArg = new FunctOperat(sqrt, ParseAddSub(ParseMultDiv())); } else if (3 == indxBuffer && 0 == strncmp("exp",TextBuffer,3)) { aktArg = new FunctOperat(exp, ParseAddSub(ParseMultDiv())); } else if (2 == indxBuffer && 0 == strncmp("ln",TextBuffer,2)) { aktArg = new FunctOperat(log, ParseAddSub(ParseMultDiv())); } else if (4 == indxBuffer && 0 == strncmp("sinh",TextBuffer,4)) { aktArg = new FunctOperat(sinh, ParseAddSub(ParseMultDiv())); } else if (4 == indxBuffer && 0 == strncmp("cosh",TextBuffer,4)) { aktArg = new FunctOperat(cosh, ParseAddSub(ParseMultDiv())); } else if (4 == indxBuffer && 0 == strncmp("tanh",TextBuffer,4)) { aktArg = new FunctOperat(tanh, ParseAddSub(ParseMultDiv())); } else if (3 == indxBuffer && 0 == strncmp("sin",TextBuffer,3)) { aktArg = new FunctOperat(sin, ParseAddSub(ParseMultDiv())); } else if (3 == indxBuffer && 0 == strncmp("cos",TextBuffer,3)) { aktArg = new FunctOperat(cos, ParseAddSub(ParseMultDiv())); } else if (3 == indxBuffer && 0 == strncmp("tan",TextBuffer,3)) { aktArg = new FunctOperat(tan, ParseAddSub(ParseMultDiv())); } else if (4 == indxBuffer && 0 == strncmp("asin",TextBuffer,4)) { aktArg = new FunctOperat(asin, ParseAddSub(ParseMultDiv())); } else if (4 == indxBuffer && 0 == strncmp("acos",TextBuffer,4)) { aktArg = new FunctOperat(acos, ParseAddSub(ParseMultDiv())); } else if (4 == indxBuffer && 0 == strncmp("atan",TextBuffer,4)) { aktArg = new FunctOperat(atan, ParseAddSub(ParseMultDiv())); } else { printf("Error unimplemented function\n"); } 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; varPosSetPosition(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 if (2 == indxBuffer && !strncmp("!=",TextBuffer,2)) { // tmpOperator = new BinaryCompOperator(!=, tmpOperand); tmpOperator = new BinaryCompOperator(neq, tmpOperand); } else if (2 == indxBuffer && !strncmp(">=",TextBuffer,2)) { // tmpOperator = new BinaryCompOperator(>=, tmpOperand); tmpOperator = new BinaryCompOperator(get, tmpOperand); } else if (2 == indxBuffer && !strncmp("<=",TextBuffer,2)) { // tmpOperator = new BinaryCompOperator(<=, tmpOperand); tmpOperator = new BinaryCompOperator(let, tmpOperand); } else if (2 == indxBuffer && !strncmp("==",TextBuffer,2)) { // tmpOperator = new BinaryCompOperator(==, tmpOperand); tmpOperator = new BinaryCompOperator(eq, tmpOperand); } else if (1 == indxBuffer && !strncmp("<",TextBuffer,1)) { // tmpOperator = new BinaryCompOperator(<, tmpOperand); tmpOperator = new BinaryCompOperator(lt, tmpOperand); } else if (1 == indxBuffer && !strncmp(">",TextBuffer,1)) { // tmpOperator = new BinaryCompOperator(>, tmpOperand); tmpOperator = new BinaryCompOperator(gt, tmpOperand); } else { // Error TextBuffer[indxBuffer] = 0; printf("%d Error, undefined operator %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 if (3 == indxBuffer && !strncmp("neq",TextBuffer,3)) { // tmpOperator = new BinaryCompOperator(!=, tmpOperand); tmpOperator = new BinaryCompOperator(neq, tmpOperand); } else if (4 == indxBuffer && !strncmp("geth",TextBuffer,4)) { // tmpOperator = new BinaryCompOperator(>=, tmpOperand); tmpOperator = new BinaryCompOperator(get, tmpOperand); } else if (4 == indxBuffer && !strncmp("leth",TextBuffer,4)) { // tmpOperator = new BinaryCompOperator(<=, tmpOperand); tmpOperator = new BinaryCompOperator(let, tmpOperand); } else if (2 == indxBuffer && !strncmp("eq",TextBuffer,2)) { // tmpOperator = new BinaryCompOperator(==, tmpOperand); tmpOperator = new BinaryCompOperator(eq, tmpOperand); } else if (3 == indxBuffer && !strncmp("lth",TextBuffer,3)) { // tmpOperator = new BinaryCompOperator(<, tmpOperand); tmpOperator = new BinaryCompOperator(lt, tmpOperand); } else if (3 == indxBuffer && !strncmp("gth",TextBuffer,3)) { // tmpOperator = new BinaryCompOperator(>, tmpOperand); tmpOperator = new BinaryCompOperator(gt, tmpOperand); } else { // Error TextBuffer[indxBuffer] = 0; printf("%d Error, undefined operator %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; }