Scala:如何组合来自不同对象的解析器组合器 [英] Scala: How to combine parser combinators from different objects

查看:78
本文介绍了Scala:如何组合来自不同对象的解析器组合器的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

给定一个实现解析器组合器的对象家族,我如何组合解析器?由于 Parsers.Parser 是一个内部类,在Scala中,内部类绑定到外部对象 ,故事变得有些复杂.

Given a family of objects that implement parser combinators, how do I combine the parsers? Since Parsers.Parser is an inner class, and in Scala inner classes are bound to the outer object, the story becomes slightly complicated.

这是一个示例,试图组合来自不同对象的两个解析器.

Here's an example that attempts to combine two parsers from different objects.

import scala.util.parsing.combinator._

class BinaryParser extends JavaTokenParsers {
  def anyrep: Parser[Any] = rep(any)
  def any: Parser[Any] = zero | one
  def zero: Parser[Any] = "0"
  def one: Parser[Any] = "1"
}

object LongChainParser extends BinaryParser {
  def parser1: Parser[Any] = zero~zero~one~one
}

object ShortChainParser extends BinaryParser {
  def parser2: Parser[Any] = zero~zero
}

object ExampleParser extends BinaryParser {
  def parser: Parser[Any] = (LongChainParser.parser1
    ||| ShortChainParser.parser2) ~ anyrep

  def main(args: Array[String]) {
    println(parseAll(parser, args(0) ))
  }
}

这将导致以下错误:

<console>:11: error: type mismatch;
 found   : ShortChainParser.Parser[Any]
 required: LongChainParser.Parser[?]
         def parser: Parser[Any] = (LongChainParser.parser1 
           ||| ShortChainParser.parser2) ~ anyrep

我已经找到了解决此问题的方法,但是自从提出以来 最近在scala用户ML(将一个解析器注入另一个解析器中),也可能值得将其放在这里.

I've found the solution to this problem already, but since it was brought up recently on scala-user ML (Problem injecting one parser into another), it's probably worth putting it here too.

推荐答案

快速答案是使用trait而不是在object s中托管解析器:

The quick answer is to use the traits instead of hosting the parsers in objects:

import scala.util.parsing.combinator._

trait BinaryParser extends JavaTokenParsers {
  def anyrep: Parser[Any] = rep(any)
  def any: Parser[Any] = zero | one
  def zero: Parser[Any] = "0"
  def one: Parser[Any] = "1"
}

trait LongChainParser extends BinaryParser {
  def parser1: Parser[Any] = zero~zero~one~one
}

trait ShortChainParser extends BinaryParser {
  def parser2: Parser[Any] = zero~zero
}

object ExampleParser extends LongChainParser with ShortChainParser  {
  def parser: Parser[Any] = (parser1 ||| parser2) ~ anyrep

  def main(args: Array[String]) {
    println(parseAll(parser, args(0) ))
  }
}

因为像~|这样的组合运算符是针对内部类编写的,所以说BinaryParser#Parser[_]对您没有任何帮助,从而将解析器引用升级到类级别.使用特征可以解决所有内部类问题,因为LongChainParserShortChainParser中的Parser[Any]现在都引用ExampleParser对象的内部类.

Because the combinator operators like ~ and | are written against the inner class, escalating the parser references to class-level by saying BinaryParser#Parser[_] doesn't do you any good. Using traits solves all that inner-class issues since both Parser[Any] from LongChainParser and ShortChainParser now refer to the inner class of ExampleParser object.

这篇关于Scala:如何组合来自不同对象的解析器组合器的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆