В качестве альтернативы решению pme вы можете попробовать использовать модуль комбинаторов синтаксического анализатора .
Во-первых, вам нужно добавить его как зависимость, так как дополнительные функции были перемещены в отдельныемодули:
libraryDependencies += "org.scala-lang.modules" %% "scala-parser-combinators" % "1.1.2"
Тогда вы можете подготовить парсер:
import java.time.format.DateTimeFormatter;
import java.time._
import scala.util.parsing.combinator._
val r = "[[0_busswvan, 24.0, 2019-09-05 20:15:33],[05f9acb08d7c11e89e8fede614b72917, 20.0, 2019-09-05 14:06:32], [0_h2qbu9h3, 28.0, 2019-09-05 14:01:20],[2_busswvan, 24.0, 2019-09-05 20:15:33],[05f9acb08d7c11e89e8fede614b72917, 25.0, 2019-08-12 14:06:32], [1442qbu9h3, 28.0, 2019-09-05 14:01:20]]"
object Parser extends RegexParsers {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
def text: Parser[String] = """\w+""".r //parser for text
def number: Parser[Double] = """\d+(\.\d*)?""".r ^^ { _.toDouble } //parser for numbers
def datetime: Parser[LocalDateTime] = """\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}""".r ^^ { p => LocalDateTime.from(formatter.parse(p)) } //parser for date
def glue: Parser[String] = """\w*,\w*""".r //parser for comma separators
def term : Parser[List[Any]] = "[" ~ text ~ ", " ~ number ~ ", " ~ datetime ~ "]" ~ opt(glue) ^^ { //parser for matching whole sublist
case _ ~ text ~ _ ~ number ~ _ ~ datetime ~ _ ~ _ => {
List(text, number, datetime)
}
}
def expr : Parser[List[List[Any]]] = "[" ~> rep(term) <~ "]" //parser for whole list containing arbitrary number of sublist
def apply(input: String): List[Any] = parseAll(expr, input) match {
case Success(result, _) => result
case failure : NoSuccess => scala.sys.error(failure.msg)
}
}
println(Parser(r))
//List(List(0_busswvan, 24.0, 2019-09-05T20:15:33), List(05f9acb08d7c11e89e8fede614b72917, 20.0, 2019-09-05T14:06:32), List(0_h2qbu9h3, 28.0, 2019-09-05T14:01:20), List(2_busswvan, 24.0, 2019-09-05T20:15:33), List(05f9acb08d7c11e89e8fede614b72917, 25.0, 2019-08-12T14:06:32), List(1442qbu9h3, 28.0, 2019-09-05T14:01:20))
Также существует проблема с вашим подходом, когда вы используете List
для хранения значениядля Double, String и LocalDateTime компилятор расширяет тип списка до List[Any]
. Вы можете рассмотреть возможность использования кортежа (String, Double, LocalDateTime)
. В этом случае парсер становится:
import java.time.format.DateTimeFormatter;
import java.time._
import scala.util.parsing.combinator._
val r = "[[0_busswvan, 24.0, 2019-09-05 20:15:33],[05f9acb08d7c11e89e8fede614b72917, 20.0, 2019-09-05 14:06:32], [0_h2qbu9h3, 28.0, 2019-09-05 14:01:20],[2_busswvan, 24.0, 2019-09-05 20:15:33],[05f9acb08d7c11e89e8fede614b72917, 25.0, 2019-08-12 14:06:32], [1442qbu9h3, 28.0, 2019-09-05 14:01:20]]"
object Parser extends RegexParsers {
val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss")
def text: Parser[String] = """\w+""".r //parser for text
def number: Parser[Double] = """\d+(\.\d*)?""".r ^^ { _.toDouble } //parser for numbers
def datetime: Parser[LocalDateTime] = """\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}""".r ^^ { p => LocalDateTime.from(formatter.parse(p)) } //parser for date
def glue: Parser[String] = """\w*,\w*""".r //parser for comma separators
def term : Parser[(String, Double, LocalDateTime)] = "[" ~ text ~ ", " ~ number ~ ", " ~ datetime ~ "]" ~ opt(glue) ^^ { //parser for matching whole sublist
case _ ~ text ~ _ ~ number ~ _ ~ datetime ~ _ ~ _ => {
(text, number, datetime)
}
}
def expr : Parser[List[(String, Double, LocalDateTime)]] = "[" ~> rep(term) <~ "]" //parser for whole list containing arbitrary number of sublist
def apply(input: String): List[Any] = parseAll(expr, input) match {
case Success(result, _) => result
case failure : NoSuccess => scala.sys.error(failure.msg)
}
}
println(Parser(r))
//List((0_busswvan,24.0,2019-09-05T20:15:33), (05f9acb08d7c11e89e8fede614b72917,20.0,2019-09-05T14:06:32), (0_h2qbu9h3,28.0,2019-09-05T14:01:20), (2_busswvan,24.0,2019-09-05T20:15:33), (05f9acb08d7c11e89e8fede614b72917,25.0,2019-08-12T14:06:32), (1442qbu9h3,28.0,2019-09-05T14:01:20))