2

私はパーサーコンビネーターが本当に好きですが、関連するテキストの前のテキストを気にしないときにデータを抽出するために思いついたソリューションには満足していません。

金額を取得するには、この小さなパーサーを検討してください。

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
4

1 に答える 1

1

amountNestedをParser[Amount]と宣言すると、タイプチェックはすべて正常に行われます。

def amountNested: Parser[Amount] = amount | junk ~> amountNested
于 2012-04-03T09:22:44.513 に答える