// Purpose.  Interpreter                private:
//                                         C c;  D d;
// Define a grammar for a language,     };
// and map each rule to a class.
                                        class Acti { public:
#include <iostream.h>                      int eval( char* i, char* o ) {
#include <string.h>                           if (e.eval(i,o)) return 1;
                                              if (f.eval(i,o)) return 1;
int sub(char* i, char* o, char* c) {          return 0; }
   strcat(o, c);  strcpy(i, &(i[1]));   private:
   return 1; }                             E e;  F f;
                                        };
class A { public:                       class Pass { public:
   int eval( char* i, char* o ) {          int eval( char* i, char* o ) {
      if (i[0] == 'a')                        if (g.eval(i,o)) return 1;
         return sub(i,o,"1");                 if (h.eval(i,o)) return 1;
      return 0; } };                          return 0; }
class B { public:                       private:
   int eval( char* i, char* o ) {          G g;  H h;
      if (i[0] == 'b')                  };
         return sub(i,o,"2");
      return 0; } };                    class NP { public:
class C { public:                          int eval( char* i, char* o ) {
   int eval( char* i, char* o ) {             if (arti.eval(i,o))
      if (i[0] == 'c')                           if (noun.eval(i,o)) return 1;
         return sub(i,o,"3");                 return 0; }
      return 0; } };                    private:
class D { public:                          Arti arti;  Noun noun;
   int eval( char* i, char* o ) {       };
      if (i[0] == 'd')                  class Verb { public:
         return sub(i,o,"4");              int eval( char* i, char* o ) {
      return 0; } };                          if (acti.eval(i,o)) return 1;
class E { public:                             if (pass.eval(i,o)) return 1;
   int eval( char* i, char* o ) {             return 0; }
      if (i[0] == 'e')                  private:
         return sub(i,o,"5");              Acti acti;  Pass pass;
      return 0; } };                    };
class F { public:
   int eval( char* i, char* o ) {       class Sent { public:
      if (i[0] == 'f')                     int eval( char* i, char* o ) {
         return sub(i,o,"6");                 if (np.eval(i,o))
      return 0; } };                             if (verb.eval(i,o)) return 1;
class G { public:                             return 0; }
   int eval( char* i, char* o ) {       private:
      if (i[0] == 'g')                     NP np;  Verb verb;
         return sub(i,o,"7");           };
      return 0; } };
class H { public:                       void main( void )
   int eval( char* i, char* o ) {       {
      if (i[0] == 'h')                     Sent S;  char* t[] = {"ace","bdh",
         return sub(i,o,"8");                            "abc","ceg","bcfgh"};
      return 0; } };                       char  i[10], o[10];
                                           for (int j=0; j < 5; j++) {
class Arti { public:                          strcpy(i,t[j]); strcpy(o,"");
   int eval( char* i, char* o ) {             cout << i << " is ";
      if (a.eval(i,o)) return 1;              if ( ! S.eval(i,o) || i[0])
      if (b.eval(i,o)) return 1;                 cout << "bad" << endl;
      return 0; }                             else
private:                                         cout << o << endl; }
   A a;  B b;                           }
};
class Noun { public:                    // ace is 135
   int eval( char* i, char* o ) {       // bdh is 248
      if (c.eval(i,o)) return 1;        // abc is bad
      if (d.eval(i,o)) return 1;        // ceg is bad
      return 0; }                       // bcfgh is bad



// Purpose.  Interpreter design pattern demo (with Template Method)
//
// Discussion.  Uses a class hierarchy to represent the grammar given
// below.  When a roman numeral is provided, the class hierarchy validates
// and interprets the string.  RNInterpreter "has" 4 sub-interpreters.
// Each sub-interpreter receives the "context" (remaining unparsed string
// and cumulative parsed value) and contributes its share to the processing.
// Sub-interpreters simply define the Template Methods declared in the base
// class RNInterpreter.
//   romanNumeral ::= {thousands} {hundreds} {tens} {ones}
//   thousands, hundreds, tens, ones ::= nine | four | {five} {one} {one} {one}
//   nine ::= "CM" | "XC" | "IX"
//   four ::= "CD" | "XL" | "IV"
//   five ::= 'D' | 'L' | 'V'
//   one  ::= 'M' | 'C' | 'X' | 'I'

#include <iostream.h>
#include <string.h>

class Thousand;  class Hundred;  class Ten;  class One;

class RNInterpreter {
public:
	RNInterpreter();		  // ctor for client
	RNInterpreter( int ) { }  // ctor for subclasses, avoids infinite loop
	int interpret( char* );	  // interpret() for client
	virtual void interpret( char* input, int& total ) {	// for internal use
		int  index;  index = 0;
		if ( ! strncmp(input, nine(), 2)) {
			total += 9 * multiplier();
			index += 2; }
		else if ( ! strncmp(input, four(), 2)) {
			total += 4 * multiplier();
			index += 2; }
		else {
			if (input[0] == five()) {
				total += 5 * multiplier();
				index = 1; }
			else index = 0;
			for (int end = index + 3 ; index < end; index++)
				if (input[index] == one())
					total += 1 * multiplier();
				else break; }
		strcpy( input, &(input[index])); }	// remove leading chars processed
protected:  // cannot be pure virtual because client asks for instance
	virtual char  one()        { }		virtual char* four() { }
	virtual char  five()       { }		virtual char* nine() { }
	virtual int   multiplier() { }
private:
	RNInterpreter*  thousands;			RNInterpreter*  hundreds;
	RNInterpreter*  tens;				RNInterpreter*  ones;
};

class Thousand : public RNInterpreter {
public:  // provide 1-arg ctor to avoid infinite loop in base class ctor
	Thousand( int ) : RNInterpreter(1) { }
protected:
	char  one()        { return 'M'; }	char* four() { return ""; }
	char  five()       { return '\0'; }	char* nine() { return ""; }
	int   multiplier() { return 1000; }
};

class Hundred : public RNInterpreter {
public:
	Hundred( int ) : RNInterpreter(1) { }
protected:
	char  one()        { return 'C'; }	char* four() { return "CD"; }
	char  five()       { return 'D'; }	char* nine() { return "CM"; }
	int   multiplier() { return 100; }
};

class Ten : public RNInterpreter {
public:
	Ten( int ) : RNInterpreter(1) { }
protected:
	char  one()        { return 'X'; }	char* four() { return "XL"; }
	char  five()       { return 'L'; }	char* nine() { return "XC"; }
	int   multiplier() { return 10; }
};

class One : public RNInterpreter {
public:
	One( int ) : RNInterpreter(1) { }
protected:
	char  one()        { return 'I'; }	char* four() { return "IV"; }
	char  five()       { return 'V'; }	char* nine() { return "IX"; }
	int   multiplier() { return 1; }
};

RNInterpreter::RNInterpreter() {  // use 1-arg ctor to avoid infinite loop
	thousands = new Thousand(1);		hundreds = new Hundred(1);
	tens      = new Ten(1);				ones     = new One(1); }

int RNInterpreter::interpret( char* input ) {
	int  total;  total = 0;
	thousands->interpret( input, total );
	hundreds->interpret( input, total );
	tens->interpret( input, total );
	ones->interpret( input, total );
	if (strcmp(input, ""))	// if input was invalid, return 0
		return 0;
	return total; }


void main() {
	RNInterpreter interpreter;
	char          input[20];
	cout << "Enter Roman Numeral: ";
	while (cin >> input)
	{
		cout << "   interpretation is " << interpreter.interpret(input) << endl;
		cout << "Enter Roman Numeral: ";
	}
}

// Enter Roman Numeral: MCMXCVI
//    interpretation is 1996
// Enter Roman Numeral: MMMCMXCIX
//    interpretation is 3999
// Enter Roman Numeral: MMMM
//    interpretation is 0
// Enter Roman Numeral: MDCLXVIIII
//    interpretation is 0
// Enter Roman Numeral: CXCX
//    interpretation is 0
// Enter Roman Numeral: MDCLXVI
//    interpretation is 1666
// Enter Roman Numeral: DCCCLXXXVIII
//    interpretation is 888
