x的值在此处未定义,因此不允许使用此引用

时间:2017-04-19 10:22:05

标签: parsing recursion purescript

我写了一个非常简单的解析器组合库,它似乎正常工作(https://github.com/mukeshsoni/tinyparsec)。

然后我尝试用json为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

我在stackoverflow上发现了类似的问题但是无法理解错误发生的原因或者我应该如何重构我的代码以便它处理从jsonValParserpropValParser的递归引用。

任何帮助都将不胜感激。

2 个答案:

答案 0 :(得分:1)

有关类似情况,请参阅https://stackoverflow.com/a/36991223/139614 - 您需要使用fix函数,或在某个解析器前面引入Unit -> ...以打破循环定义。< / p>

答案 1 :(得分:0)

我设法通过在do块中包含抛出错误的块并用noop启动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的{​​{1}}或来自Data.Fix的{​​{1}}做同样的事情。