我有一个字符串需要使用以下规则标记到列表中:
为此,我在Haskell代码中创建了上述规则作为有限状态机:
data FsaState = R | Q -- start state: Q; success state R;
deriving Show
输入:
tokenize “( (23.5+age) ∗ (20.99+adres))”
输出:
[ “(”, “ ”, “(”, “23.5”, “+”, “age”, “)”, “ ”, “∗”, “ ”, “(”, “20.99”, “+”, “adres”, “)”, “)” ]
(可能只用空格过滤掉字符串)
我应该如何开始?由于Haskell不是我的主要语言,我陷入了强制性的思维模式。
答案 0 :(得分:2)
如果您担心效率,您应该定义一个令牌数据类型(data Token = ...
)。也就是说,这是一个最小化的标记器,可以完全按照您的要求进行操作。它以递归方式工作(尾部),为每个递归调用咀嚼一个令牌(或空格)。
我选择丢弃空格而不是将其变成令牌。
import Data.Char
tokenize :: String -> [String]
tokenize "" = []
tokenize (c:cs)
| isSpace c = tokenize cs
| isAlpha c = let (i,cs') = span isAlphaNum cs in (c : i) : tokenize cs'
| isDigit c = let (n,cs') = span isDigit cs
in case cs' of
('.':cs'') -> let (m,cs''') = span isDigit cs''
in (c : n ++ "." ++ m) : tokenize cs'''
_ -> (c : n) : tokenize cs'
| c `elem` "+/*-()" = [c] : tokenize cs
| otherwise = error $ "unexpected character " ++ show c
以下是行动:
ghci> tokenize "( (23.5+age) ∗ (20.99+adres))"
["(","(","23.5","+","age",")","*","(","20.99","+","adres",")",")"]
那说:我强烈建议您编写一个解析monad(类似data Parser a = Parser { runParser :: String -> Maybe (a,String) }
),以便您可以单独编写解析器,或使用现有的库/工具(请参阅Alex特别是megaparsec