Questions tagged «parser-combinator»

4
何时使用解析器组合器?何时使用解析器生成器?
最近,我想深入了解解析器领域,希望创建自己的编程语言。 但是,我发现存在两种不同的编写解析器的方法:解析器生成器和解析器组合器。 有趣的是,我找不到任何可以解释哪种资源更好的资源。相反,我查询的许多资源(和人员)都不知道另一种方法,只是将其方法解释为该方法,而根本没有提及另一种方法: 在著名的龙书进入词法/扫描,并提到(F)法,但都没有提到解析器组合。 语言实现模式在很大程度上依赖于Java内置的ANTLR解析器生成器,根本没有提到解析器组合器。 Parsec上的Parsec 简介教程(是Haskell中的Parser Combinator)根本没有提到Parser Generators。 Boost :: spirit(最著名的C ++解析器组合器)根本没有提到解析器生成器。 很棒的说明性博客文章“ 您可能已经发明了解析器组合器”根本没有提到解析器生成器。 简单概述: 解析器生成器 解析器生成器获取用DSL编写的文件,该文件是Extended Backus-Naur形式的某种方言,并将其转换为源代码,然后可以(在编译时)成为该DSL中描述的输入语言的解析器。 这意味着编译过程分为两个单独的步骤。有趣的是,解析器生成器本身也是编译器(其中许多确实是自托管的)。 解析器组合器 解析器组合器描述了称为解析器的简单函数,这些函数均将输入作为参数,如果匹配则尝试提取此输入的第一个字符。它们返回一个元组(result, rest_of_input),如果解析器无法解析此输入中的任何内容,则该字段result可能为空(例如nil或Nothing)。一个例子是digit解析器。其他解析器当然可以将解析器作为第一个参数(最后一个参数仍保留在输入字符串中)来组合它们:例如,many1尝试尽可能多地匹配另一个解析器(但至少要匹配一次,否则它本身会失败)。 现在,您当然可以结合(组成)digit和many1创建新的解析器,例如integer。 同样,choice可以编写一个更高级别的解析器,该解析器获取解析器列表,依次尝试每个解析器。 这样,可以构建非常复杂的词法分析器/解析器。在支持运算符重载的语言中,这看起来也很像EBNF,尽管它仍然是直接用目标语言编写的(并且您可以使用所需的目标语言的所有功能)。 简单差异 语言: 解析器生成器使用EBNF-ish DSL和这些语句匹配时应生成的代码的组合编写。 解析器组合器直接以目标语言编写。 乐兴/解析: 解析器生成器在“词法分析器”(将字符串拆分成可能被标记以表明我们正在处理的值的标记)与“解析器”(从词法分析器获取标记的输出列表)之间有非常明显的区别并尝试将它们组合起来,形成一个抽象语法树)。 解析器组合器不需要/不需要这种区别;通常,简单的解析器执行“词法分析器”的工作,而更高级别的解析器将这些更简单的解析器称为确定要创建哪种AST节点。 题 但是,即使存在这些差异(这是差异列表,可能还远远不够!),我仍无法就何时使用哪一个做出明智的选择。我看不出这些差异的含义/后果。 哪些问题属性表明使用Parser Generator可以更好地解决问题?哪些问题属性表明使用Parser Combinator可以更好地解决问题?

5
解析器组合器是否将单独的解析和词法传递为良好实践?
当我开始使用解析器组合器时,我的第一个反应是从感觉上像是在解析和词法化之间的人为区别中解放出来。突然所有的一切都只是解析! 但是,我最近在codereview.stackexchange上发现了此帖子,说明有人在恢复这种区别。起初我以为这对他们很愚蠢,但是后来Parsec中存在支持这种行为的功能这一事实使我开始质疑自己。 在解析器组合器中对已经词法化的流进行解析有什么优点/缺点?
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.