2011-10-21 6 views
4

私はこれを行うにしてみてください。Parsec-Parserは問題なく動作しますが、それは改善されますか?

一部のテキスト#{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 "Some Text#{0,0,0} some Text#{0,0,0}#{0,0,0} more Text#{0 、0,0} "

しかし、私はそれがいいとは思いません。

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

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

3)同じことを実現するために、一般的にはより簡潔でスマートな方法がありますか?

答えて

5

1)私はあなたがその解析の結果を必要とするので、lookAheadが必要だと思います。 Parser (Transc,Maybe Transc)Insideを指定し、オプションの後にOutsideと指定して、そのパーサーを2回実行することを避けるとよいでしょう。パフォーマンスが問題であれば、これは価値があります。

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 

あなたはaux x y z = Outside (x,y,z)のようなヘルパーを使用してreference2の始まりを書き換えることができます。

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

+0

ありがとうございます。あなたのバージョンは残念なことに、最初は "テキスト"の醜いハックにつながったエラーを生成します。文字列 "some"でも失敗します。これは、 "eof" -checkを "text" -parserに入れ、空のInside "を入力するために強制したものです。 – Secoe

+0

@Sec Oeごめんなさい!私は、 '試してみると' eof'それ自体を扱うと思っていました。 – Anthony

関連する問題