4

私はこれをしようとします:

次の形式でテキストを解析します。

一部のテキスト #{0,0,0} 一部のテキスト #{0,0,0}#{0,0,0} その他のテキスト #{0,0,0}

いくつかのデータ構造のリストに:

[内側 "一部のテキスト",外側 (0,0,0),内側 "一部のテキスト",外側 (0,0,0),外側 (0,0,0),内側 "その他のテキスト",外側 (0, 0,0)]

したがって、これらの #{a,b,c} ビットは、残りのテキストとは異なるものに変わるはずです。

私はこのコードを持っています:

module ParsecTest where

import Text.ParserCombinators.Parsec
import Monad

type Reference = (Int, Int, Int)

data Transc = Inside String | Outside Reference
              deriving (Show)

text :: Parser Transc
text =  do
         x <- manyTill anyChar ((lookAhead reference) <|> (eof >> return (Inside "")));
         return (Inside x)

transc = reference <|> text

alot :: Parser [Transc]
alot = do
        manyTill transc eof

reference :: Parser Transc
reference = try (do{ char '#';
                  char '{';
                  a <- number;
                char ',';
                b <- number;
                char ',';
                c <- number;
                char '}';
                return (Outside (a,b,c)) })

number :: Parser Int
number = do{ x <- many1 digit;
             return (read x) }

これは期待どおりに機能します。次のように入力して、ghci でこれをテストできます。

parseTest alot "一部のテキスト #{0,0,0} 一部のテキスト #{0,0,0}#{0,0,0} その他のテキスト #{0,0,0}"

でも、もったいないと思います。

1) の使用はlookAhead本当に私の問題に必要ですか?

2)return (Inside "")醜いハックですか?

3)一般的に、同じものをアーカイブするためのより簡潔でスマートな方法はありますか?

4

1 に答える 1

5

lookAhead1)その解析の結果が必要なので、必要だと思います。オプションの following で anParser (Transc,Maybe Transc)を示す to を持つことで、そのパーサーを 2 回実行するのを避けるとよいでしょう。パフォーマンスが問題になる場合は、これを行う価値があります。InsideOutside

2) はい。

3)Applicative

number2 :: Parser Int
number2 = read <$> many1 digit

text2 :: Parser Transc
text2 = (Inside .) . (:) 
     <$> anyChar 
     <*> manyTill anyChar (try (lookAhead reference2) *> pure () <|> eof)


reference2 :: Parser Transc
reference2 = ((Outside .) .) . (,,) 
          <$> (string "#{" *> number2 <* char ',') 
          <*> number2 
          <*> (char ',' *> number2 <* char '}')

transc2 = reference2 <|> text2

alot2 = many transc2

reference2のようなヘルパーを使用する最初の部分を書き直したい場合がありaux x y z = Outside (x,y,z)ます。

編集:textで終わらない入力を処理するように変更されましたOutside

于 2011-10-21T18:05:54.287 に答える