3

Scalas パーサー コンビネーターと再帰的解析に関して、(少なくとも私の見解では) トリッキーな質問があります。私は現在、次のような PL/1 構造を解析できる小さなパーサーを構築しています。

  dcl 1 data,
    3 subData,
      5 tmp char(15),
      5 tmp1 char(15),
    3 subData2,
      5 tmp2 char(10),
      5 tmp3 char(5);

このシナリオでは、次のように AST を作成します。

Record(data)  -> (Record(subData),Record(subData2))

  Record(subData) -> (Char(tmp),Char(tmp1))

  Record(subData2) -> (Char(tmp2),Char(tmp3))  

親要素をその子要素に接続する必要があることを意味します。私の世界では、これは何らかの方法で再帰的なパーサーになるはずですが、私の問題は、サブレベルでの下降をいつ停止するかを制御する方法です。たとえば、「3 subdata」レコード構造を解析する場合、それ自体が低くないレベル番号 (この場合は行「3 subData2」) に到達すると停止する必要があります。

誰かがこの問題を手伝ってくれるか、良い方向に向けてくれますか? 私の現在の解決策は、接続されていない構造を解析した後にこの問題を解決することです。

前もって感謝します。

よろしくステファン

4

1 に答える 1

3

基本的に必要なのはParser.into(エイリアスを持っている>>) だけで、現在の結果に基づいたパーサー コンビネーターを作成します。

簡単な REPLable の例を用意しました

import util.parsing.combinator.RegexParsers

case class Record(data: String, children: List[Record])

object RecordParser extends RegexParsers {
  override def skipWhitespace = false

  def ws = "\\s*".r
  def numberGT(min: Int) = "\\d+".r ^^ {  _.toInt } ^? {
    case i if i > min => i
  }

  def subData(n: Int): Parser[Record] = ws ~> numberGT(n) ~ ws ~ ".*".r <~ "\n" >> {
    case sub ~ _ ~ data => rep(subData(sub)) ^^ { new Record(data, _) }
  }
}

val testData = """
1 data
 2 subdata
  3 child1
  3 child2
 2 sub2
"""

RecordParser.parse(RecordParser.subData(0),test)
res7: RecordParser.ParseResult[Record] = [7.1] parsed: Record(data,List(Record(subdata,List(Record(child1,List()), Record(child2,List()))), Record(sub2,List())))
于 2011-12-30T12:04:32.847 に答える