Search code examples
c++language-design

C++: Conceptual problem in designing an intepreter


I'm programming an interpreter for an experimental programming language (educational, fun,...) So far, everything went well (Tokenizer & Parser), but I'm getting a huge problem with some of the data structures in the part that actually runs the tokenized and parsed code.

My programming language basically has only two types, int and string, and they are represented as C++ strings (std class) and ints

Here is a short version of the data structure that I use to pass values around:

enum DataType
{
  Null,
  Int,
  String
}

class Symbol
{
public:
 string identifier;

 DataType type;
 string stringValue;
 int intValue;
}

I can't use union because string doesn't allow me to.

This structure above is beginning to give me a headache.

I have to scatter code like this everywhere in order to make it work, it is beginning to grow unmaintainable:

if( mySymbol.type == Int )
{
  mySymbol.intValue = 1234;
} else {
  mySymbol.stringValue = "abcde";
}

I use the Symbol data structure for variables, return values for functions and general representation of values in the programming language.

  • Is there any better way to solve this? I hope so!

Solution

  • The problem comes from the fact, that your symbol class is a type that contains two different types that you are trying to identify through the single type of the class Symbol.

    It would be better to polymorphically create the symbols:

    class Symbol
    {
    public:
        virtual Symbol& operator = (int val) = 0; // Pure virtual
        virtual Symbol& operator = (string val) = 0; // Pure virtual
    private:
        string identifier;
    };
    
    class IntSymbol : public Symbol
    {
    public:
        virtual Symbol& operator = (int val)
        {
            this->val = val;
            return *this; // to make multiple assignments possible
        }
        virtual Symbol& operator = (string val)
        {
            throw new exception("Programm error");
            return *this; // to make it compile
        }
    private:
        int val;
    };
    

    You do the same for the StringSymbol