#ifndef __SYMBOL_HPP__
#define __SYMBOL_HPP__

enum Type { TYPE_int, TYPE_bool };

struct STEntry {
  Type type;
  STEntry() {}
  STEntry(Type t) : type(t) {}
};

class Scope {
 public:
  Scope() {}
  void insert(char v, Type t) {
    if (locals.find(v) != locals.end())
      yyerror("Duplicate variable declaration");
    locals[v] = STEntry(t);
  }
  STEntry *lookup(char v) {
    if (locals.find(v) == locals.end()) return nullptr;
    return &(locals[v]);
  }
 private:
  std::map<char, STEntry> locals;
};

class SymbolTable {
 public:
  void insert(char v, Type t) {
    scopes.back().insert(v, t);
  }
  STEntry *lookup(char v) {
    for (auto s = scopes.rbegin(); s != scopes.rend(); ++s) {
      STEntry *e = s->lookup(v);
      if (e != nullptr) return e;
    }
    yyerror("Variable not found");
    return nullptr;
  }
  void enterScope() {
    scopes.push_back(Scope());
  }
  void exitScope() {
    scopes.pop_back();
  }
 private:
  std::vector<Scope> scopes;
};

extern SymbolTable st;

#endif
