私はHaskell、Parsec、および一般的なパーザーの初心者です。私は単純な言語を解析しようとしています。(この質問のために単純化すると)入れ子になった括弧の文字列で構成されています。 [[][]][]
。Parsecでこの文法を解析するには? (左回帰の珍しいケース)
下記のHaskellコードがありますが、これはうまくいきます。しかし、大文字と小文字の区別されない括弧が文字列の最後に一致するように拡張したいと思います。たとえば、]][][[
は[[]][][[]]
と同等で、[]]
は[[]]
と同等である必要があります。文字列の終わりに一致する開いた括弧でこれを行うのは簡単ですが、文字列の先頭に一致する閉じた括弧のためにそれを実行すると、左回帰と無限ループが発生し、解決する方法がわかりません。その理由が文法やParsecライブラリを使っているやり方を考えているのかどうかはわかりませんが、どちらの方法であれ、私はその道を見せてくれることを感謝しています。ここで
は、私が持っている作業コードです:
{-# LANGUAGE NoMonomorphismRestriction #-}
import qualified Text.Parsec as Parsec
import Control.Applicative
-- for testing
parse rule text = Parsec.parse rule "(source)" text
data Expr = Brackets [Expr]
deriving(Show)
openBracket = Parsec.char '['
closeBracket = Parsec.char ']'
parseBrackets = do
expr <- Parsec.between openBracket closeBracket parseExpr
return $ Brackets expr
parseExpr = Parsec.many parseBrackets
私は、閉じ括弧は、文字列の末尾にマッチしたい場合は、私はちょうど
closeBracket = (Parsec.char ']' >> return()) <|> Parsec.eof
しかし、にもかかわらずにcloseBracket
の定義を変更することができます試行錯誤のかなりのビット私は一致しない解決策が見つかりませんでした]
秒の文字列の先頭に対して。私は、Parsecでの左回帰の通常の解決策はchainl1
関数だと知っていますが、それは中置演算子には非常に特化しているようですが、ここでそれを使う方法はありません。
これは素晴らしいですが、私はそれから多くのことを学びました。(私が以前持っていたように 'Parsec.Stream sm Char => Parsec.ParsecT sum [Expr]'のようなものではなく、パーサーが読める型を与えるためにあなたが使った魔法は、特に喜んでいます。)しかしパーサーは、 '[]]'の代わりに '[]'に相当する '[]]'が出てくるように、最初に一致する括弧が見つかると、 (私はそのテストケースを質問に追加しました。最初にその意図を明確にしていないのは本当に残念です。あなたの 'parseStart'関数が何をしているのか分かり次第、修正できます) – Nathaniel
この問題に対処する自己回答ですが、それはちょっとした気分のようです... – Nathaniel