Virus721
Virus721

Reputation: 8315

C++ Interface design issue

I'm coding a parser and I have the following interface :

class IStatement
{
   // Represents instructions like "HelloWorld();"
   // Or flow control blocks like : "if( foo ) { bar(); }", "return 0;" etc...
public:
    virtual void execute( CScope & ) const = 0;
};

And the following classes :

class CGoto : public IStatement // Basically a sequence of IStatement sub classes.
{
protected:
   vector<IStatement *>
public:
   virtual void execute( CScope & ) const; // Executes all statements.
};

class CConditional : public CGoto
{
protected:
   CExpression // Condition that must be true
public:
   virtual void execute( CScope & ) const; // If expression is true, executes all statements (i.e call CGoto::execute()).
};

My problem is that i would like to make a class CIf :

class CIf : public CConditional // Repesents a whole if/else if/ else block.
{
   // "this" is the "if" part of the if/else if/else block

   vector<CConditional *> _apoElseIfs; // "else if" parts, if any.

   CConditional * _poElse; // NULL if no "else" in if/else if/else block.

public:

   virtual void execute( CScope & roScope ) const
   {
      // HERE is my problem !
      // If the condition in the "if" part is true, i'm not going to execute
      // the else if's or the else.
      // The problem is that i have no idea from here if i should return because the
      // if was executed, or if i should continue to the else if's and the else.

      CConditional::execute( roScope );

      // Was the condition of the "if" true ? (i.e return at this point)

      // For each else if
      {
         current else if -> execute( roScope );
         // Was the condition of the current "else if" true ? (i.e return at this point)
      }

      else -> execute( roScope );
   }
};

I have no idea, after i've executed an "if" or a "else if" if i should continue or return.

I thought that i could use a boolean as a return value for the method execute() that would indicate if the statement had been executed or not, but that would not make sense for implementations of IStatement that are not conditional.

I could also make it so that the class CConditional doesn't test the condition itself, and so that CConditional::execute() executes the statements regardless of the condition, and that whatever manipules the class do it itself, but i would like to encasulate that test inside the CConditional::execute() method.

I hope i explained my problem as clearly as possible. Do you have any idea about how i could do that cleanly please ?

Thank you :)

Upvotes: 2

Views: 93

Answers (1)

C. E. Gesser
C. E. Gesser

Reputation: 821

Your design seems a little confuse.

I would have made a Block class, representing a { sttmnt1, sttmnt2, sttmntN }.

class Block : public IStatement
{
    std::vector<IStatement*> statements;
public:
    virtual void execute( CScope & ) const { /* executes list of statements */ }
};

This way you always work if single statements, and can use the Block class to handle multiple statements.

Also a Expression class for statements that can be evaluated, like 2 < x.

class IExpression : public IStatement
{
public:
    virtual Value evaluate(CScope &scope) const = 0;
    virtual void execute( CScope &scope ) const { evaluate(scope); }
}

You will need a Value class to represente the result of a expression.

Finally, the If class wold have as attribute one Expression, one Statement for the if part and another (optional) for the else part.

class If: public IStatement
{
    IExpression *condition;
    IStatement *ifPart;
    IStatement *elsePart;

public:
    virtual void execute( CScope &scope ) const {
        if (condition->evaluate().asBoolValue()) {
            ifPart->execute(scope);
        }
        else if (elsePart) {
            elsePart->execute(scope);
        }
    }
}

To handle else if cases you simply need to set a new If object as the else part of the first.

Upvotes: 2

Related Questions