代码之家  ›  专栏  ›  技术社区  ›  John Knoeller

是否有一个比Lex/Flex更好的(更现代的)工具来生成C++的记录器?

  •  22
  • John Knoeller  · 技术社区  · 14 年前

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

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

    我使用flex 2.5.4 for Windows为这个定制的源文件格式生成了tokenizer,它起作用了。但我讨厌这个密码。全局变量、WiRD命名约定和它生成的C++代码非常糟糕。现有的代码生成后端粘在flex的输出上-我不使用yacc或bison。

    我将回到代码中,我想使用更好/更现代的工具。有人知道吗?

    • 在Windows命令提示下运行(Visual Studio集成正常,但我使用生成文件进行生成)
    • 生成一个正确封装的C++令牌。(无全局变量)
    • 使用正则表达式描述标记化规则(与lex语法A plus兼容)
    • 不强制我使用C运行时(或伪造它)读取文件。(从内存分析)
    • 当我的规则强制标记器后退(或自动修复)时警告我
    • 使我能够完全控制变量和方法名(这样我就可以遵守现有的命名约定)
    • 允许我将多个分析器链接到一个.exe中,而不发生名称冲突
    • 如果需要,可以生成Unicode(16位UCS-2)分析器
    • 不是集成的tokenizer+解析器生成器(我需要lex替换,而不是lex+yacc替换)

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

    5 回复  |  直到 11 年前
        1
  •  11
  •   Dietrich Epp    14 年前

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

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

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

        2
  •  6
  •   Tronic    14 年前

    boost.spirit.qi(解析器标记器)或boost.spirit.lex(仅标记器)。我绝对喜欢qi,lex也不坏,但我只是倾向于把qi作为我的解析需求…

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

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

        3
  •  5
  •   Loki Astari    14 年前

    Flex也有一个C++输出选项。
    结果是一组进行解析的类。

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

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

    那么在你的资料中,它是:

    std::fstream  file("config");
    Lexer         lexer(&file)
    while(int token = lexer.yylex())
    {
    }
    
        4
  •  5
  •   t0mm13b    11 年前

    我想到了两个工具,尽管你需要自己找出合适的, Antlr GoldParser . 在两种工具中都有可用的语言绑定,其中可以插入到C++运行时环境中。

        5
  •  2
  •   Diego Sevilla    14 年前

    boost.spirit Yard parser 我想起来了。注意,具有词素生成器的方法被C++内部DSL(特定于域的语言)所取代,以指定令牌。只是因为它是代码的一部分,而不使用外部实用程序,只需遵循一系列规则来指定语法。