Нумерация предметов в Haskell Parsec - PullRequest
1 голос
/ 29 апреля 2010

Я использую Text.ParserCombinators.Parsec и Text.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 Ответ

6 голосов
/ 29 апреля 2010

Возможно, вы захотите использовать GenParser с состоянием, содержащим текущие номера разделов в виде списка в обратном порядке, поэтому раздел 1.2.3 будет представлен как [3,2,1], и, возможно, длина списка, чтобы избежать неоднократно считая это. Что-то вроде

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

Тогда сделайте так, чтобы ваши действия синтаксического анализатора возвращали тип "GenParser Char SectionState a". Вы можете получить доступ к текущему состоянию в действиях вашего парсера, используя «getState» и «setState». Когда вы получите ряд «-» в начале строки, подсчитайте их и сравните с «глубиной» в состоянии, соответствующим образом управляйте списком «nums», а затем выведите «nums» в обратном порядке (я предлагаю сохранить nums в обратном порядке, потому что большую часть времени вы хотите получить доступ к наименее значимому элементу, поэтому поместить его в начало списка одновременно проще и эффективнее).

См. Text.ParserCombinators.Parsec.Prim для получения подробной информации о GenParser. Более обычным типом Parser является просто «type Parser a = GenParser Char () a» Вы, вероятно, хотите сказать

type MyParser a = GenParser Char SectionState a

где-то рядом с началом вашего кода.

...