1

私はText.ParserCombinators.ParsecText.XHtmlを使用して、次のような入力を解析しています。

 
- 最初のタイプ A\n
-- 最初のタイプ B\n
- 2 番目のタイプ A\n
-- 最初のタイプ B\n
-- 2 番目のタイプ B\n

そして、私の出力は次のようになります。

 
 
<h1>1 First type A\n</h1>
<h2>1.1 First type B\n</h2>
<h1>2 Second type A\n</h2>
<h2>2.1 First type B\n</h2>
<h2>2.2 Second type B\n</h2>
 

私はこの部分に来ましたが、それ以上進むことはできません:

 
 
title1= do{     
                ;(count 1 (char '-'))
                ;s <- many1 anyChar newline
                ;return (h1 << s)
    }

title2= do{     
                ;(count 2 (char '--'))
                ;s <- many1 anyChar newline
                ;return (h1 << s)
    }

text=do {
        ;many (choice [try(title1),try(title2)])
 }

main :: IO ()
main = do t putStr "Error: " >> print err
            Right x  -> putStrLn $ prettyHtml x

 

これは問題ありませんが、番号付けは含まれていません。

何か案は?

ありがとう!

4

1 に答える 1

6

おそらく、現在のセクション番号を逆順のリストとして含む状態で GenParser を使用することをお勧めします。そのため、セクション 1.2.3 は [3,2,1] として表され、繰り返しカウントを避けるためにリストの長さを表す場合があります。 . 何かのようなもの

data SectionState = SectionState {nums :: [Int], depth :: Int}

次に、パーサー アクションの戻り値の型を "GenParser Char SectionState a" にします。「getState」と「setState」を使用して、パーサー アクションで現在の状態にアクセスできます。行の先頭に一連の「-」が表示されたら、それらを数えて状態の「深さ」と比較し、「nums」リストを適切に操作してから、「nums」を逆の順序で出力します(nums を保持することをお勧めしますほとんどの場合、最も重要でないアイテムにアクセスする必要があるため、逆の順序でリストの先頭に配置する方が簡単で効率的です)。

GenParser の詳細については、Text.ParserCombinators.Parsec.Prim を参照してください。より一般的なパーサーの型は、単に "type Parser a = GenParser Char () a" です。

type MyParser a = GenParser Char SectionState a

コードの先頭付近のどこかに。

于 2010-04-29T16:49:35.557 に答える