C ++ Interpreter: как генерировать сообщения об ошибках? - PullRequest
2 голосов
/ 18 апреля 2010

Я хочу выдавать динамические сообщения об ошибках, как это делают все переводчики в настоящее время, например:

Name error: Undefined variable

будет постоянным, однако я хочу достичь:

Name error: Undefined variable 'X', in line 1

Хорошо. Номер строки действительно не был проблемой: каждое сообщение об ошибке должно иметь номер строки, поэтому я добавил его в функцию генератора ошибок:

Error( ErrType type, string msg, int line );

Так где же моя проблема?

Как мне получить 'X' в Undefined variable *?

  • Я не могу использовать sprintf, поскольку он не поддерживает строки, но я использую их везде
  • Я не могу просто использовать cout и подключить все, так как я хочу, чтобы сообщения об ошибках подавлялись
  • Я хотел бы получить все в одну функцию, как указано выше, Error()

Как собрать динамические сообщения об ошибках?

Например: Error( Name, sprintf("Undefined variable %s", myVariableName ), lineNum );

(Но myVariableName - строка, и sprintf все испортит)

Ответы [ 2 ]

3 голосов
/ 18 апреля 2010

Clang решает, что их диагностика перегружена operator<<, передавая необходимые аргументы, которые я также принял в моем компиляторе

DiagnosticBuilder Error( ErrType type, string msg, int line );

Вы можете назвать это как

Error(Serious, "Variable % is not known", lineNumber) << var;

Когда вызывается деструктор построителя диагностики, выдается ошибка.

struct DiagnosticBuilder {
  DiagnosticBuilder(std::string const& format)
    :m_emit(true), m_format(format) 
  { }
  DiagnosticBuilder(DiagnosticBuilder const& other) 
    :m_emit(true), m_format(other.m_format), m_args(other.m_args) {
    other.m_emit = false;
  }
  ~DiagnosticBuilder() {
    if(m_emit) {
      /* iterate over m_format, and print the next arg 
         everytime you hit '%' */
    }
  }

  DiagnosticBuilder &operator<<(string const& s) {
    m_args.push_back(s);
    return *this;
  }
  DiagnosticBuilder &operator<<(int n) {
    std::ostringstream oss; oss << n;
    m_args.push_back(oss.str());
    return *this;
  }
  // ...
private:
  mutable bool m_emit;
  std::string m_format;
  std::vector<std::string> m_args;
};

Я считаю, что этот способ сделать это довольно удобно. Вы можете расширить его для поддержки нескольких языков путем нумерации аргументов-заполнителей, например "Variable %2 isn't found in scope %1".

3 голосов
/ 18 апреля 2010

Вы можете получить строку C с нулевым символом в конце myVariableName, вызвав c_str:

myVariableName.c_str()

Обратите внимание, что вы используете sprintf неправильно; первый параметр sprintf принимает буфер для размещения отформатированной строки. Если вы используете std::string в своей программе, зачем вообще использовать sprintf? Если Error принимает std::string, вы можете просто использовать конкатенацию строк:

Error(Name, "Undefined variable " + myVariableName, lineNum);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...