C ++ Interpreter:如何发出错误消息?

时间:2010-04-18 14:33:11

标签: c++ string

我想像现在所有解释器一样发出动态错误消息,例如:

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 个答案:

答案 0 :(得分:3)

您可以通过调用myVariableNamec_str获取以空字符结尾的C字符串:

myVariableName.c_str()

请注意,您对sprintf的使用不正确; sprintf的第一个参数将缓冲区放入其中以放置格式化字符串。如果您在计划中使用std::string,为什么要使用sprintf?如果Error需要std::string,那么您可以使用字符串连接:

Error(Name, "Undefined variable " + myVariableName, lineNum);

答案 1 :(得分:3)

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"