summaryrefslogtreecommitdiff
path: root/main.hs
diff options
context:
space:
mode:
authorTom Smeding <tom.smeding@gmail.com>2018-04-19 11:45:46 +0200
committerTom Smeding <tom.smeding@gmail.com>2018-04-19 11:45:46 +0200
commitaf425841a63ee73603cc09510d95a36e646ddafd (patch)
tree08a1ef8435ec0ab07887256a1c86f908c2389a1a /main.hs
parent8d9d27d64d9e39ea76fd878e928e553944735e45 (diff)
Build with stack
Diffstat (limited to 'main.hs')
-rw-r--r--main.hs145
1 files changed, 0 insertions, 145 deletions
diff --git a/main.hs b/main.hs
deleted file mode 100644
index b908807..0000000
--- a/main.hs
+++ /dev/null
@@ -1,145 +0,0 @@
-module Main where
-
-import Control.Monad
-import Data.Char
-import Data.List
-import Data.Either
-import Data.Maybe
-import System.Console.Readline
-import System.Exit
-import System.IO
-import qualified Data.Map.Strict as Map
-
-import AST hiding (main)
-import Simplify
-import Parser
-import PrettyPrint
-import Utility
-import Debug
-
-
-trimlr :: String -> String
-trimlr = reverse . dropWhile isSpace . reverse . dropWhile isSpace
-
-findstr :: String -> String -> Maybe Int
-findstr pat sub = go sub 0
- where len = length pat
- go :: String -> Int -> Maybe Int
- go "" _ = Nothing
- go sub i = if take len sub == pat then Just i else go (tail sub) (i+1)
-
-mayberead :: Read a => String -> Maybe a
-mayberead s =
- let r = reads s
- ok = if null r then False else null $ snd $ head r
- v = fst $ head r
- in if ok then Just v else Nothing
-
-readrule :: String -> IO (AST,AST)
-readrule line = do
- let (patstr',(repstr')) = break (=='|') line
- patstr = desugar $ trimlr patstr'
- repstr = desugar $ trimlr $ tail repstr'
- if null repstr'
- then die $ "No pipe separator found: " ++ line
- else do
- let mpat = mayberead patstr :: Maybe AST
- mrep = mayberead repstr :: Maybe AST
- when (isNothing mpat) $ die $ "Could not parse pattern! (from '" ++ patstr ++ "')"
- when (isNothing mrep) $ die $ "Could not parse replacement! (from '" ++ repstr ++ "')"
- return (fromJust mpat,fromJust mrep)
-
-desugar :: String -> String
-desugar "" = ""
-desugar ('{':cs) =
- let midx = findIndex (=='}') cs
- idx = fromJust midx
- termcap = head cs == '{' && length cs > idx+1 && cs !! (idx+1) == '}'
- endidx = if termcap then idx+1 else idx
- after = drop (endidx+1) cs
- name' = if termcap then tail $ take (endidx-1) cs else take endidx cs
- name = map (\c -> if c == '\\' || c == '"' then '_' else c) name'
- in if isNothing midx
- then '{':desugar cs
- else if termcap
- then let mcolonidx = findIndex (==':') name
- colonidx = fromJust mcolonidx
- precolon = take colonidx name
- postcolon = drop (colonidx+1) name
- stub = case postcolon of
- "Number" -> "Number 42"
- "Variable" -> "Variable \"\""
- _ -> trace postcolon undefined
- in if isNothing mcolonidx
- then "(CaptureTerm \"" ++ name ++ "\")" ++ desugar after
- else "(CaptureConstr \"" ++ precolon ++ "\" (" ++ stub ++ "))" ++ desugar after
- else "(Capture \"" ++ name ++ "\")" ++ desugar after
-desugar (':':cs) =
- let midx = findIndex (==':') cs
- endidx = fromJust midx
- after = drop (endidx+1) cs
- name = map (\c -> if c == '\\' || c == '"' then '_' else c) $ take endidx cs
- in if isNothing midx
- then ':':desugar cs
- else "Apply \"" ++ name ++ "\" " ++ desugar after
-desugar (c:cs) = c : desugar cs
-
-readrules :: Handle -> IO (Map.Map String [(AST,AST)])
-readrules handle = liftM (uncurry fixincludes) $ go "general" Map.empty Map.empty
- where
- go :: String -- current section
- -> Map.Map String [String] -- sections still to be included (#+)
- -> Map.Map String [(AST,AST)] -- current rules db
- -> IO (Map.Map String [(AST,AST)],Map.Map String [String]) -- (rules db,includes)
- go sect includes db = hIsEOF handle >>= \eof -> if eof then return (db,includes) else do
- line <- hGetLine handle
- case take 3 line of
- "" -> go sect includes db
- "-- " -> go sect includes db
- "## " -> go (trimlr $ drop 3 line) includes db
- "#+ " -> go sect (Map.insertWith (++) sect [trimlr $ drop 3 line] includes) db
- _ -> readrule (trimlr line) >>= \rule -> go sect includes (Map.insertWith (flip (++)) sect [rule] db)
-
- fixincludes :: Map.Map String [(AST,AST)] -- rules db
- -> Map.Map String [String] -- to be included sections
- -> Map.Map String [(AST,AST)] -- resulting rules db
- fixincludes db includes = Map.foldlWithKey insertincludes db includes
- where
- insertincludes :: Map.Map String [(AST,AST)] -- db
- -> String -- section
- -> [String] -- sections to be included
- -> Map.Map String [(AST,AST)] -- resulting db
- insertincludes db sect incls = foldl (\db incl -> insertinclude db sect incl) db incls
- where insertinclude db sect incl = Map.insertWith (++) sect (fromJust $ Map.lookup incl db) db
-
-
-printrules :: [(AST,AST)] -> IO ()
-printrules db = sequence_ $ foldl (\l (pat,sub) -> l ++ [print pat,putStr " -> ",print sub]) [] db
-
-
-repl :: Map.Map String [(AST,AST)] -> IO ()
-repl db = do
- mline <- readline "> "
- case mline of
- Nothing -> return () -- EOF
- Just "" -> repl db
- Just line -> do
- addHistory line
- let eexpr = parseExpression line
- either (putStrLn . ("Error: "++)) handleExpression eexpr
- repl db
- where
- generaldb = fromJust $ Map.lookup "general" db
- sanitisedb = fromJust $ Map.lookup "sanitise" db
- displaydb = fromJust $ Map.lookup "display" db
- handleExpression expr = do
- putStrLn $ prettyPrint expr
- let sim = foldl (flip simplify) expr [generaldb,sanitisedb,displaydb]
- putStrLn $ prettyPrint sim
-
-
-main :: IO ()
-main = do
- rulesdb <- withFile "rules.txt" ReadMode readrules
- --sequence_ $ Map.foldlWithKey (\l sect rules -> putStrLn ("## "++sect) : printrules rules : putStrLn "" : l) [] rulesdb
- repl rulesdb