/*******************************************************************\

Module:

Author: Daniel Kroening, kroening@cs.cmu.edu

\*******************************************************************/

#ifndef CPROVER_ERROR_HANDLER_H
#define CPROVER_ERROR_HANDLER_H

#include <sstream>

#include "message.h"
#include "expr.h"

class error_handlert
{
public:
  error_handlert(message_handlert &_message_handler):
    message_handler(_message_handler),
    error_found(false),
    saved_error_location((const locationt &)nil_rep),
    sequence_number(1)
  {
  }

  virtual ~error_handlert() { }

  // overload to use language specific syntax
  virtual std::string to_string(const exprt &expr) { return expr.to_string(); }
  virtual std::string to_string(const typet &type) { return type.to_string(); }

  void err_location(const exprt &expr) { saved_error_location=expr.find_location(); }
  void err_location(const typet &type) { saved_error_location=type.location(); }
  void err_location(const irept &irep) { saved_error_location=(const locationt &)irep.find("#location"); }
  void err_location(const locationt &_location) { saved_error_location=_location; }

  void error(const std::string &message)
  {
    send_msg(true, message);
  }

  void warning(const std::string &message)
  {
    send_msg(false, message);
  }
  
  void error()
  {
    send_msg(true, err.str());
    clear_err();
    sequence_number++;
  }

  void warning()
  {
    send_msg(false, err.str());
    clear_err();
    sequence_number++;
  }
  
  std::ostringstream err;
  
  bool get_error_found() const
  {
    return error_found;
  }
  
  message_handlert &get_message_handler()
  {
    return message_handler;
  }
  
  void error_parse(unsigned level)
  {
    error_parse(level, err.str());
    clear_err();
  }
  
  void clear_err()
  {
    err.clear();
    err.str("");
  }

protected:
  message_handlert &message_handler;
  bool error_found;  
  locationt saved_error_location;
  unsigned sequence_number;
  
  void send_msg(bool is_error, const std::string &message)
  {
    if(message=="") return;
    if(is_error) error_found=true;
    message_handler.print(
      is_error?1:2,
      message,
      sequence_number,
      saved_error_location);
    saved_error_location.make_nil();
  }

  void error_parse_line(
    unsigned level,
    const std::string &line);

  void error_parse(
    unsigned level,
    const std::string &error);  
};

#endif
