Scala中Regexparsers,StandardToken Parsers和JavaTokenParsers之间的区别

时间:2010-04-30 10:32:27

标签: parsing scala

我正在学习Scala中的Parser Combinators,并且看到了不同的解析方法。我主要看到三种不同类型的解析器,即.gegexpParsers,StandardTokenParsers和JavaTokenParsers。我是解析的新手,并不知道如何选择合适的Parser根据我们的要求。任何人都可以解释这些不同的解析器是如何工作的以及何时使用它们。

2 个答案:

答案 0 :(得分:22)

出于不同的目的,有几种不同的解析器特征和基类。

主要特征是scala.util.parsing.combinator.Parsers。这有大多数主要的组合器,如optrepelemaccept等。绝对查看这个的文档,因为这是你的大部分内容需要知道。实际的Parser类在这里被定义为内部类,这也很重要。

另一个重要特征是scala.util.parsing.combinator.lexical.Scanners。这是解析器读取字符流并生成标记流(也称为词法分析器)的基本特征。为了实现这个特性,你需要实现一个whitespace解析器,它可以读取空格字符,注释等。你还需要实现一个token方法,它读取下一个标记。标记可以是您想要的任何内容,但它们必须是Scanners.Token的子类。 Lexical扩展ScannersStdLexical扩展Lexical。前者提供了一些有用的基本操作(如digitletter),而后者实际上定义和修饰了常见的令牌(如数字文字,标识符,字符串,保留字)。您只需要定义delimitersreserved,就可以获得对大多数语言有用的内容。令牌定义位于scala.util.parsing.combinator.token.StdTokens

一旦你有了词法分析器,就可以定义一个解析器来读取一个令牌流(由词法分子生成)并生成一个抽象语法树。分离词法分析器和解析器是一个好主意,因为您不需要担心语法中的空格或注释或其他复杂性。如果您使用StdLexical,则可以考虑使用内置了解析器的scala.util.parsing.combinator.syntax.StdTokenPasers将令牌转换为值(例如StringLit转换为String)。我不确定与StandardTokenParsers的区别。如果您定义自己的令牌类,那么为简单起见,您应该使用Parsers

您明确询问了RegexParsersJavaTokenParsersRegexParsers是一个特征,它使用一个额外的组合符Parsers扩展regex,这完全符合您的预期。如果要使用正则表达式匹配标记,请将RegexParsers混合到词法分析器中。 JavaTokenParsers提供了一些解析器,它们从Java语法中提取令牌(如标识符,整数)但没有LexicalStdLexical的令牌包。

总而言之,您可能需要两个解析器:一个读取字符并生成标记,另一个使用标记并生成AST。首先使用基于LexicalStdLexical的内容。根据您是否使用Parsers,使用基于StdTokenParsersStdLexical的内容,具体取决于您是否使用{{1}}。

答案 1 :(得分:6)

RegexpParsers允许您使用RE值(通常采用"re pattern".r形式,但同样适用于任何其他Regex实例)。没有预定义的词汇作品(代币)。

JavaTokenParsers定义了Java令牌的词汇制作:decimalNumberfloatingPointNumberstringLiteralwholeNumberident(标识符)。

StandardTokenParsers定义词汇制作“......用于简单的类Scala语言。它解析关键字和标识符,数字文字(整数),字符串和分隔符。”其成分实际上是在StdLexical中定义的。