【问题标题】:Scala: How to combine parser combinators from different objectsScala:如何组合来自不同对象的解析器组合器
【发布时间】:2010-04-16 02:42:43
【问题描述】:

给定一系列实现解析器组合器的对象,我如何组合解析器?由于Parsers.Parser 是一个内部类,而在Scala 中inner classes are bound to the outer object 中,情况变得有些复杂。

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

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-user ML (Problem injecting one parser into another) 上,可能也值得把它放在这里。

【问题讨论】:

    标签: scala parsing parser-combinators


    【解决方案1】:

    快速的答案是使用traits,而不是在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[_] 将解析器引用升级到类级别对您没有任何好处。使用特征可以解决所有内部类问题,因为来自LongChainParser 的Parser[Any] 和ShortChainParser 现在都引用了ExampleParser 对象的内部类。

    【讨论】:

    • 感谢您发布这个问题,当然也感谢您的回答!这正是我想要的。
    猜你喜欢
    • 2020-01-17
    • 1970-01-01
    • 2010-10-06
    • 1970-01-01
    • 1970-01-01
    • 2014-05-24
    • 1970-01-01
    • 2012-10-04
    • 1970-01-01
    相关资源
    最近更新 更多