我一直試圖做一個解析器一個非常簡單的語言,它看起來像這樣的Scala解析器組合(幾乎)瑣碎的語法
.*?[^ ]*?\\{
.*?\\}
這將基本上保持吃字符,直到它找到匹配[^ ]*?\\{
或\\}
的東西:塊的開始或結束。我的問題是,如果我想使用Scala的Parser Combinators來做它,我該怎麼做?我目前有:
def expr: Parser[Any] = (block | text)+
def text = ".+?".r
def block = "[^ ]*?\\{".r ~ expr ~ "}"
但這不起作用:
parsed: List(b, l, o, c, k, {, y, o, u, a, r, e, a, c, o, w, t, o, o, b, l, k, A, {, b, u, t, m, a, y, b, e, n, o, t, }, a, n, d, s, o, i, s, h, e, }, h, e, a, r, m, e, m, o, o)
看來,block
解析器不點火,所以text
分析器被反覆觸發。但是當我刪除text
解析器:
def expr: Parser[Any] = (block)+
我得到:
failure: string matching regex `[^ ]*?\{' expected but `y' found
block{you are a cow too blkA{ but maybe not} and so is he} hear me moo
^
如此明顯的block
解析器確實工作,除了沒有當text
解析器是存在的。發生了什麼?有沒有一種「適當」的方式來做到這一點,因爲這麼基礎的語法?
編輯:改變了標題,因爲它不是這麼多的不情願了,因爲只是解決問題
編輯:我現在有這樣的:
def expr: Parser[Any] = (block | text)+
def text = "[^\\}]".r
def block = "[^ ]*?\\{".r ~ expr ~ "}"
這背後的邏輯是,每個字符,它測試它是否是塊的開始。如果不是,則轉到下一個字符。這給我:
parsed: List(((block{~List(y, o, u, a, r, e, a, c, o, w, t, o, o, ((blkA{~List(b, u, t, m, a, y, b, e, n, o, t))~}), a, n, d, s, o, i, s, h, e))~}), h, e, a, r, m, e, m, o, o)
這是正確的。它一個接一個地解析非塊字符,這可能是一個性能問題(我認爲?)。有沒有辦法一次解析所有這些非塊字符並將它們放在一個大字符串中?
請不要將新問題添加到現有的問題。當然可以加強,但爲新問題提出新問題。因爲你使用了一個非貪婪的星星,所以它是一個接一個的解析。只要放棄非貪婪。 – 2012-02-01 14:20:45