2017-08-27 5 views
0

私は、構文解析の世界に新たなんだ、とかなり単純な-見せかけ問題を抱えている:Parsec(Haskell)を使ってキートークンに基づいて値を文字列に補間する方法はありますか?

私は<<key-label>>のようにエンコードされている長い通常のテキストのChunk秒で構成される文字列、およびKey秒を持っています。

data Merge a = Chunk a 
      | Key a 
    deriving (Show) 

key :: Parser (Merge String) 
key = Key <$> between (string "<<") (string ">>") (many1 letter) 

chunk :: Parser (Merge String) 
chunk = Chunk <$> many1 anyChar 

prose = many1 $ key <|> chunk 

ex = parseTest prose "hi <<x>> ! Do you like <<y>>?" 

-- Returns: 
-- [Chunk "hi <<x>> ! Do you like <<y>>?"] 

-- I'd like: 
-- [Chunk "hi ", Key "x", Chunk " !", ...] 

私は値でそれらのキーを交換したいのですが、私は私のトークン、IE String -> [Merge]に文字列を解析することができるかどうかということ解決することができます。

私はレクシング/解析である無限の深さに飛び込んできましたが、最終的にこの問題を解決するためのガイダンスは今すぐには得られますか?私は別の字句/構文解析ステップを含むデータの上に別のパスを、試してみましたが、私は代わりに、より具体的な補間LIBのparsecを使用するようをいただきたいが、

これは、私の試みの最も単純なインスタンス化したものです。

+2

あなたのパーサは 'Chunk'探し瞬間、そのルールは 'many1 anyChar'なので、残りの文字はすべてスラップアップされます。 'Key'の開始点であるシーケンス' << 'を禁止するルールを変更する必要があります。しかし、 'Key'を解析しているときに、' >> 'を見る前に文字以外のものがある場合は、それがエラーであるか、バックトラッキングして別の' Chunk'として扱うかどうかを決める必要があります。 – pat

+0

@pat私は 'many1 anyChar'があまりにも貪欲であることを理解していますが、私が間違っていれば' Chunk'が 'Key'の構文の概念をエンコードする必要があるのは奇妙ではないでしょうか?IE '' ''で止まる?)? –

+0

@ Josh.Fそれはあなたが望むセマンティクスに依存します。 '' '' ''は有効な文字列ですか? '' << << >> ''または '' << foo "'はどうですか?それにもかかわらず、別々の解析/レキシングステップがここに行く方法です(実際には、この単純な例は、レキシングと結果のクリーンアップのみで構成されていますが、これはあなたがしようとしているものの非常に単純化されたバージョンではないそう、パーサーは一切使わないでください)。 Lexingは '[Tok" hi "、OpenBrace、Tok" x "、CloseBrace、...]'のようなものを生成するはずですが、その後 'parsing'ステップはまったく簡単です。 – user2407038

答えて

1

notFollowedByを使用すると、キーでない限り、チャンクに 文字を含めることができます。 notFollowedByは の入力を消費しないので、proseはそれ自身のアイテムとして再度キーを解析するようになります。

chunk = Chunk <$> many1 (notFollowedBy key >> anyChar) 

これはaaa<<bbbbbbようにも物事がファイルの最後にすべての道を行くことによって、チャンクとして を解析されることを可能にする、それが鍵となっていてはならないことを決定し、閉じ >>が見つかりませんしたがって、チャンクの一部になることがあります。

あなたではなく、<<は常にキーの始まりであると、それが閉じていない 場合に失敗していたチャンクから<<を禁止したい場合:

chunk = Chunk <$> many1 (notFollowedBy (string "<<") >> anyChar) 
+0

作品!ちょっと、私はより複雑な構文解析があることを知っています。先読みや逆戻りするものは非効率的で、複数のパスを行うことで取り除かれます。私は複数回のアプローチを試みましたが、その後、文字/文字列の代わりにトークンでParsecを使用する方法を理解することができませんでした。あなたは私を正しい方向に向けることができますか? –

関連する問題