词法和语法分析器软件

时间:2014-09-01 11:33:11

标签: c++ yacc flex-lexer analyzer lexical

我正在设计一种基于CSS-ish(CSS +自定义扩展)的自定义语言,基本上可以这样工作:

[object.member.value = 5]{
object.member.anothervalue:8 
object.member.yetanothervalue:'hello'
object.member.yetyetanothervalue.anothervalue:blue
}

基本上,语言允许检查某些条件(如果可以嵌套),然后将一些值应用于对象。没有循环。 这将存储在纯文本文件中,并在开始时加载到应用程序(C ++)中。

我的想法是将这个CSS-ish文件转换为C ++树或类似的东西,可以在运行时进行评估

我正在考虑使用一些词法分析器和标记器(Yacc,Flex,Bison等......)。

您对工具/库的使用建议是什么?

3 个答案:

答案 0 :(得分:1)

我会使用带有递归下降解析器的自制扫描程序,因为这是一个非常简单的解析任务,使用解析器生成器会花费更多或更多的时间,然后自己编写解析器。

答案 1 :(得分:1)

您可以查看 Boost Spirit ,它可以让您轻松编写词法分析器(Boost.Lex)和解析器(Boost.Qi)。它有一个有趣的方法,包括直接在C ++代码中定义语法/语法,而不是使用单独的语法文件。它便携,标准,独立,非常优雅。

如果你的语言会演变成更复杂的东西,你可以考虑 Flex和Bison 。他们使用与Lex& amp;相同类型的输入文件。 Yacc,这是他们较旧的Unix等价物。这些工具的优点是有充足的文献资源。不方便的是,他们通过将骨架代码与您在语法文件中提供的部分混合来生成代码。因此,掌握和维护起来更复杂。

但是在你的特殊情况下,你有一个非常简单的语言,只有几个令牌,显然是一个简单的“LL(1)语法”。 (例如,解析器需要提前读取单个标记,以确定它将解析的内容没有歧义)。使用<regex>来简化令牌扫描以及创建与您的语言结构相对应的对象,可以很容易地创建自己的代码,eventuell。

答案 2 :(得分:1)

如果您希望不止一次执行此类操作,请了解如何使用解析器生成器。从长远来看,它会为你带来很多痛苦。

开始简单。这些工具将为您做很多事情,通常只需很少的努力。让他们这样做。在尝试做复杂的事情之前先把事情搞定。

其余部分假设您将使用flexbisonlexyacc相似。)您不必;还有很多选择。如果您决定尝试其他替代方案,请忽略此答案的其余部分。

但是flexbison是包含大量文档的可靠,维护良好,调试良好的软件包,并且已经被广泛使用了很长一段时间。首先阅读文档。

  • flex将自动从标准输入或提供的文件描述符中读取。让它做到这一点。
  • flex会为您跟踪行号。让它做到这一点。
  • bison会自动为您生成令牌号码。让它做到这一点。
  • bisonflex针对单字符令牌进行了优化。您不仅不需要提供令牌号,甚至不需要提供令牌名称。在您的flex文件中,只需将其放在末尾或附近:

    . { return yytext[0]; }
    

    并且不打算编写规则来处理单字符令牌。不要担心你会将非法字符标记出来; bison会为您生成错误消息。

  • 但是,不允许flex插入默认规则。 (%option nodefault足以压制它。)

其他一些提示:

  • 尽管yytext是全球性的,但假装它不是。您必须复制进一步处理所需的任何字符串。 strdup是你的朋友;使用它而不是弄乱mallocstrcpy。也可以使用asprintf; char* out; asprintf(&out, "%s%s%s", s1, s2, s3);是连接三个字符串的最简单方法。对于没有这些东西的平台,可以轻松实现不受限制的实现,因此不要担心“但它们不是Posix / Standard C / yadda yadda yadda”参数。甚至不要考虑固定长度的缓冲区。你不需要它们。诚实。
  • 另一方面,如果可以在扫描仪中处理令牌,请在那里进行处理。数字,例如;在扫描仪中执行strtol一次要容易得多,然后您甚至不需要考虑内存分配。
  • 当你不再需要它们时,不要忘记free()字符串,但是如果你发现那个困难的开始是通过泄漏内存然后在你的解析器工作之后解决问题。 (我知道有些人会发现这种亵渎神灵,但只要你记得在制作之前就这么做,那就没关系;一旦掌握了基础知识,你就会感到更有动力。)

最后:

  • 使用合理的当前版本的bison。如果你发现自己有神秘的转移/减少冲突,请使用glr解析器:是的,它有点慢,但如果它能为你节省一些痛苦,那就值得了。您可以随时返回并解决问题。 (GLR解析器不会让你免于所有语法问题。你仍然需要确保你的语法不明确。但是他们可以提供帮助。)
  • 我的个人建议:使用C界面。用C ++编译是可以的,你可以使用标准的C ++容器和其他不错的功能;只是不要在语义值中使用它们,因为这与bison的内部堆栈管理不能很好地协作。 (但指向C ++容器的指针很好。)请记住,flexbison只是控制流;你的程序的大部分将用C / C ++编写,因此你不会使用编译器工具进入新的世界。你也没有获得免费通行证:在开始编写解析器之前,你需要知道如何使用C / C ++。

希望有所帮助。祝你好运。