#ifndef _APP_H #define _APP_H #include #include #include #include using namespace std; #include "output.h" #include "arithmetica.h" #include "image.h" #include "boolean.h" #include "nodes_arithmetica.h" #include "nodes_image.h" #include "translator.h" #include "exptree.h" #include "token.h" /** * Application factory, used to run different programs dynamically * * You can use application to read an evaluate a string and check if * a string is a valid expression. * */ class App { public: virtual ~App () {} virtual void readAndEval (const string & input) = 0; virtual bool isValidExpression (const string & input) = 0; }; class ArithmeticaApp : public App { public: ArithmeticaApp () : myToken("data/arithmetica.map") {} void readAndEval (const string & input) { Translator t(myToken); Expression myExp = t.start(input, myVariables); Output out; out.printOutput(myExp); out.printEval(myExp); } bool isValidExpression (const string & input) // returns true if the user input is a valid Arithmatica expression. { string spacelessInput = stripWhite(input, myToken); if (spacelessInput == "") return false; istringstream inputStream(spacelessInput); string unaryChecker; char currentChar, nextChar; //, tempChar; int parenCount = 0; while (inputStream.get(currentChar)) { if (myToken.isOpenParen(currentChar)) { parenCount++; } else if (myToken.isCloseParen(currentChar)) { if (parenCount < 1 ) return false; else parenCount--; } if (inputStream.get(nextChar)) { inputStream.putback(nextChar); // put the char back on stream } else if (myToken.isOp(currentChar) && !myToken.isParen(currentChar)) { return false; // return false if last char is operator } else // could be valid, make sure parens line up { if (parenCount != 0) { return false; } } //check for unary op errors if (! myToken.isOp(currentChar) && //the current char is not an op ! myToken.isOp(nextChar)) // and the next char is not an op { unaryChecker = ""; while (!myToken.isOp(currentChar)) { //while the current char is not an op unaryChecker.push_back(currentChar); // add the current char to a string if (inputStream.peek() != EOF) { inputStream.get(currentChar); } else break; // and get another from the stream } nextChar = inputStream.peek(); //peek at the next char if (myToken.isOp(unaryChecker) && //if the created string is a unary op !myToken.isOpenParen(nextChar)) // and it's not followed by a ( return false; } else if (myToken.isOp(currentChar)) { // current char is and op //note: ) and ( are ops. if (myToken.isCloseParen(currentChar)) { //current char is ) if ( (!myToken.isOp(nextChar)) || // next char is not op (myToken.isOpenParen(nextChar))) // or next char is ( return false; } else { // current char is an op other than ) if ((!myToken.isOpenParen(nextChar)) && // and next char isn't ( (myToken.isBinaryOp(nextChar))) // and next char is binary op return false; } } else { // current char isn't an op if ( //(!myToken.isOp(nextChar)) || // next char isn't an op (myToken.isOpenParen(nextChar))) // or next char is ( return false; } } return true; } private: map > myVariables; Token myToken; }; class ImageApp : public App { public: ImageApp () : myToken("data/image.map") {} void readAndEval (const string & input) { Translator t(myToken); Expression myExp = t.start(input, myVariables); Output out; out.printOutput(myExp); out.printEval(myExp); } bool isValidExpression (const string & input) { return true; } private: map > myVariables; Token myToken; }; class BoolApp : public App { public: BoolApp () : myToken("data/bool.map") {} void readAndEval (const string & input) { Translator t(myToken); Expression myExp = t.start(input, myVariables); Output out; out.printOutput(myExp); out.printEval(myExp); } bool isValidExpression(const string & input) { return true; } private: map > myVariables; Token myToken; }; #endif // App.h