Использование Keep-Left / Right комбинатор не работает с конвертером результатов - PullRequest
0 голосов
/ 14 декабря 2018

У меня есть комбинатор и преобразователь результатов, который выглядит следующим образом:

// parses a line like so:
// 
// 2
// 00:00:01.610 --> 00:00:02.620 align:start position:0%
//
private def subtitleHeader: Parser[SubtitleBlock] = {
  (subtitleNumber ~ whiteSpace).? ~>
    time ~ arrow ~ time ~ opt(textLine) ~ eol
} ^^ {
  case
    startTime ~ _ ~ endTime ~ _ ~ _
  => SubtitleBlock(startTime, endTime, List(""))
}

Поскольку arrow, textline и eol не важны для моего преобразователя результатов, я надеялся, чтоможно использовать <~ и ~> в нужных местах моего комбинатора, чтобы мой конвертер не имел с ними дело.В качестве эксперимента я изменил первый ~ в синтаксическом анализаторе на <~ и удалил <code>~ _, где «стрелка» будет сопоставляться в операторе case следующим образом:

private def subtitleHeader: Parser[SubtitleBlock] = {
  (subtitleNumber ~ whiteSpace).? ~>
    time <~ arrow ~ time ~ opt(textLine) ~ eol
} ^^ {
  case
    startTime ~ endTime ~ _ ~ _
  => SubtitleBlock(startTime, endTime, List(""))
}

ОднакоЯ получаю красные кривые в IntelliJ с сообщением об ошибке:

Ошибка: (44, 31) конструктор не может быть создан для ожидаемого типа;найдено: caption.vttdissector.VttParsers. ~ [a, b] обязательно: Int startTime ~ endTime ~ _ ~ _

Что я делаю не так?

1 Ответ

0 голосов
/ 18 декабря 2018

Поскольку вы не вставили никаких скобок в цепочку ~ и <~, большинство подходящих подвыражений выбрасывается «с водой в ванне» (или, скорее, «с пробелами и стрелками»).Просто вставьте несколько скобок.

Вот общая схема, как это должно выглядеть:

(irrelevant ~> irrelevant ~> RELEVANT <~ irrelevant <~ irrelevant) ~
(irrelevant ~> RELEVANT <~ irrelevant <~ irrelevant) ~ 
...

т.е. каждое «соответствующее» подвыражение окружено ненужными вещами и парой скобок, а затемзаключенные в скобки подвыражения связаны с ~.

Ваш пример:

import scala.util.parsing.combinator._
import scala.util.{Either, Left, Right}

case class SubtitleBlock(startTime: String, endTime: String, text: List[String])

object YourParser extends RegexParsers {

  def subtitleHeader: Parser[SubtitleBlock] = {
    (subtitleNumber.? ~> time <~ arrow) ~ 
    time ~
    (opt(textLine) <~ eol)
  } ^^ {
    case startTime ~ endTime ~ _ => SubtitleBlock(startTime, endTime, Nil)
  }

  override val whiteSpace = "[ \t]+".r
  def arrow: Parser[String] = "-->".r
  def subtitleNumber: Parser[String] = "\\d+".r
  def time: Parser[String] = "\\d{2}:\\d{2}:\\d{2}.\\d{3}".r
  def textLine: Parser[String] = ".*".r
  def eol: Parser[String] = "\n".r

  def parseStuff(s: String): scala.util.Either[String, SubtitleBlock] = 
  parseAll(subtitleHeader, s) match {
    case Success(t, _) => scala.util.Right(t)
    case f => scala.util.Left(f.toString)
  } 

  def main(args: Array[String]): Unit = {
    val examples: List[String] = List(
      "2 00:00:01.610 --> 00:00:02.620 align:start position:0%\n"
    ) ++ args.map(_ + "\n")

    for (x <- examples) {
      println(parseStuff(x))
    }
  }
}

находит:

Right(SubtitleBlock(00:00:01.610,00:00:02.620,List()))
...