使用 andThen 组合解析器以创建另一个不同类型的解析器
Combining a Parser using andThen to create another Parser of different type
我正在尝试使用组合器解析器将数据解析为 return
解析器[java.util.Date]
我分两个阶段进行,首先,我使用 simpleYear 解析年份
解析器,然后我尝试将这个简单解析器的结果插入到
然后,我将操纵此输入作为此 andThen 的输出
一个 ParseResult[日期]:
遗憾的是,编译器在声明行出现以下错误:
type mismatch; found :
parser.DateParser.Input ⇒ parser.DateParser.ParseResult[java.util.Date] (which
expands to)
scala.util.parsing.input.Reader[Char] ⇒ parser.DateParser.ParseResult[java.util. required: parser.DateParser.Parser[java.util.Date]
代码如下:
object DateParser extends RegexParsers {
val formatter: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
def year = """\d{4}""".r
def month: Parser[String] =
def day = """[0-2]\d""".r | """3[01]""".r
def month = """0\d""".r | """1[0-2]""".r
def simpleDate: Parser[String] =
(year ~ "-" ~ month ~ "-" ~ day) ^^
{ case y ~ "-" ~ m ~ "-" ~ d => y + "-" + m + "-" + d }
def date: Parser[Date] = simpleDate andThen {
case Success(s, in) =>
val x: ParseResult[Date] = try {
Success(formatter.parse(s), in)
} catch {
case pe: ParseException => Failure("date format invalid", in)
}
x
case f: Failure => f
}
}
似乎scala编译器不能自己做隐式转换
将日期类型转换为 Parser[Date](可能是因为 try/catch?)
有没有其他方法可以做我想做的事?
Parser[T]
是函数 Input => ParseResult[T]
的子类,您使用的方法 andThen
来自该函数。您正在向它传递一个函数 ParseResult[String] => ParseResult[Date]
,因此您返回 Input => ParseResult[Date]
,它与类型 Parser[Date]
不匹配,这就是您收到此错误的原因。
但是您可以简单地将类型为 Input => ParseResult[T]
的函数包装在 Parser
方法中以获得 Parser[T]
。所以你可以这样定义date
:
def date: Parser[Date] = Parser(simpleDate andThen {
// Cleaned up `Success` case a bit
case Success(s, in) =>
try Success(formatter.parse(s), in)
catch {
case pe: ParseException => Failure("date format invalid", in)
}
// It's better to use `NoSuccess` instead of `Failure`,
// to cover the `Error` case as well.
case f: NoSuccess => f
})
也就是说,这不是 best/cleanest 方法。当您想调用解析器结果上的函数以某种方式修改它时,您可以使用 Parser
的方法 map
和 flatMap
或它们的等效方法(map
等效于^^
、flatMap
等同于into
和>>
)。这些与其他 Scala 类 的 map
和 flatMap
具有相同的想法,例如 Try
或 Future
.
在这种情况下你必须考虑失败的可能性,所以你必须使用flatMap
。 date
使用 flatMap
的定义可能如下所示:
def date: Parser[Date] = simpleDate >> (s =>
try success(formatter.parse(s))
catch { case pe: ParseException => failure("date format invalid") })
此外,您可能希望(如果您自己还没有这样做的话)将 formatter
设置为非宽松的:formatter.setLenient(false)
。否则它会做一些事情,比如将 2000-02-31
解析为 3 月 2 日!
我正在尝试使用组合器解析器将数据解析为 return 解析器[java.util.Date]
我分两个阶段进行,首先,我使用 simpleYear 解析年份 解析器,然后我尝试将这个简单解析器的结果插入到 然后,我将操纵此输入作为此 andThen 的输出 一个 ParseResult[日期]:
遗憾的是,编译器在声明行出现以下错误:
type mismatch; found :
parser.DateParser.Input ⇒ parser.DateParser.ParseResult[java.util.Date] (which
expands to)
scala.util.parsing.input.Reader[Char] ⇒ parser.DateParser.ParseResult[java.util. required: parser.DateParser.Parser[java.util.Date]
代码如下:
object DateParser extends RegexParsers {
val formatter: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
def year = """\d{4}""".r
def month: Parser[String] =
def day = """[0-2]\d""".r | """3[01]""".r
def month = """0\d""".r | """1[0-2]""".r
def simpleDate: Parser[String] =
(year ~ "-" ~ month ~ "-" ~ day) ^^
{ case y ~ "-" ~ m ~ "-" ~ d => y + "-" + m + "-" + d }
def date: Parser[Date] = simpleDate andThen {
case Success(s, in) =>
val x: ParseResult[Date] = try {
Success(formatter.parse(s), in)
} catch {
case pe: ParseException => Failure("date format invalid", in)
}
x
case f: Failure => f
}
}
似乎scala编译器不能自己做隐式转换 将日期类型转换为 Parser[Date](可能是因为 try/catch?)
有没有其他方法可以做我想做的事?
Parser[T]
是函数 Input => ParseResult[T]
的子类,您使用的方法 andThen
来自该函数。您正在向它传递一个函数 ParseResult[String] => ParseResult[Date]
,因此您返回 Input => ParseResult[Date]
,它与类型 Parser[Date]
不匹配,这就是您收到此错误的原因。
但是您可以简单地将类型为 Input => ParseResult[T]
的函数包装在 Parser
方法中以获得 Parser[T]
。所以你可以这样定义date
:
def date: Parser[Date] = Parser(simpleDate andThen {
// Cleaned up `Success` case a bit
case Success(s, in) =>
try Success(formatter.parse(s), in)
catch {
case pe: ParseException => Failure("date format invalid", in)
}
// It's better to use `NoSuccess` instead of `Failure`,
// to cover the `Error` case as well.
case f: NoSuccess => f
})
也就是说,这不是 best/cleanest 方法。当您想调用解析器结果上的函数以某种方式修改它时,您可以使用 Parser
的方法 map
和 flatMap
或它们的等效方法(map
等效于^^
、flatMap
等同于into
和>>
)。这些与其他 Scala 类 的 map
和 flatMap
具有相同的想法,例如 Try
或 Future
.
在这种情况下你必须考虑失败的可能性,所以你必须使用flatMap
。 date
使用 flatMap
的定义可能如下所示:
def date: Parser[Date] = simpleDate >> (s =>
try success(formatter.parse(s))
catch { case pe: ParseException => failure("date format invalid") })
此外,您可能希望(如果您自己还没有这样做的话)将 formatter
设置为非宽松的:formatter.setLenient(false)
。否则它会做一些事情,比如将 2000-02-31
解析为 3 月 2 日!