2

私は Scala の Parser ライブラリをいじっています。長さが指定され、その後にその長さのメッセージが続く形式のパーサーを作成しようとしています。例えば:

x.parseAll(x.message, "5helloworld") // result: "hello", remaining: "world"

コンビネータを使用してこれを行う方法がわかりません。私の心は最初に行きます:

def message = length ~ body

しかし、明らかに体は長さに依存し、それを行う方法がわかりません:p

代わりに、メッセージ パーサーを 1 つのパーサー (パーサーの組み合わせではなく) として定義するだけで済みます。

とにかく、私はスカラ初心者です。これは素晴らしいと思います:)

4

3 に答える 3

4

intoそのため、またはその略語を使用する必要があります>>

scala> object T extends RegexParsers {
     |   def length: Parser[String] = """\d+""".r
     |   def message: Parser[String] = length >> { length => """\w{%d}""".format(length.toInt).r }
     | }
defined module T

scala> T.parseAll(T.message, "5helloworld")
res0: T.ParseResult[String] =
[1.7] failure: string matching regex `\z' expected but `w' found

5helloworld
      ^

scala> T.parse(T.message, "5helloworld")
res1: T.ParseResult[String] = [1.7] parsed: hello

使用する際は優先順位に注意してください。たとえば、上記の関数の後に「〜の残り」を追加すると、Scala はそれをlength >> ({ length => ...} ~ remainder)ではなくとして解釈し(length >> { length => ...}) ~ remainderます。

于 2011-06-11T18:58:22.070 に答える
2

これは文脈自由言語とは思えないため、 flatMap を使用する必要があります。

def message = length.flatMap(l => bodyOfLength(n))

ここで、長さは Parser[Int] 型で、bodyOfLength(n) は次のように repN に基づきます。

def bodyWithLength(n: Int) : Parser[String] 
  = repN(n, elem("any", _ => true)) ^^ {_.mkString}
于 2011-06-11T15:35:40.940 に答える
1

私はこの目的のためにpasrerコンビネータを使用しません。しかし、そうしなければならない場合、または問題がより複雑になった場合は、これを試すことができます。

def times(x :Long,what:String) : Parser[Any] = x match {
case 1 => what;
case x => what~times(x-1,what);
}

何かを残したい場合は、parseAllを使用しないでください。parseを使用してください。長さを解析し、結果を可変フィールドx(私は醜いですが、ここでは便利です)に格納し、本体をx回解析すると、文字列が解析され、残りはパーサーに残ります。

于 2011-06-11T15:54:26.283 に答える