C ++选项/长选项实现

时间:2012-09-30 05:11:57

标签: c++ linux parsing

我正在Linux平台上使用C ++编写元编程语言解析器。现在,我需要为解析器实现option / long选项以提供一些额外的功能。基本上,如果用户传入一些附加选项,解析器需要在解析文本文件时存储统计信息。

我可以想到两种方法来实现它。一种方法是用户全局存储用户输入的选项。另一种方法是创建一个单例类来存储选项。所以我想知道是否有其他方法来实现它。实施它的最佳/最推荐的方法是什么?提前谢谢。

此致

K.Hein

2 个答案:

答案 0 :(得分:2)

全局变量和单例变量都会使解析器的单元测试变得很痛苦。要使用不同选项对解析器的行为进行单元测试,您的测试需要修改全局变量。这种方法至少存在两个问题:全局变量和你的类之间没有明确的关联。除了检查实现之外,读者无法分辨您的类中使用了哪些全局变量以及它们如何影响行为。这样的全局变量不能是const(因为它们是在main中设置的)。因此,您失去了沟通和执行的能力,一旦创建了解析器,就无法更改选项的值。

经典单例甚至比全局变形更糟糕,因为它无法替换实现,通常会完全阻碍测试。

一个很好的方法是注入一个const对象,它将选项存储到解析器构造函数中。但是不要在此对象中放置命令行解析逻辑,否则您将无法在测试中方便地使用该对象。

答案 1 :(得分:1)

要扩展Jan的答案,您将拥有如下功能:

bool my_parser(const parser_options &options);

parser_options类型可以是一个简单的结构,例如:

struct parser_options
{
    FILE *source_file;
    bool warnings_as_errors;
    std::shared_ptr<error_handler> eh;
    ...
};

error_handler可以这样定义:

struct error_handler
{
    virtual void error(int code, const char *message) = 0;
    virtual void warning(int code, const char *message) = 0;
    virtual ~error_handler() {}
};

该程序将执行以下操作:

int main(int argc, const char *argv)
{
    parser_options options;
    // process argc/argv options here, adding them to options, e.g.:
    //     case WARN_AS_ERROR: options.warnings_as_errors = true; break;
    return my_parser(options, &error) ? ERROR_SUCCESS : ERROR_FAILURE;
}

这允许您编写直接调用my_parser的测试,独立于命令行处理设置parser_options,并允许指定不同的error_handler(例如,机器可读形式的信息。

注意:这并不是一个完美的解析器设计,它只是一个如何设计这样的东西的例子。

注意:此设计对于测试并非严格必要,前提是可以将应用程序配置为控制管道(例如,不进行优化,打印内部AST,内部表示,汇编代码,预处理器输出)。但是,设计更灵活,因为它允许不同的程序使用它而无需直接调用命令行程序(GUI应用程序/ IDE,静态分析工具等)。