// CS 2704 Spring 2001 // Homework 2: Parsing a delimited input script // // Programmer: Bill McQuain // Platform: Win NT Workstation 4.0 // Compiler: MS Visual C++ V6.0, SP4 // Last modified: January 16, 2001 // // Description: // The program processed tab-delimited command lines from an input // script, named "Parsing.in". There are no data structures in this // project. // // Any line of the input script beginning with a semicolon character // ';' is treated as a comment. // // Any line not beginning with a semicolon is a command line. Each // command line will begin with a command string, terminated by a // single tab character. Each command will take at least two // parameters, which will either be strings or positive integers. // // It is guaranteed that no string will begin with a digit, and that // no integer will begin with a '+' character. All the integers // will be less than INT_MAX. // // Each remaining line contains one of the following commands: // // precedes [ | ] // equals [ | ] // follows [ | ] // // Each of these commands specifies a proposition. The program // determines whether that proposition is true or false, using // the comparison operators appropriate to the types of the // parameters, and prints either a confirmation or denial message. // // min // // The program must determine the minimum value in the given list, // and print that value in a confirmation message. // // exit // // The program will print a confirmation message and terminate. // // // The command lines are tab-separated, and none is more than 255 // characters long. // // Results are written to a log file, "ParseLog.txt". Processing stops // when an exit command, or end of file is reached. // #include #include #include #include #include using namespace std; const int MAXLINELENGTH = 255; const char COMMENTFLAG = ';'; const string Delimiter = "--------------------------------------------------"; enum Command {PRECEDES, EQUALS, FOLLOWS, MIN, EXIT, UNKNOWN}; void ProcessCmds(istream& In, ostream& Log); string getCommandLine(istream& In); void handlePrecedes(istream& In, ostream& Log); void handleEquals(istream& In, ostream& Log); void handleFollows(istream& In, ostream& Log); void handleMin(istream& In, ostream& Log); Command Classify(string S); void printHeader(ostream& Log); void main() { ifstream In("ParseIn.txt"); ofstream Log("ParseLog.txt"); printHeader(Log); ProcessCmds(In, Log); In.close(); Log.close(); } ///////////////////////////////////////////////////////////////// ProcessCmds() // ProcessCmds() contains the command processing logic. // // The command word is read from each line of the script file and // classified. Valid commands (aside from "exit") are then passed on // to dedicated handler functions. Processing stops on an "exit" command // or when an empty command string is obtained at end of file. // // Parameters: // In input file stream connected to script file // Log log file stream // // Pre: - In has been opened on a conformant input file // - Log has been opened on the output file // - there is a global string named Delimiter // // Post: - all command lines in the script file have been processed // // Called by: main() // Calls: handlePrecedes(), handleEquals(), handleFollows(), handleMin() // void ProcessCmds(istream& In, ostream& Log) { string cmdLine; string cmdString; cmdLine = getCommandLine(In); while (In && (cmdLine.length() > 0) ) { Log << "Command: " << cmdLine << endl; istringstream parseCmdLine(cmdLine); getline(parseCmdLine, cmdString, '\t'); switch( Classify(cmdString) ) { case PRECEDES: handlePrecedes(parseCmdLine, Log); break; case EQUALS: handleEquals(parseCmdLine, Log); break; case FOLLOWS: handleFollows(parseCmdLine, Log); break; case MIN: handleMin(parseCmdLine, Log); break; case EXIT: Log << "Exiting..." << endl; Log << Delimiter << endl; return; default: break; }; Log << Delimiter << endl; cmdLine = getCommandLine(In); } } ///////////////////////////////////////////////////////////////// getCommandLine() // getCommandLine() gets the next command line from the input stream. // // Parameters: // In input file stream connected to script file // // Pre: - In has been opened on a conformant input file // // Post: - The next command line, if any, has been read from In and // returned. // // Called by: ProcessCmds() // Calls: none // string getCommandLine(istream& In) { string nextCmdLine = ""; getline(In, nextCmdLine, '\n'); while ( In && ( (nextCmdLine.length() == 0) || (nextCmdLine.at(0) == COMMENTFLAG) ) ) { getline(In, nextCmdLine, '\n'); } return nextCmdLine; } ///////////////////////////////////////////////////////////////// handlePrecedes() // handlePrecedes() processes an "precedes" command. // // Parameters: // In input file stream connected to script file // Log log file stream // // Pre: - In has been opened on a conformant input file // - Log has been opened on the output file // // Post: - Command has been handled as described in the program header. // // Called by: ProcessCmds() // Calls: none // void handlePrecedes(istream& In, ostream& Log) { string sFirst, sSecond; int iFirst, iSecond; if ( isdigit(In.peek())) { // integer assertion In >> iFirst >> iSecond; In.ignore(MAXLINELENGTH, '\n'); if (iFirst < iSecond) { // which is true Log << "True: " << iFirst << " < " << iSecond << endl; } else { // which is false Log << "False: " << iFirst << " >= " << iSecond << endl; } } else { // string assertion getline(In, sFirst, '\t'); getline(In, sSecond, '\t'); if (sFirst < sSecond) { // which is true Log << "True: " << sFirst << " < " << sSecond << endl; } else { // which is false Log << "False: " << sFirst << " >= " << sSecond << endl; } } return; } ///////////////////////////////////////////////////////////////// handleEquals() // handleEquals() processes an "equals" command. // // Parameters: // In input file stream connected to script file // Log log file stream // // Pre: - In has been opened on a conformant input file // - Log has been opened on the output file // // Post: - Command has been handled as described in the program header. // // Called by: ProcessCmds() // Calls: none // void handleEquals(istream& In, ostream& Log) { string sFirst, sSecond; int iFirst, iSecond; if ( isdigit(In.peek())) { // integer assertion In >> iFirst >> iSecond; In.ignore(MAXLINELENGTH, '\n'); if (iFirst == iSecond) { // which is true Log << "True: " << iFirst << " == " << iSecond << endl; } else { // which is false Log << "False: " << iFirst << " != " << iSecond << endl; } } else { // string assertion getline(In, sFirst, '\t'); getline(In, sSecond, '\t'); if (sFirst == sSecond) { // which is true Log << "True: " << sFirst << " == " << sSecond << endl; } else { // which is false Log << "False: " << sFirst << " != " << sSecond << endl; } } return; } ///////////////////////////////////////////////////////////////// handleFollows() // handleFollows() processes an "follows" command. // // Parameters: // In input file stream connected to script file // Log log file stream // // Pre: - In has been opened on a conformant input file // - Log has been opened on the output file // // Post: - Command has been handled as described in the program header. // // Called by: ProcessCmds() // Calls: none // void handleFollows(istream& In, ostream& Log) { string sFirst, sSecond; int iFirst, iSecond; if ( isdigit(In.peek())) { // integer assertion In >> iFirst >> iSecond; In.ignore(MAXLINELENGTH, '\n'); if (iFirst > iSecond) { // which is true Log << "True: " << iFirst << " > " << iSecond << endl; } else { // which is false Log << "False: " << iFirst << " <= " << iSecond << endl; } } else { // string assertion getline(In, sFirst, '\t'); getline(In, sSecond, '\t'); if (sFirst > sSecond) { // which is true Log << "True: " << sFirst << " > " << sSecond << endl; } else { // which is false Log << "False: " << sFirst << " <= " << sSecond << endl; } } return; } ///////////////////////////////////////////////////////////////// handleMin() // handleMin() processes an "follows" command. // // Parameters: // In input file stream connected to script file // Log log file stream // // Pre: - In has been opened on a conformant input file // - Log has been opened on the output file // // Post: - Command has been handled as described in the program header. // // Called by: ProcessCmds() // Calls: none // void handleMin(istream& In, ostream& Log) { int MinSoFar = INT_MAX, Next; In >> Next; while ( In ) { if ( Next < MinSoFar ) MinSoFar = Next; In >> Next; } Log << "Minimum: " << MinSoFar << endl; return; } ///////////////////////////////////////////////////////////////// Classify() // Classify() returns an enum type value corresponding to the string // passed to it. // // Parameters: // S a command word from the script file // // Pre: - S has been initialized // - there is a global enum type, Command with values PRECEDES, // EQUALS, FOLLOWS, MIN, EXIT, UNKNOWN // // Post: - If the command string is valid, then the matching // enum value is returned. // - If the command string is invalid, then the enum value // UNKNOWN is returned // // Called by: ProcessCmds() // Calls: none // Command Classify(string S) { if (S == "precedes") return PRECEDES; if (S == "equals") return EQUALS; if (S == "follows") return FOLLOWS; if (S == "min") return MIN; if (S == "exit") return EXIT; return UNKNOWN; } ///////////////////////////////////////////////////////////////// printHeader() // printHeader() prints an ID header to the Log file. // // Parameters: // Log output stream connected to the log file // // Pre: - Log has been opened on the log file // // Post: - the programmer's name and assignment info have been // written to the log file // - a delimiter line has been logged // // Called by: main() // Calls: none // void printHeader(ostream& Log) { Log << "Programmer: Bill McQuain" << endl; Log << "CS 2704 Homework 2: Parsing a Script File" << endl; Log << Delimiter << endl; }