Scala 将自定义标记器与解析器子类连接

Scala 将自定义标记器与解析器子类连接,scala,parsing,Scala,Parsing,我很难理解当您已经有一个令牌列表(不是字符)时,scala解析器combinator api应该如何使用。我已经查看了令牌解析器的源代码,但是我无法理解“词法”成员是什么,以及如何插入自己的阅读器实现(或者以另一种方式让解析器使用令牌) 在线提供的示例(以及Odersky等人的“Scala编程”一书)没有说明如何将api与非字符标记一起使用。一些示例表明,解析器的子类必须将elem参数设置为令牌的类型,但是令牌来自哪里?Reader[MyToken]输入参数在哪里 只是想澄清一下:词法分析已经完

我很难理解当您已经有一个令牌列表(不是字符)时,scala解析器combinator api应该如何使用。我已经查看了令牌解析器的源代码,但是我无法理解“词法”成员是什么,以及如何插入自己的阅读器实现(或者以另一种方式让解析器使用令牌)

在线提供的示例(以及Odersky等人的“Scala编程”一书)没有说明如何将api与非字符标记一起使用。一些示例表明,解析器的子类必须将elem参数设置为令牌的类型,但是令牌来自哪里?Reader[MyToken]输入参数在哪里

只是想澄清一下:词法分析已经完成了。删除空格、分隔符,所有这些都已经完成了。我有一个令牌列表,只想使用解析器组合器niceness创建一个AST。标记看起来有点像这样:

sealed abstract class MyToken {
  val line : Int
  val col : Int
}
case class LPAREN ( line : Int, col : Int ) extends MyToken
case class RPAREN ( line : Int, col : Int ) extends MyToken

等等。

我终于明白了。phrase()方法接受一个Reader参数,因此我可以包装我的令牌流并调用它

class MyParsers extends Parsers {
  type Elem = MyToken

  def parse(tokens: Iterable[MyToken]): ParseResult[Any] = {
    val reader = new MyReader(tokens)
    phrase(myGrammarRule)(reader)
  }

  // ...etc...
}

sealed class MyReader(tokens : Iterable[MyToken]) extends Reader[MyToken] {
  def pos : Position = tokens.head
  def atEnd : Boolean = tokens.isEmpty
  def rest : Reader[MyToken] = new MyReader(tokens.tail)
  def first : MyToken = tokens.head
}

sealed abstract class MyToken extends Position {
  val _line : Int
  val _col : Int

  override def column = _col
  override def line = _line
  override def lineContents = ""
}

case class LPAREN ( _line : Int, _col : Int ) extends MyToken
case class RPAREN ( _line : Int, _col : Int ) extends MyToken

位置mixin很好,因为它允许解析器使用令牌中已经存在的位置信息,而无需添加任何胶水。

Hm,我想如果我也实现lineContents(),我将从解析器获得更好的诊断消息。感谢这个好例子。我自己一直在破解一个自定义令牌解析器,但您的代码更干净:)