2011-12-30 12 views
3

Scalasパーサーのコンビネータと再帰的な解析については、少なくとも私の見解では難しい質問があります。親要素というレベル番号に基づく再帰的な構文解析

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

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

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

意味:私は次のようにASTを構築したい。このシナリオでは

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

:私は現在、このようなPL/1の構造を解析することができるはず小さなパーサを構築します子どもたちとつながなければならない。私の世界では、これは何らかの形で再帰的なパーサになるはずですが、私の問題は、どのようにしてサブレベルでのダウンを止めるかを制御する方法です。たとえば、 "3つのサブデータ"レコード構造を解析する場合、それ自身ではないレベル番号、この場合は "3 subData2"を打つと停止する必要があります。

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

ありがとうございます。

よろしくステファン

+0

どのようにレコード構造がであるもののレベルを知っていますか?あなたの例では、それは識別またはレコードのタイプ(tmpとsubData)のどちらかです。いずれにせよ、パーザーは私にはまっすぐに見えるので、うまくいきませんでしたが、あなたが試みたことについてより具体的にできる方が好きです。 –

答えて

3

基本的にはあなたが必要とするすべては(それは別名>>を持っている)Parser.intoあり、それは現在の1の結果に基づいているパーサコンビネータを作成します。

は私がのためのシンプルな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()))) 
+0

ありがとうございました。:) – StefanE

関連する問題