This server is intended for use for Academic Classwork related Git repositories only. Projects/repositories will generally be removed after 6 months following close of the semester. Inactive repositories from previous semester are now being archived when no activity for 365 days. They are renamed and marked as 'archived'. After 90 days in that state they will be removed from the system completely.

SymbolTableEntry.h 3.79 KB
Newer Older
Jonathan Evans's avatar
Jonathan Evans committed
1 2 3 4
#ifndef SYMBOL_TABLE_ENTRY_H
#define SYMBOL_TABLE_ENTRY_H

#include <string>
jdev52's avatar
jdev52 committed
5
#include <cstring>
6 7
#include <ostream>
#include <stdexcept>
Jonathan Evans's avatar
Jonathan Evans committed
8 9
using namespace std;

jdev52's avatar
jdev52 committed
10 11 12 13 14 15 16 17 18 19 20 21 22 23
#define UNDEFINED     -1   // Type codes 
#define FUNCTION   8 
#define INT    1 
#define STR    2 
#define INT_OR_STR   3 
#define BOOL    4
#define INT_OR_BOOL  5 
#define STR_OR_BOOL  6 
#define INT_OR_STR_OR_BOOL 7     
#define NOT_APPLICABLE   -1 

#define ARITHMETIC          10
#define LOGICAL             11
#define RELATIONAL          12
Jonathan Evans's avatar
Jonathan Evans committed
24

jdev52's avatar
jdev52 committed
25 26 27 28 29 30 31 32 33 34 35 36 37 38
#define ADD 0
#define SUBTRACT 1
#define MULTIPLY 2
#define DIVIDE 3
#define AND 4
#define OR 5
#define NOT 6
#define LT 7
#define GT 8
#define LE 9
#define GE 10
#define EQ 11
#define NE 12

39 40 41 42 43 44 45
union TYPE_VALUE{
  char* text;
  bool boolean;
  int number;
};

struct TYPE_INFO 
46
{
47 48
  TYPE_VALUE value;

jdev52's avatar
jdev52 committed
49
	// one of the above type codes
50 51
	int type;

jdev52's avatar
jdev52 committed
52
	// numParams and returnType only applicable if type == FUNCTION   
53
  int numParams;  
54 55 56 57
	int returnType;
  
  // operatorType is only applicable if production is an operator 
  int operatorType;   
jdev52's avatar
jdev52 committed
58 59
  int operatorInstance;

jdev52's avatar
jdev52 committed
60 61
  operator bool()
  { 
jdev52's avatar
jdev52 committed
62 63 64 65 66 67 68
    if(type == BOOL){
      return value.boolean;
    }  
    return true;
  }

  bool operator!(){
jdev52's avatar
jdev52 committed
69
    return !(bool(*this));
jdev52's avatar
jdev52 committed
70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
  }

  // man I really wish I had c++20's operator<=>/operator semantics right now
  bool operator<(const TYPE_INFO& rhs) {
    if(type != rhs.type){
      throw std::invalid_argument("invalid type for comparison");
    }
    bool result = false;
    switch(rhs.type){
      case INT:
        result = value.number < rhs.value.number;
        break;
      case STR:
        result = (strcmp(value.text, rhs.value.text) == -1);
        break;
    }
    return result;
  }

  bool operator==(const TYPE_INFO& rhs){
    if(type != rhs.type){
      throw std::invalid_argument("invalid type for comparison");
    }
    bool result = false;
    switch(rhs.type){
      case INT:
        result = value.number == rhs.value.number;
        break;
      case STR:
        result = (strcmp(value.text, rhs.value.text) == 0);
        break;
    }
    return result;
  }

  bool operator<=(const TYPE_INFO& rhs){
    return (*this < rhs) || (*this == rhs);
  }

  bool operator>=(const TYPE_INFO& rhs){
    return !(*this < rhs);
  }

  bool operator>(const TYPE_INFO& rhs){
    return !(*this <= rhs);
  }

  bool operator!=(const TYPE_INFO& rhs){
    return !(*this == rhs);
  }
120 121 122 123 124 125 126 127 128 129

  friend ostream& operator<<(ostream& os, const TYPE_INFO& rhs){
    switch(rhs.type){
      case INT:
        os << rhs.value.number;
        break;
      case STR:
        os << rhs.value.text;
        break;
      case BOOL:
jdev52's avatar
jdev52 committed
130
        os << ((rhs.value.boolean)?"t":"nil");
131 132 133 134 135 136 137
        break;
      default:
        throw std::invalid_argument("invalid type at print");
    }
    return os;
  }
}; 
jdev52's avatar
jdev52 committed
138

Jonathan Evans's avatar
Jonathan Evans committed
139 140 141 142 143
class SYMBOL_TABLE_ENTRY 
{
private:
  // Member variables
  string name;
jdev52's avatar
jdev52 committed
144
  TYPE_INFO typeInfo;  
Jonathan Evans's avatar
Jonathan Evans committed
145 146 147

public:
  // Constructors
jdev52's avatar
jdev52 committed
148 149 150 151 152 153
  SYMBOL_TABLE_ENTRY( ) { 
    name = "";
    typeInfo.type = UNDEFINED;
    typeInfo.numParams = UNDEFINED;
    typeInfo.returnType = UNDEFINED;
  }
Jonathan Evans's avatar
Jonathan Evans committed
154

jdev52's avatar
jdev52 committed
155
  SYMBOL_TABLE_ENTRY(const string theName, const TYPE_INFO theType) {
Jonathan Evans's avatar
Jonathan Evans committed
156
    name = theName;
jdev52's avatar
jdev52 committed
157 158 159
    typeInfo.type = theType.type;
    typeInfo.returnType = theType.returnType;
    typeInfo.numParams = theType.numParams;
Jonathan Evans's avatar
Jonathan Evans committed
160 161
  }

162 163 164 165 166 167 168 169
  SYMBOL_TABLE_ENTRY(const string theName, const int type = UNDEFINED,
       const int numParams = UNDEFINED, const int returnType = UNDEFINED){
    name = theName;
    typeInfo.type = type;
    typeInfo.returnType = numParams;
    typeInfo.numParams = returnType;  
  }

Jonathan Evans's avatar
Jonathan Evans committed
170 171
  // Accessors
  string getName() const { return name; }
172
  TYPE_INFO getTypeInfo() const { return typeInfo; }
Jonathan Evans's avatar
Jonathan Evans committed
173 174 175
};

#endif  // SYMBOL_TABLE_ENTRY_H