2016-05-02 10 views
2

私はコンパイルエラーメッセージThe value of xyz is undefined here, so reference is not allowed.とdo-notationを明確にしたいと考えています。私は例を十分に一般化することはできませんでした。私が与えることができるのは、この動作を見つけた具体例です。そのために残念。"未定義値、参照が許可されていません"回避策

purescript-parsingを使用して、ネストされた複数行のコメントを受け入れるパーサーを作成します。この例を簡略化するため、各コメントは(で始まり、末尾には)となり、aまたは別のコメントのいずれかを含むことができます。いくつかの例:(a)((a))が受け入れられました。()(aまたはfooが拒否されました。

ラインcontent <- string "a" <|> comment上のエラーThe value of comment is undefined here, so reference is not allowed.に次のコードの結果:私は私の知る限り理解し、それが結果のパーサを変更しないcontent <- string "a" <|> comment上記の行を挿入することで、エラーを取り除くことができます

comment :: Parser String String 
comment = do 
    open <- string "(" 
    content <- commentContent 
    close <- string ")" 
    return $ open ++ content ++ close 

commentContent :: Parser String String 
commentContent = do 
    content <- string "a" <|> comment 
    return content 

commentContent :: Parser String String 
commentContent = do 
    optional (fail "") 
    content <- string "a" <|> comment 
    return content 

質問は次のとおりです:すべての

  • ここに何が起こっていますか?余分なラインはなぜ助けますか?
  • コードをコンパイルするための非ハックな方法は何ですか?手動doをdesugar場合
+0

あなたが遭遇しているエラーコードとこのリンクのwikiページを読んでいますか? https://github.com/Thimoteus/SandScript/wiki/2.-構文解析 - 再帰的に - 余分な行があなたの問題を修正するのは本当に奇妙です。 – stholzm

+0

ありがとうございました、サンスクリプトのテキストは興味深いものでした。エラーについては、なぜ必要なのか分かりますが、余分な行がなぜそれを削除するのか分かりません。そして、余分な行を持つパーサは意図的に動作します。 –

答えて

3

第二ケースが働く理由は、より明らかになった:

commentContent :: Parser String String 
commentContent = 
    optional (fail "") >>= \_ -> 
    string "a" <|> comment >>= \content -> 
     return content 

このように定義すると、comment参照がラムダの内部にあるので、そのための定義時に評価されていませんcommentContentです。

非ハックな解決策については、それは私が想像するところではfixのいくつかの使用を伴います。 pは、あなたが自分自身の中に使用することができますmyParserへの参照がある

myParser = fix \p -> do 
    ... parser definition .... 

fixはあなたのような再帰的なパーサを定義することができます。ここでは、相互に再帰的なパーサーがある場合については、fixで解決するにはどうすればよいか正確にはわかりませんが、いくつかのオプションが考えられますが、特に優雅なものはありません。おそらく、このような何か:

parens :: Parser String String -> Parser String String 
parens p = do 
    open <- string "(" 
    content <- p 
    close <- string ")" 
    return $ open ++ content ++ close 

comment :: Parser String String 
comment = parens commentContent 

commentContent :: Parser String String 
commentContent = fix \p -> do 
    content <- string "a" <|> parens p 
    return content 

Unitの値になるまであなたが再帰的な参照を遅らせることができるように、奇妙なdo場合と同様のトリックを使用してパーサの1の前にUnit ->を挿入する方が簡単かもしれません

comment :: Parser String String 
comment = do 
    open <- string "(" 
    content <- commentContent unit 
    close <- string ")" 
    return $ open ++ content ++ close 

commentContent :: Unit -> Parser String String 
commentContent _ = do 
    content <- string "a" <|> comment 
    return content 
関連する問題