是否有比lex / flex更好(更现代)的工具来为C ++生成标记化器?

时间:2010-01-30 23:01:13

标签: c++ windows lex tokenize

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

命令行参数变得非常复杂,我们开始允许它们作为一个被解析的文件提供,就好像它是一个非常大的命令行,但语法仍然很尴尬。所以我添加了使用更合理的语法解析源文件的功能。

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

我即将重新回到那段代码中,我想使用更好/更现代的工具。有谁知道这件事。

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

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

5 个答案:

答案 0 :(得分:11)

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

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

它生成的代码对程序的影响非常小。代码也非常快,Ragel语法比我见过的任何东西都更灵活,更易读。它是一块坚如磐石的软件。它可以生成表驱动的解析器或goto驱动的解析器。

答案 1 :(得分:6)

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

答案 2 :(得分:5)

我想到了两种工具,但您需要自己找出合适的工具,AntlrGoldParser。两种工具都提供了语言绑定,可以将其插入到C ++运行时环境中。

答案 3 :(得分:5)

Flex还有一个C ++输出选项 结果是一组用于解析的类。

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

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

然后在你的来源中它是:

std::fstream  file("config");
Lexer         lexer(&file)
while(int token = lexer.yylex())
{
}

答案 4 :(得分:2)

我想到了{p> boost.spiritYard parser。请注意,具有词法分析器生成器的方法在某种程度上被C ++内部DSL(特定于域的语言)所取代,以指定令牌。仅仅因为它是您的代码的一部分而不使用外部实用程序,只需遵循一系列规则来指定您的语法。