// Lab Problem 4A - file "machine4a.h" // SE307 CCT // T Naughton, CS NUIM, tomn@cs.may.ie // Last updated 1 November 2000 #include #include #include #include "machinebase.h" // direct base class for this machine #ifndef MACHINE4A_H #define MACHINE4A_H /* This class describes a machine that analyses the code of ** another machine passed to it as input. ** The machine assumes that inputs are syntactically correct and ** follow the restricted format defined in the lab sheets. ** ** The particular analysis performed is determined by the ** ProcessingDeclaration() and ProcessStatement() methods. ** In this machine, these methods perform a simple static ** analysis. ** The machine keeps track of nested loops in the input ** machine's code through recursion so that it knows when the ** final `}' symbol has been reached. It demonstrates this by ** `pretty printing' the input machine's code. ** ** This machine extends MachineBase. As of October 2000 the ** code resides at http://www.cs.may.ie/~tnaughton/ ** at the link for course SE307 Computational Complexity Theory. */ class MachineFourA : public MachineBase { /* This class defines a machine that reads a description of ** another machine (a program following the format described ** in the lab sheets) and performs some analysis on it. The ** result of the analysis is a simple true/false answer. */ /* The following protected data members are from MachineBase: ** char b - input buffer ** ifstream machin - stream object to read from file ** bool analysis - the result of the analysis ** ** The following public methods are from MachineBase: ** bool Analyse() - analyse the input machine in some way ** ** The following protected methods are from MachineBase: ** string Spaces(int) - create blanks for indendation ** string ReadUntil(char) - read from machin until a particular ** character is encountered ** void JumpEndBlock() - reposition file pointer at end of ** current block */ /* ** Data members: public, protected, and private */ /* ** Member functions: public, protected, and private */ public: MachineFourA(string fname); // constructor virtual ~MachineFourA(); // destructor private: virtual void ProcessDeclaration(); // process a declaration virtual void ProcessStatement(int level); // process a statement }; MachineFourA::MachineFourA(string fname) :MachineBase(fname) { /* Constructor. Call base class constructor. Initialise ** derived class data members. */ } MachineFourA::~MachineFourA() { /* Destructor. Tidy up. Automatically call base class ** destructor. ** This method is also virtual. This means that a base ** class pointer pointing to a derived class will call the ** derived class' destructor on any explicit "delete" ** calls. */ } void MachineFourA::ProcessDeclaration() { /* Process the declaration by scanning through until a ** semicolon is encountered. Something more sophisticated ** will need to be done here if the program is to analyse ** the machine rather than simply pretty print the code. ** Spaces and newlines are ignored here. */ cout << endl << Spaces(1) << b; cout << ReadUntil(';'); cout << b << flush; } void MachineFourA::ProcessStatement(int level) { /* Process assignments, couts, increments, and while loops. ** When processing the statements within loops, call this ** method recursively. This allows us to follow the structure ** of the code: as shown by our ability to `pretty print' the ** program. Something more sophisticated will need to be done ** here if the input machine is to be really analysed. ** Spaces and newlines are ignored here. `level' is used for ** correct indentation. */ if (b == 'w') { // a while loop // process the control portion of the loop first cout << endl << Spaces(level) << b; cout << ReadUntil('{'); cout << b << flush; // process the body of the loop machin >> b; while (b != '}') { ProcessStatement(level+1); machin >> b; // read first symbol of next statement } // process the end of the loop cout << endl << Spaces(level) << b << flush; } else { // the statement is not a while loop, process simply cout << endl << Spaces(level) << b; cout << ReadUntil(';'); cout << b << flush; } } #endif