2012-10-18 20 views
2

爲了紀念Rebol 3開放源代碼any-minute-now (?),我又回到了搞亂它。作爲練習,我試圖用PARSE方言編寫自己的JSON解析器。PARSE方言應該用於基本上關於修改輸入的任務嗎?

既然道格拉斯克羅克福德credits influence of Rebol on his discovery of JSON,我認爲這很容易。除了使用方括號替換大括號並擺脫所有這些逗號之外,僅在字符串上使用LOAD的障礙之一是,當他們想要做相當於SET-WORD!的事實時,他們使用的東西看起來像字符串給Rebol的標記器與後非法流浪冒號:

{ 
    "key one": { 
     "summary": "This is the string content for key one's summary", 
     "value": 7 
    }, 
    "key two": { 
     "summary": "Another actually string, not supposed to be a 'symbol'", 
     "value": 100 
    } 
} 

基本上,我想找到所有的都像"foo bar":的情況下,把它們變成foo-bar:,同時留下了後面沒有冒號單靠匹配報價對。

當我在PARSE中解決這個問題時(我原則上理解的很好,但仍未使用太多),出現了一些問題。但是,主要的是,當你可以逃避代碼並修改解析器下的系列時(特別是在Rebol 3中),有什麼承諾條件?更一般地說,它是「適合這種工作的工具」

這裏是我試過的規則,這似乎爲任務的這部分工作:

any [ 
    ; require a matched pair of quotes & capture series positions before 
    ; and after the first quote, and before the last quote 

    to {"} beforePos: skip startPos: to {"} endPos: skip 

    ; optional colon next (if not there the rest of the next rule is skipped) 

    opt [ 
     {:} 

     ; if we got to this part of the optional match rule, there was a colon. 
     ; we escape to code changing spaces to dashes in the range we captured 

     (
      setWordString: copy/part startPos endPos 
      replace/all setWordString space "-" 
      change startPos setWordString 
     ) 

     ; break back out into the parse dialect, and instead of changing the 
     ; series length out from under the parser we jump it back to the position 
     ; before that first quote that we saw 

     :beforePos 

     ; Now do the removals through a match rule. We know they are there and 
     ; this will not cause this "colon-case" match rule to fail...because we 
     ; saw those two quotes on the first time through! 

     remove [{"}] to {"} remove [{"}] 
    ] 
] 

這樣行不行?在開放代碼中是否有機會詆譭外部解析......如果不是在這種情況下,那麼在一些細微的不同之處呢?

一如既往,任何教誨「它更乾淨/更短/更好的這種方式」建議表示讚賞。

P.S.爲什麼沒有replace/all/part

+0

這不是你要求的,但是如果你還沒有這樣的代碼,請檢查這段代碼:http://reb4.me/r/altjson REBOL <-> Christopher Ross-Gill的JSON轉換器。 – endo64

回答

2

新的關鍵字如change,insertremove應該有助於這種類型的事情。我認爲這種方法的主要缺點是推動系列的延遲問題(我已經看到提到構建新字符串比操縱更快)。

token: [ 
    and [{"} thru {"} any " " ":"] 
    remove {"} copy key to {"} remove {"} remove any " " 
    (key: replace/all key " " "-") 
] 

parse/all json [ 
    any [ 
     to {"} [ 
      and change token key 
      ; next rule here, example: 
      copy new-key thru ":" (probe new-key) 
      | skip 
     ] 
    ] 
] 

這是一個有點令人費解,因爲我似乎無法得到「變化工作,我會期望(行爲就像change,不change/part),但在理論上你應該能夠使其沿着這些線段變短有一個相當乾淨的規則。理想的可能是:

token: [ 
    {"} copy key to {"} skip any " " and ":" 
    (key: replace/all key " " "-") 
] 

parse/all json [ 
    any [ 
     to {"} change token key 
     | thru {"} 
    ] 
] 

編輯:另一種軟糖周圍change -

token: [ 
    and [{"} key: to {"} key.: skip any " " ":"] 
    (key: replace/all copy/part key key. " " "-") 
    remove to ":" insert key 
] 

parse/all json [ 
    any [to {"} [token | skip]] 
] 
+0

+1這回答了一些「這是可能的」部分。潛在的緩慢也是一個好點。雖然我仍然想知道與PARSE簽訂的合同的合法性限制。最簡單的合同是*「不要改變解析器下的輸入」*,但是如果你的輸入是嵌套塊而不是字符串別名可能使得難以承諾。另外:我添加了一個[meta post](http://meta.stackexchange.com/questions/152002/why-do-unknown-language-ids-in-prettification-fall-back-to-guessing-instead-of)關於語法突出顯示編輯我對你的帖子... – HostileFork

+0

我沒有看到改變輸入的問題,本身,我猜如果你希望在某些其他點的值不變,麻煩會。有點像做--'鍵:「鍵」打印大寫鍵「 - 沒有意識到你已經改變了字符串''鍵'指向。我想這取決於你想成爲多麼聰明。 「'和'imo背後的哲學爲更多負責任的多通解析提供了方法,尤其是如果第一遍修改源代碼的話。無論如何,仍然不確定是否抓住了你的問題的本質,想:) – rgchris

+0

同意語法 - 如果它不承認lang-rebol,最好不要着色。 – rgchris

2

另一種方式是考慮解析爲編譯器編譯器EBNF。如果我沒有記錯的R2語法:

copy token [rule] (append output token) 

假設正確的語法,並在字符串中沒有{"}

thru {"} skip copy key to {"} skip 
; we know ":" must be there, no check 
thru {"} copy content to {"} skip 
(append output rejoin[ {"} your-magic-with key {":"} content {"} ]) 

更精確,而不是to,炭的炭:

any space {"} copy key some [ string-char | "\" skip ] {"} 
any space ":" any space {"} copy content any [ string-char | "\" skip ] {"} 
(append output rejoin[ {"} your-magic-with key {":"} content {"} ]) 
; content can be empty -> any, key not -> some 

string-char將是一個字符集,除了{\}{"},語法?

不知道R3仍然是這樣的...: -/

+1

PARSE與EBNF不兼容。相反,它與TDPL語言系列(包括TDPL,GTDPL和PEG)兼容。 – Ladislav

0

既然別人已經回答了parse問題,我會回答PS:

有幾個建議選項從未被添加到replace,主要原因是處理選項有開銷,而且這個函數已經需要一些有趣的優化來處理它已有的選項。一旦我們稍微改進了它的API,我們將嘗試用本機代替該函數。它基本上與reword函數類似,我們直到最近才確定最終的API。對於replace我們還沒有討論過。

/part選項的情況下,它以前根本沒有被任何人提出過,並且在統一現有的內部長度計算時可能會有一些概念上的尷尬。可以有一個有限的/part選項,只是整數而不是偏移參考。如果/part長度優先於內部計算的長度,則可能是最好的。不過,如果我們最終調整了API,那麼可能不需要/part選項。