Haskell Parsec项目编号

时间:2010-04-29 10:58:54

标签: parsing haskell functional-programming parsec

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

 
- First type A\n
-- First type B\n
- Second type A\n
-- First type B\n
--Second type 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

 

这没关系,但不包括编号。

有什么想法吗?

谢谢!

1 个答案:

答案 0 :(得分: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类型只是“类型Parser a = GenParser Char()a”你可能想说

type MyParser a = GenParser Char SectionState a

靠近代码开头的地方。