Функция токенайзера строки Haskell - PullRequest
9 голосов
/ 25 ноября 2011

Мне нужен был токенайзер String в Haskell, но очевидно ничего не определено в Prelude или других модулях.В Data.Text есть splitOn, но его неудобно использовать, потому что вам нужно обернуть строку в текст.

Токенизатор не слишком сложен, поэтому я написал один (он не обрабатывает несколько соседнихразделители, но это работало хорошо для того, что мне было нужно).Я чувствую, что-то вроде этого должно быть уже где-то в модулях ..

Это моя версия

tokenizer :: Char -> String -> [String]
tokenizer delim str = tokHelper delim str []

tokHelper :: Char -> String -> [String] -> [String]
tokHelper d s acc 
    | null pos  = reverse (pre:acc)
    | otherwise = tokenizer d (tail pos) (pre:acc)
        where (pre, pos) = span (/=d) s

Я искал в Интернете больше решений и нашел некоторые обсуждения, такие как thisсообщение в блоге .

Последний комментарий (сделанный Махи 10 июня 2011 года) особенно интересен.Почему бы не сделать версию слова более универсальной, чтобы справиться с этим?Я пытался найти такую ​​функцию, но не нашел ни одной ..

Есть ли более простой способ для этого или «токенизация» строки не слишком повторяющаяся проблема?:)

Ответы [ 2 ]

16 голосов
/ 25 ноября 2011

Библиотека split - это то, что вам нужно.Установите с cabal install split, тогда у вас будет доступ ко многим функциям в стиле split / tokenizer.

Некоторые примеры из библиотеки:

 > import Data.List.Split
 > splitOn "x" "axbxc"
 ["a","b","c"]
 > splitOn "x" "axbxcx"
 ["a","b","c",""]
 > endBy ";" "foo;bar;baz;"
 ["foo","bar","baz"]
 > splitWhen (<0) [1,3,-4,5,7,-9,0,2]
 [[1,3],[5,7],[0,2]]
 > splitOneOf ";.," "foo,bar;baz.glurk"
 ["foo","bar","baz","glurk"]
 > splitEvery 3 ['a'..'z']
 ["abc","def","ghi","jkl","mno","pqr","stu","vwx","yz"]

Функция wordsBy из той же библиотеки является обобщенной версией words, как вы и хотели:

wordsBy (=='x') "dogxxxcatxbirdxx" == ["dog","cat","bird"]
4 голосов
/ 26 ноября 2011

Если вы анализируете язык, похожий на Haskell, вы можете использовать функцию lex из Prelude: http://hackage.haskell.org/packages/archive/base/latest/doc/html/Prelude.html#v:lex

...