适用于yacc / byacc / bison和lex / flex

时间:2010-03-10 03:24:52

标签: parsing yacc flex-lexer

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

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

假设开发人员......

  • ...对C语言感到满意
  • ...确实至少知道一个脚本 语言(例如,Python,Perl等)
  • ...几乎必须编写一些解析代码 每个项目都在进行中。

所以我的问题是:

  • 适当的情况是什么 是否适合这些公用事业?
  • 是否有(合理的)情况 哪里没有更好的 替代问题而不是yacc 和lex(或衍生物)?
  • 实际解析问题的频率 人们可以期待遇到任何空头 在yacc和lex中出现的是 更近期更好地解决了 溶液
  • 对于尚未开发的开发人员 熟悉这些工具是值得的 它让他们投入时间 学习他们的语法/习语?怎么做 这些与其他解决方案相比?

5 个答案:

答案 0 :(得分:5)

lex / yacc和衍生品在今天如此普遍存在的原因是它们比其他工具存在的时间长得多,它们在文献中有更多的报道,而且传统上它们都带有Unix操作系统。它与其他词法分析器和解析器生成器工具的比较几乎没有什么关系。

无论您选择哪种工具,总会有一个重要的学习曲线。因此,一旦您使用了一个给定的工具并且在使用中变得相对舒适,您就不太可能想要学习另一个工具的额外工作。那是很自然的。

此外,在20世纪60年代末和70年代早期创建lex / yacc时,硬件限制对解析提出了严峻挑战。 Yacc使用的表驱动的LR解析方法当时是最合适的,因为它可以通过使用相对较小的通用程序逻辑并通过将状态保持在磁带或磁盘上的文件中来实现小内存占用。代码驱动的解析方法(例如LL)具有更大的最小内存占用量,因为解析器程序的代码本身代表语法,因此它需要完全适合RAM来执行,并且它将状态保存在RAM中的堆栈中。

当内存变得越来越丰富时,更多的研究进入了不同的解析方法,如LL和PEG,以及如何使用这些方法构建工具。这意味着在lex / yacc系列之后创建的许多替代工具使用不同类型的语法。然而,切换语法类型也会产生重要的学习曲线。一旦熟悉了一种语法,例如LR或LALR语法,就不太可能想要切换到使用不同类型语法的工具,例如LL语法。

总体而言,lex / yacc系列工具通常比最近到达的工具更为简陋,这些工具通常具有复杂的用户界面,可以图形化地显示语法和语法冲突,甚至可以通过自动重构来解决冲突。

所以,如果您之前没有使用过任何解析器工具的经验,那么无论如何您必须学习新工具,那么您应该考虑其他因素,例如语法和冲突的图形可视化,自动重构,良好的可用性文档,可以输出生成的词法分析器/解析器的语言等等。不要选择任何工具只是因为“这是其他人似乎正在使用的东西”。

以下是我可以考虑使用lex / yacc或flex / bison的一些原因:

  • 开发人员已经熟悉lex / yacc或flex / bison
  • 开发人员对LR / LALR语法最为熟悉和熟悉
  • 开发人员有大量书籍涉及lex / yacc,但没有涵盖其他人的书籍
  • 开发商有一份未来的工作机会,并且被告知lex / yacc技能会增加他被聘用的机会
  • 开发商无法从项目成员/利益相关者那里获得使用其他工具的支持
  • 环境中安装了lex / yacc,由于某种原因,安装其他工具是不可行的

答案 1 :(得分:1)

是否值得学习这些工具将在很大程度上取决于(几乎完全依赖于您编写的解析代码的数量,或者您对该通用订单编写更多代码的兴趣。我已经使用了它们很多,并且找到了它们非常有用。

你使用的工具实际上并没有像你想象的那么多。对于我必须处理的大约95%的投入,彼此之间的差异很小,最好的选择就是我最熟悉和最舒适的选择。

当然,lex和yacc产生(并要求你编写你的行为)C(或C ++)。如果您对它们不满意,那么使用和生成您喜欢的语言(例如Python或Java)的工具无疑将是一个更好的选择。举个例子,我不建议尝试使用这种工具,使用一种你不熟悉或不舒服的语言。特别是,如果您在产生编译器错误的操作中编写代码,那么在跟踪问题时,编译器可能会得到比平常更少的帮助,因此您确实需要熟悉该语言以识别问题关于编译器发现错误的地方的最小提示。

答案 2 :(得分:0)

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

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

基本上,它允许我们指定像“ingroup('GroupA')而不是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,但我确实使用了一个解析器生成器(其名称目前已经逃过了我......)

答案 3 :(得分:0)

我认为,为了支持特定于域的语言,避免创建新语言是一个很好的建议。这将更好地利用您的时间来获取现有语言并使用域功能扩展它。

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

如果有充分的理由使用这些工具,可能是因为他们的遗产。您可能已经拥有需要增强的语言框架,这已经在其中一个工具中实现。您可能也会从大量有关这些旧工具的教程信息中受益,因为没有那么大的语料库可以用于实现语言的更新和更光滑的方式。

答案 4 :(得分:0)

我们的办公室实施了完整的编程语言。我们用它来做。我认为这是一种快速简便的方法来为事物编写解释器。你可以想象使用它们编写几乎任何类型的文本解析器,但很多时候它是A)更容易自己快速编写或B)你需要比它们提供的更多的灵活性。