2017-04-19 23 views
0

我編寫了一個非常簡單的解析器組合器庫,它似乎可以正常工作(https://github.com/mukeshsoni/tinyparsec)。x的值在此處未定義,因此不允許此引用

然後我試着用庫爲json編寫解析器。對於JSON解析器的代碼是在這裏 - https://github.com/mukeshsoni/tinyparsec/blob/master/src/example_parsers/JsonParser.purs

對JSON語法是遞歸 -

data JsonVal 
    = JsonInt Int 
    | JsonString String 
    | JsonBool Boolean 
    | JsonObj (List (Tuple String JsonVal)) 

這意味着解析器JSON對象必須再次調用解析器jsonVal。對於jsonObj解析器的代碼看起來是這樣的 -

jsonValParser 
    = jsonIntParser <|> jsonBoolParser <|> jsonStringParser <|> jsonObjParser 

propValParser :: Parser (Tuple String JsonVal) 
propValParser = do 
    prop <- stringLitParser 
    _ <- symb ":" 
    val <- jsonValParser 
    pure (Tuple prop val) 

listOfPropValParser :: Parser (List (Tuple String JsonVal)) 
listOfPropValParser = sepBy propValParser (symb ",") 


jsonObjParser :: Parser JsonVal 
jsonObjParser = do 
    _ <- symb "{" 
    propValList <- listOfPropValParser 
    _ <- symb "}" 
    pure (JsonObj propValList) 

但是當我嘗試構建它,我得到以下錯誤 - The value of propValParser is undefined here. So this reference is not allowed here

我發現計算器類似的問題,但不明白爲什麼錯誤發生或我應該如何重構我的代碼,以便它能夠處理從jsonValParserpropValParser的遞歸引用。

任何幫助,將不勝感激。

+0

可能重複[「未定義的值,引用不允許」解決方法](http://stackoverflow.com/questions/36984245/undefined-value-reference-not-allowed-workaround) – Prune

+0

可能的,但我認爲代碼看起來不同。此外,我不明白該模式背後的原因不被允許。 –

回答

1

有關類似情況,請參見https://stackoverflow.com/a/36991223/139614 - 您需要使用fix函數,或在解析器前面引入Unit -> ...以打破循環定義。

+0

'fix'有什麼作用?它如何打破這個循環? 爲什麼循環定義是一個問題?我在我的解析器庫中有另一個循環定義的例子(用於定義'many'和'many1'組合器 - https://github.com/mukeshsoni/tinyparsec/blob/master/src/TinyParsec.purs#L80)。爲什麼這不是問題? –

0

我設法通過包裝它用一個空操作,拋出錯誤DO塊內,開始做塊的塊擺脫錯誤 -

listOfPropValParser :: Parser (List (Tuple String JsonVal)) 
listOfPropValParser = do 
    _ <- pure 1 -- does nothing but defer the execution of the second line 
    sepBy propValParser (symb ",") 

必須爲jsonValParser這樣做。

jsonValParser = do 
    _ <- pure 1 
    jsonIntParser <|> jsonBoolParser <|> jsonStringParser <|> jsonObjParser 

這個想法是推遲可能導致循環依賴的代碼的執行。添加的行_ <- pure 1正好如此。我認爲它可能會從做fix相同,或從Data.Lazy做什麼defer

相關問題