2015-07-21 48 views
0

使用scala parser combinators我已經解析了一些文本輸入,並創建了一些自己的類型。結果打印罰款。現在我需要通過輸出,我認爲這是一個包含我創建的類型的嵌套結構。我如何去做這件事?
這就是我所說的解析器:Scala解析,如何通過已收集的內容

GMParser1.parseItem(i_inputHard_2) match { 
    case GMParser1.Success(res, _) => 
    println(">" + res + "< of type: " + res.getClass.getSimpleName) 
    case x => 
    println("Could not parse the input string:" + x) 
} 

編輯 我從MsgResponse(O2 Flow|Off)會得到什麼是:

>(MsgResponse~(O2 Flow~Off))< of type: $tilde 

什麼我回來從WthrResponse(Id(Tube 25,Carbon Monoxide)|0.20)是:

>(WthrResponse~IdWithValue(Id(Tube 25,Carbon Monoxide),0.20))< of type: $tilde 

爲了給這個問題的上下文提供一些輸入分析。我會想GET在Id

trait Keeper 
case class Id(leftContents:String,rightContents:String) extends Keeper 

這裏是正在創建Id

def id = "Id(" ~> idContents <~ ")" ^^ { contents => Id(contents._1,contents._2) } 

這裏是解析器全:創建

object GMParser1 extends RegexParsers { 
    override def skipWhitespace = false 
    def number = regex(new Regex("[-+]?(\\d*[.])?\\d+")) 
    def idContents = text ~ ("," ~> text) 
    def id = "Id(" ~> idContents <~ ")" ^^ { contents => Id(contents._1,contents._2) } 
    def text = """[A-Za-z0-9* ]+""".r 
    def wholeWord = """[A-Za-z]+""".r 
    def idBracketContents = id ~ ("|" ~> number) ^^ { contents => IdWithValue(contents._1,contents._2) } 
    def nonIdBracketContents = text ~ ("|" ~> text) 
    def bracketContents = idBracketContents | nonIdBracketContents 
    def outerBrackets = "(" ~> bracketContents <~ ")" 
    def target = wholeWord ~ outerBrackets 
    def parseItem(str: String): ParseResult[Any] = parse(target, str) 

    trait Keeper 
    case class Id(leftContents:String,rightContents:String) extends Keeper 
    case class IdWithValue(leftContents:Id,numberContents:String) extends Keeper 
} 
+1

結果似乎沒有包含任何「Id」,所以似乎沒有任何可以解決的問題。也許'id'規則從來沒有被調用過(或者它從未在給定的輸入中成功),或者你拋棄了它的結果,無論哪個規則調用'id'。 – sepp2k

+0

我在想,當映射(^^)完成時,'Id'將被放入輸出中。我只是把整個解析器放在一起,以防你可以看到我丟棄的地方。我可以解決這個問題,它甚至可能是最好的方式(但不會像'var'那樣需要使用'var'),因爲它們在創建時會存儲'Id'等內容。 –

+1

你的意見是什麼?它看起來好像不符合'idBracketContents'規則,而是進入'nonIdBracketContents'規則。 – sepp2k

回答

1

分析器由~運算符產生一個值爲~的案例類。爲了獲得它的內容,你可以像在任何其他案例類一樣對它進行模式匹配(記住它的名字是符號的,所以它用中綴)。

所以,你可以用case GMParser1.Success(functionName ~ argument) => ...替代case GMParser1.Success(res, _) => ...得到的函數名和參數(或任何的wholeWordbracketContentswholeWord "(" bracketContents ")"的語義)。然後,您可以類似地使用嵌套模式來獲取參數的各個部分。

您可以(也可能應該)在規則中同時使用^^和模式匹配來創建更有意義的AST結構,該結構不包含~。例如,將nonIdBracketContents結果與bracketContents結果區分開來會很有用。

+0

目前,或者直到我變得更加純粹的功能性,我將會繼續保留'Id'或其他任何* in-situ *的想法。我已經完成了模式匹配,那麼爲什麼又要這樣做呢? (爲什麼我首先問你可能會說!)。很好地知道正確處理產出的一個很好的例子/參考。到目前爲止,我所見過的大多數文檔都只關注解析。 –

+0

@ChrisMurphy創建自己的數據類型而不是'〜'的好處是,你可以區分'nonIdBracketContents'和'bracketContents',而不必深入內部查看是否存在任何'IdWithValue's 。而在更復雜的語法中,如果僅使用'〜',則可能會出現無法區分不同規則的結果的情況。至於處理「恰當」的輸出,這完全取決於你想用它做什麼。 – sepp2k

+0

輸出我的意思是從第一個lexing階段輸出。 '〜'是否真的包含了整個解析樹?人們通常會在'〜'裏面看看,或者做我所做的事情(現在用FastParse),並且只需要使用地圖功能來創建你想要看到的內容。 –