parser-c 0.3.0

Macros for parser-c.
Documentation
-- Generate lexer patterns (reimplementation)
-- input := tokenlist
-- tokenlist := tokenspec [,\n] tokenlist |
-- tokenspec := (tletters | tctor tletters+) @__?
-- tctor     := ctor | (composite ctor)
import Data.Maybe
import Data.Char
import qualified Data.Text as T
import System.IO
import System.Environment
import Data.List as L
import Data.Ord

parseInput :: String -> [[String]]
parseInput = map (map T.unpack) .
             catMaybes .
             map (parseTokenSpec . T.strip) .
             T.split (','==) . T.intercalate (T.pack ",") .
             T.lines . T.pack

parseTokenSpec t | T.null t = Nothing
                 | T.head t == '(' =
                   let (tokexpr,tokenstr) = T.break (==')') t
                   in Just $ parseTokenSpec' (T.snoc tokexpr ')') (T.words $ T.tail tokenstr)
                 | otherwise =
                   let (tokexpr:tokens) = T.words t
                   in Just $ parseTokenSpec' tokexpr tokens

parseTokenSpec' tokexpr tokenlist =
  case T.unpack (last (tokexpr:tokenlist)) of
    "@__" -> addReservedTokens (parseTokenSpec'' tokexpr (init tokenlist))
    _     -> parseTokenSpec'' tokexpr tokenlist

parseTokenSpec'' tokexpr [] = [tokexpr, tokexpr]
parseTokenSpec'' tokexpr ts = tokexpr : ts

addReservedTokens [tokexpr, tok] = tokexpr : [us `T.append` tok, tok, us `T.append` tok `T.append` us ]
  where us = T.pack "__"
addReservedTokens list = error $ "addReservedTokens" ++ show list

expandInput = sortBy (comparing (dropWhile (=='_') . snd)) . concatMap expand
  where
    expand (t:ts) = [ (t,t') | t' <- ts ]

genOutput (ttok,tstr) =
  "idkwtok " ++ pattern ++ " = tok " ++ (show$length tstr) ++ " " ++ (genTok ttok)
  where
    genTok ts@('(':_) = ts
    genTok (t:ts) = "CTok" ++ (toUpper t : ts)
    pattern = "(" ++ L.intercalate " : " (map charPat tstr) ++ " : [])"
    charPat c = '\'' : c : '\'' : []

run ifile ofile = do
  inp <-readFile ifile
  let tokens = parseInput inp
  withFile ofile WriteMode $ \handle -> do
    hPutStrLn handle $ "-- Tokens: " ++ unwords (concatMap tail tokens)
    mapM_ (hPutStrLn handle) ((map genOutput . expandInput) tokens)

main = do
  arguments <- getArgs
  let (ifile,ofile) =
        case arguments of
          [a,b]-> (a,b)
          _ -> error "Usage: GenerateKeywords.hs tokenlist.txt tokenlist.hs"
  run ifile ofile