æå¼·ã®ãã¼ã¶ã¼ãParser Combinator
å®ã¯æ¨æ¥ã®è©±é¡ã¯ããããæ¸ããã¨ãã話ã¨ã¤ãªãããããã®ã ã
(ç´æ¥çã«ã¯ç¡ããã©)
Yaccã¨æ£è¦è¡¨ç¾ã¨Parser Combinatorã¨
(åº)
çªç¶ã§ããããHaskellã¯æååå¦çãå¼·åã ã¨æãã
ãããæå¼·ã¬ãã«ã«ã
ä»ã®ããããæååå¦çãå¾æã§ããã¨ãããè¨èªã®ããã«
æ£è¦è¡¨ç¾ã«ããç½®æãå¯è½ã§ããã¨ããæååããªãã¸ã§ã¯ãã§
æç¨ãªã¡ã½ããããããã使ããã¨ããããã£ã
å°æå
ã®ãã®ã§ã¯ãªãã¦ãã£ã¨æ ¹æ¬çãªã¬ãã«ã§å¼·åãªã®ã§ããã
ããã¯Haskellã«æ¼ãã¦æååãæåã®ãªã¹ãã§ãããããã¦ãããã¨ã«
èµ·å ãããããããªã人ããè¦ãã¨æååããªã¹ãã§ããã¨ãããã¨ã¯
Cã«ããã¦æååãé
åã§è¡¨ããã¦ããã®ã¨ãã¶ããããããªãã
Haskellãæååããªã¹ãã¨ãã¦æã£ã¦ãã¦ããããã¨ããã®ã¯
Haskellãå
¨è¨èªä¸ã§ãã»ã¨ãã©æå¼·ã®ãªã¹ãæä½è½åãæã£ã¦ããããã§ããã
Cã§æååãé
åã«ãªã£ã¦ãã¦ãä½ããããããªãã®ã¯ã
Cãé
åæä½ã大ãã¦å¾æã§ã¯ãªãããã§ããã
ãã¨ãã°ãåç´ç½®æãªã (æåxãæååyã«ç½®æ)
str >>= (\c -> if c == x then y else [c])
ç½®æ対象ãæååâæååã
replace x y str = inner str where inner = inner str@(s:ss) | isPrefixOf x s = y:inner (drop lx) | otherwise = s:inner ss lx = length x
ãã®ããã«å®ç¾©ããã°è¡ããã(å®ç¾©ããªããã°ãªããã®ã ãã©)
å®ç¾©ããããã°è¤æ°ã®ç½®æãä¸åº¦ã«è¡ãã®ããªãã®ãã®ã§ããã
replaceMultiple = foldl (\f (x,y) -> f . replace x y) id ... replaceMultiple [("foo","bar"),("hello","world")] str
ãã¡ãããã®ãããªã±ã¼ã¹ã¯é常ã«åç´ã§ã
ç¾å®ã«ã¯ããå°ãè¤éãªãããã³ã°ãå¿
è¦ã«ãªããã¨ãå¤ãã ããã
åç´æ¯è¼ã§ã¯ç¡çã ãã©ãCFG*1ãæã¡åºãã»ã©ã§ãâ¦
ã¨ãã£ãå ´åãå¤ãã®è¨èªã§ã¯æ£è¦è¡¨ç¾ã®åãåããã
æ£è¦è¡¨ç¾ã¯ç¢ºãã«ä¾¿å©ã§ããã
便å©ãªã®ã ããæ£è¦è¡¨ç¾ã¯å¤§ä½ã®å ´åã«ããã¦å
¨ãè¨èªã¨ã¯ç¬ç«ã§ããã
ããã°ã©ãã¯"ç¹å®ã®æ£è¦è¡¨ç¾ã®ææ³"ã«å¾ã£ã¦"æåå"ã§ããã
æå®ãããã¨ã«ãªãã
ããã¯è¨èªã¨ã¯å¥ã«æ£è¦è¡¨ç¾ã®ææ³ãè¦ããå¿
è¦ããããã¨ãæå³ãã
ããã«è¨èªå¦çç³»ã¨ç¬ç«ãªã®ã§å®è¡æã¾ã§æ£è¦è¡¨ç¾ãæ£ãããã©ããã
確ãããããªãã
Haskellã ã¨ãããã£ãå ´åãParser combinatorã使ãã
Parser combinatorã¯Haskellã«ã¨ã£ã¦ã¯æ®éã®é¢æ°ã§ããã
å¥æ®µç¹æ®ãªãã®ã§ã¯ãªããã¨ãä¸å¿æã£ã¦ããã
æ®éã®ããã°ã©ã ãªã®ã§ãæ£è¦è¡¨ç¾ã®è¨èªã¯ã©ã¹ã«ã¨ãããããã¨ãªã
BNFã§è¡¨ç¾ã§ããææ³ããã¼ãºã§ããã
(BNFã§è¡¨ç¾ã§ããªãã¯ã©ã¹ã®ææ³(0åè¨èªããã¥ã¼ãªã³ã°ãã·ã³ã¨ç価)
ã解æã§ãããã©â¦)
ã¨ããããä¸ä¾ãæ¸ãã¦ã¿ãã
ä¸ããããæååããY/M/Dã®å½¢ã§ä¸ããããæååã
M.D,Yã«ç½®æãããããªããã°ã©ã ã§ããã
ãªãã以ä¸ã®ããã°ã©ã ã§ã¯ãã¼ã¶ã³ã³ããã¼ã¿ã®"å®è£
ã®ä¸ä¾"ã§ãã
Text.ParserCombinators.Parsecã使ã£ã¦ããã
main = putStrLn $ repl "today is 2004/07/30 desu." repl str = case parse p "" str of Left err -> error "ããã£?!ã¨ã©ã¼?ããããªããã!!" Right ls -> ls where p = do ls <- many $ (try date) <|> (anyChar >>= \c -> return [c]) return $ concat ls date = do y <- many1 digit char '/' m <- many1 digit char '/' d <- many1 digit return $ m ++ "." ++ d ++ "," ++ y
$ ./a.out today is 07.30,2004 desu.
æ£è¦è¡¨ç¾ã使ãå ´åã«æ¯ã¹ã¦ã³ã¼ãã¯é·ããªã£ã¦ããã¨æããããã
ã¨ã©ã¼ã¯ã³ã³ãã¤ã«æã«ãã§ãã¯ã§ãããã
ä½ãããã¼ã¶ã¼ããªãã¸ã§ã¯ãã¨ãã¦åå¨ãã¦ããã®ã§ããã
ä¸è¨ã½ã¼ã¹ã ã¨"date"ãY/M/DãèªèãM,D.Yãè¿ããã¼ã¶ã¼ã§ããã
ãã®ãã¨ã¯ãã¼ã¶ã¼ã«é¢ããæ¼ç®ãå®ç¾©ã§ãããã¨ãæå³ããã
å
ã®ã½ã¼ã¹ä¸ã§ãã¼ã¶ã¼ã¯ãpã¨dateã§ããã
dateã¯ã¾ãã«ãã®åé¡ã®ããã«ä½æãããã®ã§ãããã
pãè¡ã£ã¦ããã®ã¯dateã§è§£æã§ãããã©ããããã§ãã¯ãç¶ãã¦ããã ãã§ã
ããã¯ãã®åé¡åºæã®å¦çã§ã¯ãªãã
dateãæ½è±¡åãããã£ã¨ä¸è¬çã«ä½¿ç¨ã§ããã®ã§ããã
main = putStrLn $ replaceBy date "today is 2004/07/30 desu." where date = do y <- many1 digit char '/' m <- many1 digit char '/' d <- many1 digit return $ m ++ "." ++ d ++ "," ++ y replaceBy :: Parser String -> String -> String replaceBy p str = case parse (repAll p) "" str of Left err -> error "ããã£?!(ç¥" Right ls -> ls repAll :: Parser String -> Parser String repAll p = do ls <- many $ (try p) <|> (anyChar >>= \c -> return [c]) return $ concat ls
replaceByã¯ãã¼ã¶ã¼ãå¼æ°ã«ã¨ããå¤æé¢æ°ãè¿ãé¢æ°ã¨ãªãã
ããã§ã"today"ã¨ããæååã"yesterday"ã«ãå¤ããã
ã¨åä½ãå¤æ´ãããå ´åã
main = putStrLn $ replaceBy (date <|> today) "today is 2004/07/30 desu." where date = ... today = string "today" >> return "yesterday"
ã¨å¤æ´ããã°ããã
æåã«æ¸ããreplaceãreplaceByãç¨ãã¦
replace x y = replaceBy (string x >> return y)
ã¨æ¸ããªãããã¨ãåºæ¥ãã
string x >> return y ã¨ããé¨åãè¤æ°ååºã¦ããã®ã§ã
replaceParser :: String -> String -> Parser String replaceParser x y = string x >> return y
ããããã®ããã«æ½è±¡åããã®ãããããç¥ããªãã
ã¨ã¾ãããªããããããåºæ¥ãã¨ãã話ã§ä»åã¯ã¾ã
å
·ä½çãªã¨ããã¾ã§çªã£è¾¼ãã¤ããã¯ç¡ãã£ãã®ã ãâ¦
åãçãã®ãªã話ã«ãªã£ã¦ããã®ã§ãä»åã¯ãã®è¾ºã§ã
次ãããã«Parser Combinatorã¨ãããã®ã«ã¤ãã¦ã
æ¸ããã¨æãã(ç§ãæ¸ãå¿
è¦ãç¡ããããªæ°ããããã©)
å®è·µçããã°ã©ã ã¯ããã«ãã®å
ã«ã§ãã
*1:æèèªç±ææ³