У меня есть несколько строк, которые я хочу разборки в список «кусков». Мои строки выглядят как этотРазбор строки в haskell
"some text [[anchor]] some more text, [[another anchor]]. An isolated ["
И я жду, чтобы получить обратно что-то вроде этого
[
TextChunk "some text ",
Anchor "anchor",
TextChunk " some more text, "
Anchor "another anchor",
TextChunk ". An isolated ["
]
Я сумел написать функцию и типы, которые делают то, что мне нужно, но они, кажется, слишком некрасиво. Есть ли лучший способ сделать это?
data Token = TextChunk String | Anchor String deriving (Show)
data TokenizerMode = EatString | EatAnchor deriving (Show)
tokenize::[String] -> [Token]
tokenize xs =
let (_,_,tokens) = tokenize' (EatString, unlines xs, [TextChunk ""])
in reverse tokens
tokenize' :: (TokenizerMode, String, [Token]) -> (TokenizerMode, String,[Token])
-- If we're starting an anchor, add a new anchor and switch modes
tokenize' (EatString, '[':'[':xs, tokens) = tokenize' (EatIdentifier, xs, (Identifier ""):tokens)
-- If we're ending an anchor ass a new text chunk and switch modes
tokenize' (EatAnchor, ']':']':xs, tokens) = tokenize' (EatString, xs, (TextChunk ""):tokens)
-- Otherwise if we've got stuff to consume append it
tokenize' (EatString, x:xs, (TextChunk t):tokens) = tokenize'(EatString, xs, (TextChunk (t++[x])):tokens)
tokenize' (EatAnchor, x:xs, (Identifier t):tokens) = tokenize'(EatAnchor, xs, (Identifier (t++[x])):tokens)
--If we've got nothing more to consume we're done.
tokenize' (EatString, [], tokens) = (EatString, [], tokens)
--We'll only get here if we're given an invalid string
tokenize' xx = error ("Error parsing .. so far " ++ (show xx))
На самом деле это не токенизация, а синтаксический анализ. И для всех ваших потребностей синтаксического анализа, Parsec. –
@CatPlusPlus согласился, что его разбор .. обновленный текст и название для соответствия. –
@CatPlusPlus Можете ли вы показать мне, как это будет выглядеть с помощью парсека? Я нахожу, что docs/tutes немного неясны по своему вкусу. –