[go: up one dir, main page]

Menu

[5c95e0]: / Xcerpt.hs  Maximize  Restore  History

Download this file

230 lines (179 with data), 8.3 kB

  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
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
{------------------------------------------------------------------------------
The Xcerpt CommandLine interface
USAGE:
xcerpt [OPTIONS] <program-file>
xcerpt [OPTIONS] -g <goal> <program-file>
xcerpt -I
WHERE
<program-file> is the filesystem path to an Xcerpt program. If not given,
reads from stdin
<goal> is a query term in Xcerpt syntax, e.g. "var C" or
"var C -> results"
OPTIONS
-c --cgi generate cgi content-type output
-I --interactive interactive mode (for debugging and experimenting)
-i <fmt> --input=<fmt> set format of input (xml or xcerpt syntax)
-o <fmt> --output=<fmt> set format of output (only useful in conjunction
with -g)
If a goal is given with -g, the program simply dumps the constraint store after
evaluation on the screen, limited to the variables occuring in <goal>.
If no goal is given, the Xcerpt program is evaluated according to the goals
specified in the program. If the program contains no goal ("a library"),
nothing happens.
[CVS Revision: $Id: Main.hs,v 1.16 2003/01/07 14:18:43 wastl Exp $]
-------------------------------------------------------------------------------}
module Main where
import Data.Char (isAlphaNum,isSpace,toUpper,toLower)
import System (getArgs)
import System.Exit
import System.IO (stdin,stdout,openFile,hGetContents,IOMode(..))
import System.Console.GetOpt
import Xcerpt.Data.Term
import Xcerpt.Data.Program
import Xcerpt.Data.Formula
import qualified Xcerpt.Parser.XcerptV1 as V1 (parseProgram,parseGoal,parseTerm)
import qualified Xcerpt.Parser.XcerptV2 as V2 (parseProgram,parseGoal,parseTerm)
import Xcerpt.Parser.XML as XML (parseProgramXML,parseXML)
import Xcerpt.EngineNG.Solver (solve, solveCS)
import Xcerpt.EngineNG.Program (evalQuery,hRunProgram,RunDesc(..))
import Xcerpt.EngineNG.Substitution (getSubstitutions,Substitution,showSubstitutions)
import Xcerpt.EngineNG.Matrix
import Xcerpt.Misc
import Xcerpt.Version (version, versions)
import Xcerpt.EngineNG.Transformations as Transformations
import XcerptInteractive (interfaceIA)
#ifdef OBSERVE
import Observe
#else
runO :: IO a -> IO ()
runO x = do x
return ()
observe :: String -> a -> a
observe _ x = x
#endif
data Arg = Version | Help |
Interactive | CGI |
ArgProgram String | ArgGoal String |
InputFormat String | OutputFormat String | Force |
Param String String
deriving (Show,Eq)
options :: [OptDescr Arg]
options =
[ Option ['V'] ["version"] (NoArg Version) "show version number",
Option ['h','?'] ["help"] (NoArg Help) "show usage",
Option ['I'] ["interactive"] (NoArg Interactive) "launch interactive interface",
Option ['c'] ["cgi"] (NoArg CGI) "add CGI headers in output",
Option ['g'] ["goal"] (ReqArg ArgGoal "term") "eval goal (together with -p)",
Option ['p'] ["program"] (ReqArg ArgProgram "FILE") "eval program",
Option ['i'] ["in"] (ReqArg (InputFormat . lc) "xml|xcerpt1|xcerpt2") "input format",
Option ['o'] ["out"] (ReqArg (OutputFormat . lc) "xml|xcerpt1|xcerpt2") "output format",
Option ['f'] ["force"] (NoArg Force) "enforce output format (override specification in program)",
Option ['D'] ["DEFINE"] (ReqArg ((uncurry Param) . break2 ('='==)) "key=value") "set parameter"
]
parsers =
[ ("xml", (XML.parseProgramXML, parseXML) ),
("xcerpt1", (V1.parseProgram, V1.parseTerm)),
("xcerpt2", (V2.parseProgram, V2.parseTerm)),
("xcerpt", (V2.parseProgram, V2.parseTerm))
]
lc :: String -> String
lc = map toLower
break2 p l = let (xs,(y:ys)) = break p l in (xs,ys)
-- process command line arguments
mainOpts :: [String] -> IO ([Arg], [String])
mainOpts argv =
case (getOpt Permute options argv) of
(o,n,[] ) -> return (o,n)
(_,_,errs) -> error (concat errs ++ usageInfo header options)
where header = "Usage: xcerpt [OPTION...] [program]"
-- get the goal from a list of (processed) command line arguments
getGoal :: [Arg] -> Maybe String
getGoal [] = Nothing
getGoal (ArgGoal g:_) = Just g
getGoal (_:xs) = getGoal xs
-- get the program from a list of (processed) command line arguments
getProgram :: [Arg] -> Maybe String
getProgram [] = Nothing
getProgram (ArgProgram p:_) = Just p
getProgram (_:xs) = getProgram xs
-- main function, fetch arguments, process arguments and proceed with
-- the function "process"
main :: IO ()
main = do args' <- getArgs
(args,files) <- mainOpts args'
process args files
-- interpret "absolute" arguments and decide which evaluation method
-- to use
process :: [Arg] -> [String] -> IO ()
process args files =
case filter absolute args
of -- print usage info
(Help:_) -> putStrLn (usageInfo header options)
-- print version info
(Version:_) -> putStrLn versions
-- start interactive interface
(Interactive:_) -> interfaceIA
-- evaluate program
[] -> evalProg args files
where header = versions ++ "Usage: xcerpt [OPTION...] [program]"
absolute x = x == Help || x == Version || x == Interactive
-- evaluate program. retrieve program content from either a specified file or
-- from stdin and parse it according to the chosen input format (xml or xcerpt)
evalProg :: [Arg] -> [String] -> IO ()
evalProg args files =
do if CGI `elem` args
then do putStrLn "Content-Type: text/html\n\n"
putStrLn ("<!-- Generator: Xcerpt "++version++" -->")
else return ()
-- get program
phandle <- case (getProgram args, files)
of -- parameter -p given
(Just f,_) -> openFile f ReadMode
-- no parameter -p, but file provided as last argument
(Nothing,[f]) -> openFile f ReadMode
-- no file provided, read from stdin
(Nothing,_) -> return stdin
p_unparsed <- hGetContents phandle
-- parse program depending on input format
let parser = maybe (error ("unknown parser: "++(selectInput args))) fst $
lookup (selectInput args) parsers
p_parsed = parser p_unparsed
-- if there is a goal, evaluate it against the program, else run the
-- program using the contained goals.
let toMap (Param k v) = (k,V2.parseTerm v)
isParam (Param _ _) = True
isParam _ = False
params = map toMap $ filter isParam args
outformat = selectOutput args
force = selectForce args
maybe (hRunProgram (RunDesc stdout outformat force) p_parsed params ) (runGoal args p_parsed) (getGoal args)
runGoal :: [Arg] -> Program -> String -> IO ()
runGoal args p g =
do -- parse goal depending on input format
let goal = case (selectInput args)
of "xml" -> QTerm [] (parseXML g)
_ -> V2.parseGoal g
-- evaluate goal against the program
result <- evalGoal p goal
-- transform result into a solved form and restrict to the
-- variables occuring in the goal
let substs = getSubstitutions (getVariablesQ goal) result
-- display result according to the specified output format
if (selectOutput args) == "xml"
then putStrLn (showSubstitutions "XML" substs)
else putStrLn (showSubstitutions "XCERPT" substs)
selectInput [] = "xcerpt2"
selectInput ((InputFormat f):xs) = f
selectInput (_:xs) = selectInput xs
selectOutput [] = "xcerpt2"
selectOutput ((OutputFormat f):xs) = f
selectOutput (_:xs) = selectOutput xs
selectForce [] = False
selectForce (Force:xs) = True
selectForce (_:xs) = selectForce xs
getVariablesQ (QAnd _ qs _) = concat . map getVariablesQ $ qs
getVariablesQ (QOr _ qs _) = concat . map getVariablesQ $ qs
getVariablesQ (QTerm _ t) = getVariables t
evalGoal p q = do let p' = distributeParameters $ assignParameters [] $ p
p'' <- distributeResources p'
return (evalQuery p'' q)