Parsing yacc/byacc/bison和lex/flex的适当用途

Parsing yacc/byacc/bison和lex/flex的适当用途,parsing,yacc,flex-lexer,Parsing,Yacc,Flex Lexer,我读到的大多数关于这些实用程序的帖子通常建议使用其他方法来获得相同的效果。例如,提及这些工具的问题通常至少有一个答案包含以下内容: 使用boost库(在此处插入适当的boost库) 不要创建DSL使用(在此处插入喜爱的脚本语言) Antlr更好 假设开发者 。。。熟悉C语言 。。。是否至少知道一个脚本 语言(如Python、Perl等) 。。。必须用几乎所有的语言编写一些解析代码 每个项目都在进行 因此,我的问题是: 什么是合适的情况 是否非常适合这些实用程序 有(合理的)情况吗

我读到的大多数关于这些实用程序的帖子通常建议使用其他方法来获得相同的效果。例如,提及这些工具的问题通常至少有一个答案包含以下内容:

  • 使用boost库(在此处插入适当的boost库)
  • 不要创建DSL使用(在此处插入喜爱的脚本语言)
  • Antlr更好

假设开发者

  • 。。。熟悉C语言
  • 。。。是否至少知道一个脚本 语言(如Python、Perl等)
  • 。。。必须用几乎所有的语言编写一些解析代码 每个项目都在进行

因此,我的问题是:

  • 什么是合适的情况 是否非常适合这些实用程序
  • 有(合理的)情况吗 那里没有更好的 问题的替代方案,而不是yacc 和lex(或衍生工具)
  • 在实际的解析问题中有多少次 你能指望遇到空头吗 在yacc和lex中出现的 最好由最近的 解决方案
  • 对于尚未开发的开发人员 熟悉这些工具值得吗 这是他们应该投入时间的 学习他们的语法/习语?怎么办 这些与其他解决方案相比

在以前的一个项目中,我需要一种能够以相对非技术人员能够轻松使用的方式对任意数据生成查询的方法。数据是CRM类型的东西(比如名字、姓氏、电子邮件地址等等),但它的目的是针对许多不同的数据库,所有这些数据库都具有不同的模式

因此,我开发了一个用于指定查询的小DSL(例如,[FirstName]='Joe'和[LastName]='Bloggs'将选择所有被称为“Joe Bloggs”的人)。它有一些更复杂的选项,例如“optedout(medium)”语法可以选择所有选择不在特定媒体(电子邮件、短信等)上接收消息的人。有一个“ingroup(xyz)”,可以选择特定组中的每个人,等等

基本上,它允许我们指定诸如“ingroup('GroupA')和not ingroup('GroupB')之类的查询,这将被转换为如下SQL查询:

SELECT
    *
FROM
    Users
WHERE
    Users.UserID IN (SELECT UserID FROM GroupMemberships WHERE GroupID=2) AND
    Users.UserID NOT IN (SELECT UserID GroupMemberships WHERE GroupID=3)
(正如您所看到的,查询没有尽可能有效,但我想这就是机器生成的结果)


我没有使用flex/bison,但我确实使用了一个解析器生成器(目前我还不知道它的名称…)

我认为避免创建新语言是一个很好的建议,因为它只支持特定于领域的语言。这将更好地利用您的时间,使用现有的语言并使用域功能对其进行扩展

如果您试图创建一种新的语言是出于其他原因,也许是为了研究语言设计,那么这些工具就有点过时了。较新的生成器(如antlr),甚至是较新的实现语言(如ML),使语言设计变得更加容易


如果说有充分的理由使用这些工具,那可能是因为它们的遗留问题。您可能已经有了需要增强的语言的框架,该框架已经在其中一个工具中实现。您可能还受益于关于这些旧工具的大量教程信息,对于这些工具,还没有为更新和更灵活的语言实现方式编写的语料库。

我们在我的办公室中实现了一整套编程语言。我们用它来做这个。我认为这是一种快速而简单的方式来为事情编写翻译。可以想象,您可以使用它们编写几乎任何类型的文本解析器,但很多时候,要么a)自己快速编写,要么B)您需要比它们提供的更大的灵活性。

学习这些工具是否值得,将在很大程度上取决于(几乎完全取决于您编写了多少解析代码,或者您对按照一般顺序编写更多代码有多感兴趣。我已经使用了很多,并且发现它们非常有用

你所使用的工具并没有你所相信的那么重要。对于我处理的大约95%的输入,它们之间的差别很小,最好的选择只是我最熟悉和最舒服的一个


当然,lex和yacc会产生(并要求您用)C(或C++)编写操作。如果您对它们不满意,可以使用并产生您喜欢的语言(例如Python或Java)的工具毫无疑问,这将是一个更好的选择。就我而言,我不建议尝试将这样的工具与您不熟悉或不舒服的语言一起使用。特别是,如果您在某个操作中编写代码时产生编译器错误,那么在跟踪问题时,您从编译器获得的帮助可能会比平时少得多,因此您确实需要对该语言足够熟悉,只需对编译器发现错误的地方给出一点提示就可以识别问题。

lex/yacc和派生工具在今天如此普遍的原因是它们比其他工具存在的时间要长得多,它们在文献和实践中的覆盖面要大得多这与它们与其他lexer和解析器生成器工具的比较关系不大

无论你选择哪种工具,都会有一条重要的学习曲线。因此,一旦你使用了某个工具几次,并且对它的使用感到相对舒适,你就不太可能想花费额外的精力学习另一个工具。这是很自然的

此外,在20世纪60年代末和70年代初创建lex/yacc时,硬件限制对解析造成了严重挑战。yacc使用的表驱动LR解析方法在当时最合适,因为它可以通过使用rel以较小的内存占用实现