私はパーサーコンビネーターが本当に好きですが、関連するテキストの前のテキストを気にしないときにデータを抽出するために思いついたソリューションには満足していません。
金額を取得するには、この小さなパーサーを検討してください。
import scala.util.parsing.combinator._
case class Amount(number: Double, currency: String)
object MyParser extends JavaTokenParsers {
def number = floatingPointNumber ^^ (_.toDouble)
def currency = """\w+""".r ^? ({
case "USD" => "USD"
case "EUR" => "EUR"
}, "Unknown currency code: " + _)
def amount = (number ~ currency) ^^ {
case num ~ curr => Amount(num, curr)
} | currency ~ number ^^ {
case curr ~ num => Amount(num, curr)
}
def junk = """\S+""".r
def amountNested: Parser[Any] = amount | junk ~> amountNested
}
ご覧のとおりAmount
、パーサーに有効なデータで始まる文字列を指定すると、簡単にsを取り戻すことができます。
scala> MyParser.parse(MyParser.amount, "101.41 EUR")
res7: MyParser.ParseResult[Amount] = [1.11] parsed: Amount(101.41,EUR)
scala> MyParser.parse(MyParser.amount, "EUR 102.13")
res8: MyParser.ParseResult[Amount] = [1.11] parsed: Amount(102.13,EUR)
ただし、その前に一致しないテキストがある場合は失敗します。
scala> MyParser.parse(MyParser.amount, "I have 101.41 EUR")
res9: MyParser.ParseResult[Amount] =
[1.2] failure: Unknown currency code: I
I have 101.41 EUR
^
私の解決策はamountNested
パーサーであり、再帰的にを見つけようとしますAmount
。これは機能しますが、次のようになりますParseResult[Any]
。
scala> MyParser.parse(MyParser.amountNested, "I have 101.41 EUR")
res10: MyParser.ParseResult[Any] = [1.18] parsed: Amount(101.41,EUR)
この型情報の喪失(もちろん、パターンマッチングを使用して「取得」できます)は、成功には。が含まれるため、残念ながら思われますAmount
。
"I have 101.41 EUR"
一致するかどうかにかかわらず、入力()を検索し続ける方法はありParser[Any]
ますか?
ScalaDocsを見ると、*
上のメソッドが役立つように見えますが、次のParser
ようなことを試してみると、失敗または無限ループしか発生しません。
def amount2 = ("""\S+""".r *) ~> amount