我正在学习 scala 中的 Parser Combinators 并看到不同的解析方式。我主要看到三种不同类型的解析器,即 RegexpParsers、StandardTokenParsers 和 JavaTokenParsers。我是解析新手,不知道如何根据我们的选择合适的解析器要求。谁能解释一下这些不同的解析器是如何工作的以及何时使用它们。
最佳答案
有几种不同的解析器特征和基类用于不同的目的。
主要特征是scala.util.parsing.combinator.Parsers
.这具有大多数主要组合符,例如 opt
, rep
, elem
, accept
等。一定要查看此文档的文档,因为这是您需要了解的大部分内容。实际Parser
class 在这里被定义为内部类,这也很重要。
另一个重要特征是scala.util.parsing.combinator.lexical.Scanners
.这是读取字符流并生成标记流(也称为词法分析器)的解析器的基本特征。为了实现这个特性,你需要实现一个 whitespace
解析器,它读取空白字符、注释等。您还需要实现 token
方法,它读取下一个 token 。 token 可以是任何你想要的,但它们必须是 Scanners.Token
的子类. Lexical
扩展 Scanners
和 StdLexical
扩展 Lexical
.前者提供了一些有用的基本操作(如 digit
、 letter
),而后者实际定义和词法化常见标记(如数字文字、标识符、字符串、保留字)。您只需定义 delimiters
和 reserved
, 你会得到对大多数语言有用的东西。 token 定义位于 scala.util.parsing.combinator.token.StdTokens
.
一旦有了词法分析器,就可以定义一个解析器,它读取标记流(由词法分析器生成)并生成抽象语法树。分离词法分析器和解析器是一个好主意,因为您无需担心语法中的空格或注释或其他复杂情况。如果您使用 StdLexical
,您可以考虑使用 scala.util.parsing.combinator.syntax.StdTokenPasers
它具有内置的解析器以将标记转换为值(例如, StringLit
到 String
)。我不确定与 StandardTokenParsers
有什么区别.如果您定义自己的 token 类,您应该只使用 Parsers
为简单起见。
您专门询问了RegexParsers
和 JavaTokenParsers
. RegexParsers
是扩展 Parsers
的特征加上一个额外的组合器:regex
,这正是您所期望的。混入RegexParsers
如果您想使用正则表达式来匹配标记,请发送给您的词法分析器。 JavaTokenParsers
提供了一些解析器,它们从 Java 语法(如标识符、整数)中提取标记,但没有 Lexical
的标记包袱。或 StdLexical
.
总而言之,您可能需要两个解析器:一个读取字符并生成标记,另一个获取标记并生成 AST。使用基于 Lexical
的东西或 StdLexical
为了第一。使用基于 Parsers
的东西或 StdTokenParsers
第二个取决于您是否使用 StdLexical
.
关于parsing - Scala中Regex Parsers,Standard TokenParsers和JavaTokenParsers之间的区别,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2743835/