1

我正在使用Text.ParserCombinators.ParsecText.XHtml来解析这样的输入:

 
- 第一个类型 A\n
-- 第一个类型 B\n
- 第二种 A\n
-- 第一个类型 B\n
--第二种类型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。更常见的 Parser 类型只是“type Parser a = GenParser Char() a” 你可能想说

type MyParser a = GenParser Char SectionState a

在代码开头附近的某个地方。

于 2010-04-29T16:49:35.557 回答