-
Notifications
You must be signed in to change notification settings - Fork 2
/
Main.hs
117 lines (109 loc) · 4.29 KB
/
Main.hs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
-- This file is part of tersmu
-- Copyright (C) 2014 Martin Bays <mbays@sdf.org>
--
-- This program is free software: you can redistribute it and/or modify
-- it under the terms of version 3 of the GNU General Public License as
-- published by the Free Software Foundation.
--
-- You should have received a copy of the GNU General Public License
-- along with this program. If not, see http://www.gnu.org/licenses/.
module Main where
import ParseText (parseText)
import JboParse (evalText, evalStatement)
import JboSyntax
import ParseM (ParseStateT, evalParseStateT)
import JboShow
import Logic
import Bindful
import Morph
import Control.Monad.State
import Control.Monad.Identity
import Control.Applicative
import Data.Map (Map)
import qualified Data.Map as Map
import Data.List
import Data.Char
import Data.Either
import System.IO
import System.IO.Error
import System.Exit
import System.Process
import System.Environment
import System.Console.GetOpt
versionString = "0.2"
doParse :: OutputType -> Handle -> Handle -> String -> IO ()
doParse ot h herr s = case morph s of
Left errpos -> highlightError herr errpos s "Morphology error"
Right text -> evalParseStateT $ showParsedText ot h herr text $ parseText text
showParsedText :: OutputType -> Handle -> Handle -> String -> Either Int Text -> ParseStateT IO ()
showParsedText ot h _ s (Right text) = do
jboText <- mapStateT (return.runIdentity) $ JboParse.evalText text
when (not $ null jboText) $ do
liftIO $ hPutStr h $ concat
[if not $ (jbo && ot == Loj) || (not jbo && ot == Jbo)
then evalBindful (logjboshow jbo jboText) ++ "\n\n"
else ""
| jbo <- [False,True]
]
showParsedText _ _ herr s (Left pos) = highlightError herr pos s "Parse error"
highlightError h pos s errstr = let context = 40 in
liftIO $ hPutStr h $ errstr++":" ++
"\n\t{" ++ take (context*2) (drop (pos-context) s) ++ "}" ++
"\n\t " ++ replicate (min pos context) ' ' ++
"^" ++
"\n\n"
data OutputType = Jbo | Loj | Both
deriving (Eq, Ord, Show)
data InputType = WholeText | Paras | Lines
deriving (Eq, Ord, Show)
data Opt = Output OutputType | Input InputType | Help | Version
deriving (Eq, Ord, Show)
options =
[ Option ['l'] ["loj"] (NoArg (Output Loj)) "output logical form only"
, Option ['j'] ["jbo"] (NoArg (Output Jbo)) "output forethoughtful lojbanic form only"
, Option ['L'] ["lines"] (NoArg (Input Lines)) "interpret each line as a lojban text"
, Option ['p'] ["paragraphs"] (NoArg (Input Paras)) "interpret each blank-line-separated paragraph as a lojban text"
, Option ['v'] ["version"] (NoArg Version) "show version"
, Option ['h'] ["help"] (NoArg Help) "show help"
]
parseArgs :: [String] -> IO ([Opt],[String])
parseArgs argv =
case getOpt Permute options argv of
(o,_,[]) | Help `elem` o -> putStrLn (usageInfo header options) >> exitWith ExitSuccess
(o,_,[]) | Version `elem` o -> putStrLn versionString >> exitWith ExitSuccess
(o,n,[]) -> return (o,n)
(_,_,errs) -> ioError (userError (concat errs ++ usageInfo header options))
where header = "Usage: tersmu [OPTION...] [in] [out]\n\t(use '-' for stdin/stdout)"
main :: IO ()
main = do
(opts,args) <- getArgs >>= parseArgs
let outType = last $ Both:[t | Output t <- opts]
let inType = last $ WholeText:[t | Input t <- opts]
(inf, h) <- case args of
[] -> return (Nothing,stdout)
[infn] -> do
s <- if infn == "-" then getContents else readFile infn
return (Just s,stdout)
[infn,outfn] -> do
s <- if infn == "-" then getContents else readFile infn
h <- if outfn == "-" then return stdout else openFile outfn WriteMode
return (Just s, h)
case inf of
Nothing -> repl outType h `catchIOError` (\e ->
if isEOFError e then exitWith ExitSuccess
else putStr (show e) >> exitFailure)
Just s -> mapM (doParse outType h stderr) (mangleInput inType s) >> hClose h
where
repl outType h = do
-- interactive mode
hPutStr stderr "> "
hFlush stderr
s <- getLine
hPutStrLn stderr ""
doParse outType h stderr s
repl outType h
mangleInput WholeText = (\x -> [x]) . map (\c -> if c `elem` "\n\r" then ' ' else c)
mangleInput Lines = lines
mangleInput Paras = map (intercalate " ") . splitAtNulls . lines
splitAtNulls ls = let (h,t) = break null ls in
h : if null t then [] else splitAtNulls (tail t)