2014-02-28 40 views
0

我正在寫一個解析器的Scala爲以下語法:解析器接受Scala中的任何字符串?

expr := "<" anyString ">" "<" anyString ">" 
anyString := // any string 

例如,"<foo> <bar>"是一個有效的字符串,如"<http://www.example.com/example> <123>",並"<1> <_hello>"

到目前爲止,我有以下幾點:

object MyParser extends JavaTokenParsers { 

    override def skipWhitespace = false 

    def expr: Parser[Any] = "<" ~ anyString ~ ">" ~ whiteSpace ~ "<" ~ anyString ~ ">" 

    def anyString = ??? 

} 

我的問題如下(我已經包括了我的疑似答案,但無論如何請確認,如果我沒錯的話):

  1. 如何實現接受任何字符串的正則表達式解析器?這必須有一個幾乎微不足道的答案,如def anyString = """\a*""".r,其中\a是代表任何字符的符號(儘管\a可能不是我正在尋找的droid)。

  2. 如果我設置anyString接受任何字符串,它會在>符號之前停止,還是會運行直到字符串結束並失敗?我相信它會一直運行直到字符串結束並失敗,然後它最終會找到>並消耗到那裏。這似乎導致非常低效的解析器,並且對此的任何評論將不勝感激!

  3. 如果有什麼內<>字符串中包含>符號(例如<fo>o> <bar>)?將anyString消耗到第一個>還是最後一個?有沒有什麼方法可以指定它是否消耗最少或最多?

  4. 爲了解決上述問題,我想禁止<>anyString。如何寫這個?

謝謝!

回答

0

我目前正在研究自己的問題,我會盡力在這裏回答我自己。

  1. Java的Patterndocumentation指定.任何字符匹配。因此,它接受任何字符串正則表達式是:

    def anyString = ".*".r 
    

    接受任何非空字符串,我們可以使用".+".r

  2. 要理解這一點,考慮下面的玩具例子:

    object MyParser1 { 
        override def skipWhitespace = false 
        def expr = "<" ~ anyString ~ ">" 
        def anyString = ".*".r 
    } 
    

    這裏,串<>拒絕。爲了測試這一點,使用:

    println( MyParser1.parseAll(MyParser1.expr, "<>") ) 
    

    這表明.*解析器消耗直到串,由此>不適用於最終的解析器的端部。因此,似乎有必要禁止在anyString中出現<>表單。

  3. 如前面一點,.*解析器消耗整個字符串,因此消耗所有>符號。

  4. 在同一文檔中給出否定運算符。爲了排除<>,我們可以這樣寫:

    def almostAnyString = "[^<>]*".r 
    

    一般來說,結構[^abc]將任何字符匹配除了abc

總之,到目前爲止,我已經找到了最好的實現如下:

object MyParser extends JavaTokenParsers { 
    override def skipWhitespace = false // don't allow whitespace between parsers by default 

    def expr: Parser[Any] = "<" ~ almostAnyString ~ ">" ~ 
          whiteSpace ~ // this parser is defined in JavaTokenParsers 
          "<" ~ almostAnyString ~ ">" 

    def almostAnyString = "[^<>]*".r 

} 
+0

你並不真的需要禁止'<',你呢?問題是,你需要'< c <- d >'被接受嗎? –