Subscribed unsubscribe Subscribe Subscribe

ネストしたincludeに対応するlexer

Haskell

Cの#includeとか設定ファイルのincludeディレクティブ的なincludeに対応するlexerメモ。「*」指定などのglob対応。Parsec 3で。

tIncluded :: Stream String IO Char => ParsecT String u IO TokenType
tIncluded = lexeme $ do
  try $ symbol "include"
  glob <- many1 $ C.satisfy (not . isSpace)
  (curPos, curDir, curInp) <- getCtx
  files <- liftIO $ do
    let srcDir = takeDirectory $ sourceName curPos
    setCurrentDirectory srcDir
    fs <- namesMatching glob
    return $ (srcDir </>) <$> fs
  ts <- forM files $ \file -> do
    setPosition $ initialPos file
    contents <- liftIO $ readFile file
    setInput contents
    tokens
  setCtx curPos curDir curInp
  return $ Included $ concat ts
  where getCtx = (,,) <$> getPosition
                      <*> liftIO getCurrentDirectory
                      <*> getInput
        setCtx pos dir inp = do
          setPosition pos
          liftIO $ setCurrentDirectory dir
          setInput inp

もうちょっと綺麗にならないかなー。