22

我最近将源文件解析添加到现有工具中,该工具从复杂的命令行参数生成输出文件。

命令行参数变得如此复杂,以至于我们开始允许将它们作为一个文件提供,该文件被解析为一个非常大的命令行,但语法仍然很笨拙。所以我添加了使用更合理的语法解析源文件的能力。

我使用 flex 2.5.4 for windows 来为这种自定义源文件格式生成标记器,它工作正常。但我讨厌代码。全局变量、奇怪的命名约定以及它生成的 c++ 代码非常糟糕。现有的代码生成后端粘在 flex 的输出上——我不使用 yacc 或 bison。

我即将深入研究该代码,并且我想使用更好/更现代的工具。有谁知道那件事。

  • 在 Windows 命令提示符下运行(Visual Studio 集成没问题,但我使用 make 文件构建)
  • 生成适当封装的 C++ 标记器。(没有全局变量)
  • 使用正则表达式来描述标记化规则(与 lex 语法兼容)
  • 不强迫我使用 c-runtime(或伪造它)进行文件读取。(从内存中解析)
  • 当我的规则强制标记器回溯(或自动修复它)时警告我
  • 让我完全控制变量和方法名称(这样我就可以符合我现有的命名约定)
  • 允许我将多个解析器链接到单个 .exe 中而不会发生名称冲突
  • 如果我愿意,可以生成一个 UNICODE(16 位 UCS-2)解析器
  • 不是集成标记器 + 解析器生成器(我想要 lex 替换,而不是 lex+yacc 替换)

如果这是唯一可用的工具,我可能会使用刚刚生成标记表的工具。

4

5 回答 5

11

Ragel: http: //www.complang.org/ragel/它符合您的大部分要求。

  • 它在 Windows 上运行
  • 它不声明变量,因此您可以根据需要将它们放入类或函数中。
  • 它有很好的工具来分析正则表达式以查看它们何时会回溯。(我对此不太了解,因为我从不在 Ragel 中使用会创建回溯解析器的语法。)
  • 变量名不能更改。
  • 表名以机器名作为前缀,它们被声明为“const static”,因此您可以将多个表放在同一个文件中,并在单个程序中拥有多个同名的表(只要它们是在不同的文件中)。
  • 您可以将变量声明为任何整数类型,包括 UChar(或您喜欢的任何 UTF-16 类型)。但是,它不会自动处理代理对。它也没有用于 Unicode 的特殊字符类(我认为)。
  • 它只做正则表达式......没有野牛/yacc 功能。

它生成的代码对程序的干扰很小。代码也非常快,而且 Ragel 语法比我见过的任何东西都更加灵活和可读。这是一款坚如磐石的软件。它可以生成表驱动解析器或 goto 驱动解析器。

于 2010-01-30T23:25:35.157 回答
7

Boost.Spirit.Qi(解析器分词器)或 Boost.Spirit.Lex(仅限分词器)。我非常喜欢 Qi,Lex 也不错,但我只是倾向于使用 Qi 来满足我的解析需求......

Qi 唯一真正的缺点往往是编译时间增加,而且它的运行速度也比手写解析代码稍慢。不过,它通常比使用正则表达式解析要快得多。

http://www.boost.org/doc/libs/1_41_0/libs/spirit/doc/html/index.html

于 2010-01-30T23:19:52.013 回答
6

Flex 还具有 C++ 输出选项。
结果是一组执行该解析的类。

只需将以下内容添加到您的 lex 文件的头部:

%option C++
%option yyclass="Lexer"

然后在您的来源中是:

std::fstream  file("config");
Lexer         lexer(&file)
while(int token = lexer.yylex())
{
}
于 2010-01-30T23:18:35.917 回答
5

有两个工具浮现在脑海中,尽管您需要自己找出合适的工具,AntlrGoldParser。两种工具中都有可用的语言绑定,可以将其插入 C++ 运行时环境。

于 2010-01-30T23:08:35.450 回答
2

我想到了boost.spiritYard 解析器。请注意,使用词法分析器生成器的方法在某种程度上被 C++ 内部 DSL(特定于域的语言)替代以指定标记。仅仅因为它是您代码的一部分,无需使用外部实用程序,只需遵循一系列规则来指定您的语法。

于 2010-01-30T23:22:39.483 回答