Использование Keep-Left/ Right комбинатор не работает с конвертером результатов
У меня есть комбинатор и конвертер результатов, который выглядит так:
// 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
не важны для моего конвертера результатов, я надеялся, что смогу использовать <~
а также ~>
в правильных местах в моем комбинаторе, так что мой конвертер не должен иметь с ними дело. В качестве эксперимента я изменил первый ~
в парсере к <~ и убрал ~ _
где "стрелка" будет соответствовать в 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 ответ
Так как вы не вставили никаких скобок в цепочку ~
а также <~
большинство подходящих подвыражений выбрасывается "с водой в ванне" (или, скорее, "с пробелами и стрелками"). Просто вставьте несколько скобок.
Вот общая схема, как она должна выглядеть:
(irrelevant ~> irrelevant ~> RELEVANT <~ irrelevant <~ irrelevant) ~
(irrelevant ~> RELEVANT <~ irrelevant <~ irrelevant) ~
...
т. е. каждое "соответствующее" подвыражение окружено несущественным материалом и парой скобок, а затем заключенные в скобки подвыражения связаны ~
"S.
Ваш пример:
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()))