forked from GitHub/gf-core
cleanup
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
module GF.Command.Abstract(module GF.Command.Abstract,Expr,showExpr,Term) where
|
||||
|
||||
import PGF(CId,mkCId,Expr,showExpr)
|
||||
import PGF2(Expr,showExpr)
|
||||
import GF.Grammar.Grammar(Term)
|
||||
|
||||
type Ident = String
|
||||
@@ -31,12 +31,6 @@ data Argument
|
||||
| AMacro Ident
|
||||
deriving Show
|
||||
|
||||
valCIdOpts :: String -> CId -> [Option] -> CId
|
||||
valCIdOpts flag def opts =
|
||||
case [v | OFlag f (VId v) <- opts, f == flag] of
|
||||
(v:_) -> mkCId v
|
||||
_ -> def
|
||||
|
||||
valIntOpts :: String -> Int -> [Option] -> Int
|
||||
valIntOpts flag def opts =
|
||||
case [v | OFlag f (VInt v) <- opts, f == flag] of
|
||||
@@ -49,12 +43,6 @@ valStrOpts flag def opts =
|
||||
v:_ -> valueString v
|
||||
_ -> def
|
||||
|
||||
maybeCIdOpts :: String -> a -> (CId -> a) -> [Option] -> a
|
||||
maybeCIdOpts flag def fn opts =
|
||||
case [v | OFlag f (VId v) <- opts, f == flag] of
|
||||
(v:_) -> fn (mkCId v)
|
||||
_ -> def
|
||||
|
||||
maybeIntOpts :: String -> a -> (Int -> a) -> [Option] -> a
|
||||
maybeIntOpts flag def fn opts =
|
||||
case [v | OFlag f (VInt v) <- opts, f == flag] of
|
||||
|
||||
@@ -3,7 +3,7 @@ import GF.Command.Abstract(Option,Expr,Term)
|
||||
import GF.Text.Pretty(render)
|
||||
import GF.Grammar.Printer() -- instance Pretty Term
|
||||
import GF.Grammar.Macros(string2term)
|
||||
import PGF(mkStr,unStr,showExpr)
|
||||
import PGF2(mkStr,unStr,showExpr)
|
||||
|
||||
data CommandInfo m = CommandInfo {
|
||||
exec :: [Option] -> CommandArguments -> m CommandOutput,
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
|
||||
module GF.Command.Commands (
|
||||
PGFEnv,HasPGFEnv(..),pgf,mos,pgfEnv,pgfCommands,
|
||||
HasPGF(..),pgfCommands,
|
||||
options,flags,
|
||||
) where
|
||||
import Prelude hiding (putStrLn)
|
||||
|
||||
import PGF
|
||||
import PGF.Internal(writePGF)
|
||||
import PGF2
|
||||
import PGF2.Internal(writePGF)
|
||||
|
||||
import GF.Compile.Export
|
||||
import GF.Compile.ToAPI
|
||||
@@ -24,33 +24,25 @@ import GF.Command.TreeOperations ---- temporary place for typecheck and compute
|
||||
|
||||
import GF.Data.Operations
|
||||
|
||||
-- import PGF.Internal (encodeFile)
|
||||
import Data.Char
|
||||
import Data.List(intersperse,nub)
|
||||
import Data.Maybe
|
||||
import qualified Data.Map as Map
|
||||
import GF.Text.Pretty
|
||||
import Data.List (sort)
|
||||
--import Debug.Trace
|
||||
import Control.Monad(mplus)
|
||||
|
||||
class (Functor m,Monad m,MonadSIO m) => HasPGF m where getPGF :: m (Maybe PGF)
|
||||
|
||||
data PGFEnv = Env {pgf::Maybe PGF,mos::Map.Map Language Morpho}
|
||||
instance (Monad m,HasPGF m) => TypeCheckArg m where
|
||||
typeCheckArg e = do mb_pgf <- getPGF
|
||||
case mb_pgf of
|
||||
Just pgf -> either fail
|
||||
(return . fst)
|
||||
(inferExpr pgf e)
|
||||
Nothing -> fail "Import a grammar before using this command"
|
||||
|
||||
pgfEnv mb_pgf = Env mb_pgf mos
|
||||
where mos = case mb_pgf of
|
||||
Just pgf -> Map.fromList [(la,buildMorpho pgf la) | la <- languages pgf]
|
||||
Nothing -> Map.empty
|
||||
|
||||
class (Functor m,Monad m,MonadSIO m) => HasPGFEnv m where getPGFEnv :: m PGFEnv
|
||||
|
||||
instance (Monad m,HasPGFEnv m) => TypeCheckArg m where
|
||||
typeCheckArg e = do env <- getPGFEnv
|
||||
case pgf env of
|
||||
Just gr -> either (fail . render . ppTcError)
|
||||
(return . fst)
|
||||
(inferExpr gr e)
|
||||
Nothing -> fail "Import a grammar before using this command"
|
||||
|
||||
pgfCommands :: HasPGFEnv m => Map.Map String (CommandInfo m)
|
||||
pgfCommands :: HasPGF m => Map.Map String (CommandInfo m)
|
||||
pgfCommands = Map.fromList [
|
||||
("aw", emptyCommandInfo {
|
||||
longname = "align_words",
|
||||
@@ -63,7 +55,7 @@ pgfCommands = Map.fromList [
|
||||
"by the view flag. The target format is png, unless overridden by the",
|
||||
"flag -format. Results from multiple trees are combined to pdf with convert (ImageMagick)."
|
||||
],
|
||||
exec = needPGF $ \ opts arg pgf mos -> do
|
||||
exec = needPGF $ \ opts arg pgf -> do
|
||||
let es = toExprs arg
|
||||
let langs = optLangs pgf opts
|
||||
if isOpt "giza" opts
|
||||
@@ -75,7 +67,7 @@ pgfCommands = Map.fromList [
|
||||
let grph = if null es then [] else lsrc ++ "\n--end_source--\n\n"++ltrg++"\n-end_target--\n\n"++align
|
||||
return $ fromString grph
|
||||
else do
|
||||
let grphs = map (graphvizAlignment pgf langs) es
|
||||
let grphs = map (graphvizWordAlignment langs graphvizDefaults) es
|
||||
if isFlag "view" opts || isFlag "format" opts
|
||||
then do
|
||||
let view = optViewGraph opts
|
||||
@@ -108,16 +100,17 @@ pgfCommands = Map.fromList [
|
||||
"by the flag '-clitics'. The list of stems is given as the list of words",
|
||||
"of the language given by the '-lang' flag."
|
||||
],
|
||||
exec = needPGF $ \opts ts pgf mos -> case opts of
|
||||
_ | isOpt "raw" opts ->
|
||||
return . fromString .
|
||||
unlines . map (unwords . map (concat . intersperse "+")) .
|
||||
map (getClitics (isInMorpho (optMorpho pgf mos opts)) (optClitics opts)) .
|
||||
concatMap words $ toStrings ts
|
||||
_ ->
|
||||
return . fromStrings .
|
||||
getCliticsText (isInMorpho (optMorpho pgf mos opts)) (optClitics opts) .
|
||||
concatMap words $ toStrings ts,
|
||||
exec = needPGF $ \opts ts pgf -> do
|
||||
concr <- optLang pgf opts
|
||||
case opts of
|
||||
_ | isOpt "raw" opts ->
|
||||
return . fromString .
|
||||
unlines . map (unwords . map (concat . intersperse "+")) .
|
||||
map (getClitics (not . null . lookupMorpho concr) (optClitics opts)) .
|
||||
concatMap words $ toStrings ts
|
||||
_ -> return . fromStrings .
|
||||
getCliticsText (not . null . lookupMorpho concr) (optClitics opts) .
|
||||
concatMap words $ toStrings ts,
|
||||
flags = [
|
||||
("clitics","the list of possible clitics (comma-separated, no spaces)"),
|
||||
("lang", "the language of analysis")
|
||||
@@ -151,10 +144,11 @@ pgfCommands = Map.fromList [
|
||||
("file","the file to be converted (suffix .gfe must be given)"),
|
||||
("lang","the language in which to parse")
|
||||
],
|
||||
exec = needPGF $ \ opts _ pgf mos -> do
|
||||
exec = needPGF $ \opts _ pgf -> do
|
||||
let file = optFile opts
|
||||
let printer = if (isOpt "api" opts) then exprToAPI else (showExpr [])
|
||||
let conf = configureExBased pgf (optMorpho pgf mos opts) (optLang pgf opts) printer
|
||||
concr <- optLang pgf opts
|
||||
let conf = configureExBased pgf concr printer
|
||||
(file',ws) <- restricted $ parseExamplesInGrammar conf file
|
||||
if null ws then return () else putStrLn ("unknown words: " ++ unwords ws)
|
||||
return (fromString ("wrote " ++ file')),
|
||||
@@ -175,21 +169,19 @@ pgfCommands = Map.fromList [
|
||||
explanation = unlines [
|
||||
"Generates a list of random trees, by default one tree.",
|
||||
"If a tree argument is given, the command completes the Tree with values to",
|
||||
"all metavariables in the tree. The generation can be biased by probabilities,",
|
||||
"given in a file in the -probs flag."
|
||||
"all metavariables in the tree. The generation can be biased by probabilities",
|
||||
"if the grammar was compiled with option -probs"
|
||||
],
|
||||
flags = [
|
||||
("cat","generation category"),
|
||||
("lang","uses only functions that have linearizations in all these languages"),
|
||||
("number","number of trees generated"),
|
||||
("depth","the maximum generation depth")
|
||||
("number","number of trees generated")
|
||||
],
|
||||
exec = needPGF $ \ opts arg pgf mos -> do
|
||||
exec = needPGF $ \opts arg pgf -> do
|
||||
gen <- newStdGen
|
||||
let dp = valIntOpts "depth" 4 opts
|
||||
let ts = case mexp (toExprs arg) of
|
||||
Just ex -> generateRandomFromDepth gen pgf ex (Just dp)
|
||||
Nothing -> generateRandomDepth gen pgf (optType pgf opts) (Just dp)
|
||||
Just ex -> generateRandomFrom gen pgf ex
|
||||
Nothing -> generateRandom gen pgf (optType pgf opts)
|
||||
returnFromExprs $ take (optNum opts) ts
|
||||
}),
|
||||
|
||||
@@ -197,29 +189,25 @@ pgfCommands = Map.fromList [
|
||||
longname = "generate_trees",
|
||||
synopsis = "generates a list of trees, by default exhaustive",
|
||||
explanation = unlines [
|
||||
"Generates all trees of a given category. By default, ",
|
||||
"the depth is limited to 4, but this can be changed by a flag.",
|
||||
"Generates all trees of a given category.",
|
||||
"If a Tree argument is given, the command completes the Tree with values",
|
||||
"to all metavariables in the tree."
|
||||
],
|
||||
flags = [
|
||||
("cat","the generation category"),
|
||||
("depth","the maximum generation depth"),
|
||||
("lang","excludes functions that have no linearization in this language"),
|
||||
("number","the number of trees generated")
|
||||
],
|
||||
examples = [
|
||||
mkEx "gt -- all trees in the startcat, to depth 4",
|
||||
mkEx "gt -- all trees in the startcat",
|
||||
mkEx "gt -cat=NP -number=16 -- 16 trees in the category NP",
|
||||
mkEx "gt -cat=NP -depth=2 -- trees in the category NP to depth 2",
|
||||
mkEx "gt (AdjCN ? (UseN ?)) -- trees of form (AdjCN ? (UseN ?))"
|
||||
],
|
||||
exec = needPGF $ \opts arg pgf mos -> do
|
||||
let dp = valIntOpts "depth" 4 opts
|
||||
exec = needPGF $ \opts arg pgf -> do
|
||||
let ts = case mexp (toExprs arg) of
|
||||
Just ex -> generateFromDepth pgf ex (Just dp)
|
||||
Nothing -> generateAllDepth pgf (optType pgf opts) (Just dp)
|
||||
returnFromExprs $ take (optNumInf opts) ts
|
||||
Just ex -> generateAllFrom pgf ex
|
||||
Nothing -> generateAll pgf (optType pgf opts)
|
||||
returnFromExprs $ take (optNumInf opts) (map fst ts)
|
||||
}),
|
||||
|
||||
("i", emptyCommandInfo {
|
||||
@@ -253,22 +241,17 @@ pgfCommands = Map.fromList [
|
||||
longname = "linearize",
|
||||
synopsis = "convert an abstract syntax expression to string",
|
||||
explanation = unlines [
|
||||
"Shows the linearization of a Tree by the grammars in scope.",
|
||||
"Shows the linearization of a tree by the grammars in scope.",
|
||||
"The -lang flag can be used to restrict this to fewer languages.",
|
||||
"A sequence of string operations (see command ps) can be given",
|
||||
"as options, and works then like a pipe to the ps command, except",
|
||||
"that it only affect the strings, not e.g. the table labels.",
|
||||
"These can be given separately to each language with the unlexer flag",
|
||||
"whose results are prepended to the other lexer flags. The value of the",
|
||||
"unlexer flag is a space-separated list of comma-separated string operation",
|
||||
"sequences; see example."
|
||||
"that it only affect the strings, not e.g. the table labels."
|
||||
],
|
||||
examples = [
|
||||
mkEx "l -lang=LangSwe,LangNor no_Utt -- linearize tree to LangSwe and LangNor",
|
||||
mkEx "gr -lang=LangHin -cat=Cl | l -table -to_devanagari -- hindi table",
|
||||
mkEx "l -unlexer=\"LangAra=to_arabic LangHin=to_devanagari\" -- different unlexers"
|
||||
mkEx "gr -lang=LangHin -cat=Cl | l -table -to_devanagari -- hindi table"
|
||||
],
|
||||
exec = needPGF $ \ opts ts pgf mos -> return . fromStrings . optLins pgf opts $ toExprs ts,
|
||||
exec = needPGF $ \ opts ts pgf -> return . fromStrings . optLins pgf opts $ toExprs ts,
|
||||
options = [
|
||||
("all", "show all forms and variants, one by line (cf. l -list)"),
|
||||
("bracket","show tree structure with brackets and paths to nodes"),
|
||||
@@ -279,8 +262,7 @@ pgfCommands = Map.fromList [
|
||||
("treebank","show the tree and tag linearizations with language names")
|
||||
] ++ stringOpOptions,
|
||||
flags = [
|
||||
("lang","the languages of linearization (comma-separated, no spaces)"),
|
||||
("unlexer","set unlexers separately to each language (space-separated)")
|
||||
("lang","the languages of linearization (comma-separated, no spaces)")
|
||||
]
|
||||
}),
|
||||
|
||||
@@ -291,18 +273,20 @@ pgfCommands = Map.fromList [
|
||||
"Prints all the analyses of space-separated words in the input string,",
|
||||
"using the morphological analyser of the actual grammar (see command pg)"
|
||||
],
|
||||
exec = needPGF $ \opts ts pgf mos -> case opts of
|
||||
_ | isOpt "missing" opts ->
|
||||
return . fromString . unwords .
|
||||
morphoMissing (optMorpho pgf mos opts) .
|
||||
concatMap words $ toStrings ts
|
||||
_ | isOpt "known" opts ->
|
||||
return . fromString . unwords .
|
||||
morphoKnown (optMorpho pgf mos opts) .
|
||||
concatMap words $ toStrings ts
|
||||
_ -> return . fromString . unlines .
|
||||
map prMorphoAnalysis . concatMap (morphos pgf mos opts) .
|
||||
concatMap words $ toStrings ts,
|
||||
exec = needPGF $ \opts ts pgf -> do
|
||||
concr <- optLang pgf opts
|
||||
case opts of
|
||||
_ | isOpt "missing" opts ->
|
||||
return . fromString . unwords .
|
||||
morphoMissing concr .
|
||||
concatMap words $ toStrings ts
|
||||
_ | isOpt "known" opts ->
|
||||
return . fromString . unwords .
|
||||
morphoKnown concr .
|
||||
concatMap words $ toStrings ts
|
||||
_ -> return . fromString . unlines .
|
||||
map prMorphoAnalysis . concatMap (morphos pgf opts) .
|
||||
concatMap words $ toStrings ts,
|
||||
flags = [
|
||||
("lang","the languages of analysis (comma-separated, no spaces)")
|
||||
],
|
||||
@@ -316,8 +300,8 @@ pgfCommands = Map.fromList [
|
||||
longname = "morpho_quiz",
|
||||
synopsis = "start a morphology quiz",
|
||||
syntax = "mq (-cat=CAT)? (-probs=FILE)? TREE?",
|
||||
exec = needPGF $ \ opts arg pgf mos -> do
|
||||
let lang = optLang pgf opts
|
||||
exec = needPGF $ \ opts arg pgf -> do
|
||||
lang <- optLang pgf opts
|
||||
let typ = optType pgf opts
|
||||
let mt = mexp (toExprs arg)
|
||||
restricted $ morphologyQuiz mt pgf lang typ
|
||||
@@ -336,22 +320,13 @@ pgfCommands = Map.fromList [
|
||||
"Shows all trees returned by parsing a string in the grammars in scope.",
|
||||
"The -lang flag can be used to restrict this to fewer languages.",
|
||||
"The default start category can be overridden by the -cat flag.",
|
||||
"See also the ps command for lexing and character encoding.",
|
||||
"",
|
||||
"The -openclass flag is experimental and allows some robustness in ",
|
||||
"the parser. For example if -openclass=\"A,N,V\" is given, the parser",
|
||||
"will accept unknown adjectives, nouns and verbs with the resource grammar."
|
||||
"See also the ps command for lexing and character encoding."
|
||||
],
|
||||
exec = needPGF $ \opts ts pgf mos ->
|
||||
exec = needPGF $ \opts ts pgf ->
|
||||
return $ fromParse opts (concat [map ((,) s) (par pgf opts s) | s <- toStrings ts]),
|
||||
flags = [
|
||||
("cat","target category of parsing"),
|
||||
("lang","the languages of parsing (comma-separated, no spaces)"),
|
||||
("openclass","list of open-class categories for robust parsing"),
|
||||
("depth","maximal depth for proof search if the abstract syntax tree has meta variables")
|
||||
],
|
||||
options = [
|
||||
("bracket","prints the bracketed string from the parser")
|
||||
("lang","the languages of parsing (comma-separated, no spaces)")
|
||||
]
|
||||
}),
|
||||
|
||||
@@ -374,7 +349,7 @@ pgfCommands = Map.fromList [
|
||||
" " ++ opt ++ "\t\t" ++ expl |
|
||||
((opt,_),expl) <- outputFormatsExpl, take 1 expl /= "*"
|
||||
]),
|
||||
exec = needPGF $ \opts _ pgf mos -> prGrammar pgf mos opts,
|
||||
exec = needPGF $ \opts _ pgf -> prGrammar pgf opts,
|
||||
flags = [
|
||||
--"cat",
|
||||
("file", "set the file name when printing with -pgf option"),
|
||||
@@ -410,7 +385,7 @@ pgfCommands = Map.fromList [
|
||||
examples = [
|
||||
mkEx "pt -compute (plus one two) -- compute value"
|
||||
],
|
||||
exec = needPGF $ \opts arg pgf mos ->
|
||||
exec = needPGF $ \opts arg pgf ->
|
||||
returnFromExprs . takeOptNum opts . treeOps pgf opts $ toExprs arg,
|
||||
options = treeOpOptions undefined{-pgf-},
|
||||
flags = [("number","take at most this many trees")] ++ treeOpFlags undefined{-pgf-}
|
||||
@@ -430,7 +405,7 @@ pgfCommands = Map.fromList [
|
||||
("lines","return the list of lines, instead of the singleton of all contents"),
|
||||
("tree","convert strings into trees")
|
||||
],
|
||||
exec = needPGF $ \ opts _ pgf mos -> do
|
||||
exec = needPGF $ \ opts _ pgf -> do
|
||||
let file = valStrOpts "file" "_gftmp" opts
|
||||
let exprs [] = ([],empty)
|
||||
exprs ((n,s):ls) | null s
|
||||
@@ -439,7 +414,7 @@ pgfCommands = Map.fromList [
|
||||
Just e -> let (es,err) = exprs ls
|
||||
in case inferExpr pgf e of
|
||||
Right (e,t) -> (e:es,err)
|
||||
Left tcerr -> (es,"on line" <+> n <> ':' $$ nest 2 (ppTcError tcerr) $$ err)
|
||||
Left err -> (es,"on line" <+> n <> ':' $$ nest 2 err $$ err)
|
||||
Nothing -> let (es,err) = exprs ls
|
||||
in (es,"on line" <+> n <> ':' <+> "parse error" $$ err)
|
||||
returnFromLines ls = case exprs ls of
|
||||
@@ -457,38 +432,13 @@ pgfCommands = Map.fromList [
|
||||
flags = [("file","the input file name")]
|
||||
}),
|
||||
|
||||
("rt", emptyCommandInfo {
|
||||
longname = "rank_trees",
|
||||
synopsis = "show trees in an order of decreasing probability",
|
||||
explanation = unlines [
|
||||
"Order trees from the most to the least probable, using either",
|
||||
"even distribution in each category (default) or biased as specified",
|
||||
"by the file given by flag -probs=FILE, where each line has the form",
|
||||
"'function probability', e.g. 'youPol_Pron 0.01'."
|
||||
],
|
||||
exec = needPGF $ \ opts arg pgf mos -> do
|
||||
let ts = toExprs arg
|
||||
let tds = rankTreesByProbs pgf ts
|
||||
if isOpt "v" opts
|
||||
then putStrLn $
|
||||
unlines [showExpr [] t ++ "\t--" ++ show d | (t,d) <- tds]
|
||||
else return ()
|
||||
returnFromExprs $ map fst tds,
|
||||
options = [
|
||||
("v","show all trees with their probability scores")
|
||||
],
|
||||
examples = [
|
||||
mkEx "p \"you are here\" | rt -probs=probs | pt -number=1 -- most probable result"
|
||||
]
|
||||
}),
|
||||
|
||||
("tq", emptyCommandInfo {
|
||||
longname = "translation_quiz",
|
||||
syntax = "tq -from=LANG -to=LANG (-cat=CAT)? (-probs=FILE)? TREE?",
|
||||
synopsis = "start a translation quiz",
|
||||
exec = needPGF $ \ opts arg pgf mos -> do
|
||||
let from = optLangFlag "from" pgf opts
|
||||
let to = optLangFlag "to" pgf opts
|
||||
exec = needPGF $ \ opts arg pgf -> do
|
||||
from <- optLangFlag "from" pgf opts
|
||||
to <- optLangFlag "to" pgf opts
|
||||
let typ = optType pgf opts
|
||||
let mt = mexp (toExprs arg)
|
||||
restricted $ translationQuiz mt pgf from to typ
|
||||
@@ -522,7 +472,7 @@ pgfCommands = Map.fromList [
|
||||
"flag -format. Results from multiple trees are combined to pdf with convert (ImageMagick).",
|
||||
"See also 'vp -showdep' for another visualization of dependencies."
|
||||
],
|
||||
exec = needPGF $ \ opts arg pgf mos -> do
|
||||
exec = needPGF $ \ opts arg pgf -> do
|
||||
let absname = abstractName pgf
|
||||
let es = toExprs arg
|
||||
let debug = isOpt "v" opts
|
||||
@@ -535,8 +485,8 @@ pgfCommands = Map.fromList [
|
||||
mclab <- case cnclabels of
|
||||
"" -> return Nothing
|
||||
_ -> (Just . getCncDepLabels) `fmap` restricted (readFile cnclabels)
|
||||
let lang = optLang pgf opts
|
||||
let grphs = map (graphvizDependencyTree outp debug mlab mclab pgf lang) es
|
||||
concr <- optLang pgf opts
|
||||
let grphs = map (graphvizDependencyTree outp debug mlab mclab concr) es
|
||||
if isOpt "conll2latex" opts
|
||||
then return $ fromString $ conlls2latexDoc $ stanzas $ unlines $ toStrings arg
|
||||
else if isFlag "view" opts && valStrOpts "output" "" opts == "latex"
|
||||
@@ -582,9 +532,8 @@ pgfCommands = Map.fromList [
|
||||
"by the view flag. The target format is png, unless overridden by the",
|
||||
"flag -format. Results from multiple trees are combined to pdf with convert (ImageMagick)."
|
||||
],
|
||||
exec = needPGF $ \ opts arg pgf mos -> do
|
||||
let es = toExprs arg
|
||||
let lang = optLang pgf opts
|
||||
exec = needPGF $ \opts arg pgf -> do
|
||||
let es = toExprs arg
|
||||
let gvOptions = GraphvizOptions {noLeaves = isOpt "noleaves" opts && not (isOpt "showleaves" opts),
|
||||
noFun = isOpt "nofun" opts || not (isOpt "showfun" opts),
|
||||
noCat = isOpt "nocat" opts && not (isOpt "showcat" opts),
|
||||
@@ -597,10 +546,11 @@ pgfCommands = Map.fromList [
|
||||
leafEdgeStyle = valStrOpts "leafedgestyle" "dashed" opts
|
||||
}
|
||||
let depfile = valStrOpts "file" "" opts
|
||||
concr <- optLang pgf opts
|
||||
mlab <- case depfile of
|
||||
"" -> return Nothing
|
||||
_ -> (Just . getDepLabels) `fmap` restricted (readFile depfile)
|
||||
let grphs = map (graphvizParseTreeDep mlab pgf lang gvOptions) es
|
||||
let grphs = map (graphvizDependencyTree "dot" False mlab Nothing concr) es
|
||||
if isFlag "view" opts || isFlag "format" opts
|
||||
then do
|
||||
let view = optViewGraph opts
|
||||
@@ -647,7 +597,7 @@ pgfCommands = Map.fromList [
|
||||
"flag -format. Results from multiple trees are combined to pdf with convert (ImageMagick).",
|
||||
"With option -mk, use for showing library style function names of form 'mkC'."
|
||||
],
|
||||
exec = needPGF $ \ opts arg pgf mos ->
|
||||
exec = needPGF $ \opts arg pgf ->
|
||||
let es = toExprs arg in
|
||||
if isOpt "mk" opts
|
||||
then return $ fromString $ unlines $ map (tree2mk pgf) es
|
||||
@@ -659,7 +609,7 @@ pgfCommands = Map.fromList [
|
||||
else do
|
||||
let funs = not (isOpt "nofun" opts)
|
||||
let cats = not (isOpt "nocat" opts)
|
||||
let grphs = map (graphvizAbstractTree pgf (funs,cats)) es
|
||||
let grphs = map (graphvizAbstractTree pgf (graphvizDefaults{noFun=funs,noCat=cats})) es
|
||||
if isFlag "view" opts || isFlag "format" opts
|
||||
then do
|
||||
let view = optViewGraph opts
|
||||
@@ -694,7 +644,7 @@ pgfCommands = Map.fromList [
|
||||
"If a whole expression is given it prints the expression with refined",
|
||||
"metavariables and the type of the expression."
|
||||
],
|
||||
exec = needPGF $ \opts arg pgf mos -> do
|
||||
exec = needPGF $ \opts arg pgf -> do
|
||||
case toExprs arg of
|
||||
[e] -> case unApp e of
|
||||
Just (id, []) -> case functionType pgf id of
|
||||
@@ -702,7 +652,7 @@ pgfCommands = Map.fromList [
|
||||
putStrLn ("Probability: "++show (treeProbability pgf e))
|
||||
return void
|
||||
Nothing -> case categoryContext pgf id of
|
||||
Just hypos -> do putStrLn ("cat "++showCId id++if null hypos then "" else ' ':showContext [] hypos)
|
||||
Just hypos -> do putStrLn ("cat "++id++if null hypos then "" else ' ':showContext [] hypos)
|
||||
let ls = [showFun pgf fn ty | fn <- functionsByCat pgf id, Just ty <- [functionType pgf fn]]
|
||||
if null ls
|
||||
then return ()
|
||||
@@ -712,7 +662,7 @@ pgfCommands = Map.fromList [
|
||||
Nothing -> do putStrLn ("unknown category of function identifier "++show id)
|
||||
return void
|
||||
_ -> case inferExpr pgf e of
|
||||
Left tcErr -> error $ render (ppTcError tcErr)
|
||||
Left err -> error err
|
||||
Right (e,ty) -> do putStrLn ("Expression: "++showExpr [] e)
|
||||
putStrLn ("Type: "++showType [] ty)
|
||||
putStrLn ("Probability: "++show (treeProbability pgf e))
|
||||
@@ -724,14 +674,12 @@ pgfCommands = Map.fromList [
|
||||
]
|
||||
where
|
||||
needPGF exec opts ts = do
|
||||
Env mb_pgf mos <- getPGFEnv
|
||||
mb_pgf <- getPGF
|
||||
case mb_pgf of
|
||||
Just pgf -> liftSIO $ exec opts ts pgf mos
|
||||
Just pgf -> liftSIO $ exec opts ts pgf
|
||||
_ -> fail "Import a grammar before using this command"
|
||||
|
||||
par pgf opts s = [parse_ pgf lang (optType pgf opts) (Just dp) s | lang <- optLangs pgf opts]
|
||||
where
|
||||
dp = valIntOpts "depth" 4 opts
|
||||
par pgf opts s = [parse concr (optType pgf opts) s | concr <- optLangs pgf opts]
|
||||
|
||||
fromParse opts = foldr (joinPiped . fromParse1 opts) void
|
||||
|
||||
@@ -740,49 +688,39 @@ pgfCommands = Map.fromList [
|
||||
jA (Exprs es1) (Exprs es2) = Exprs (es1++es2)
|
||||
-- ^ fromParse1 always output Exprs
|
||||
|
||||
fromParse1 opts (s,(po,bs))
|
||||
| isOpt "bracket" opts = pipeMessage (showBracketedString bs)
|
||||
| otherwise =
|
||||
fromParse1 opts (s,po) =
|
||||
case po of
|
||||
ParseOk ts -> fromExprs ts
|
||||
ParseFailed i -> pipeMessage $ "The parser failed at token "
|
||||
ParseOk ts -> fromExprs (map fst ts)
|
||||
ParseFailed i _ -> pipeMessage $ "The parser failed at token "
|
||||
++ show i ++": "
|
||||
++ show (words s !! max 0 (i-1))
|
||||
-- ++ " in " ++ show s
|
||||
ParseIncomplete -> pipeMessage "The sentence is not complete"
|
||||
TypeError errs ->
|
||||
pipeMessage . render $
|
||||
"The parsing is successful but the type checking failed with error(s):"
|
||||
$$ nest 2 (vcat (map (ppTcError . snd) errs))
|
||||
|
||||
optLins pgf opts ts = case opts of
|
||||
_ | isOpt "groups" opts ->
|
||||
concatMap snd $ groupResults
|
||||
[[(lang, s) | lang <- optLangs pgf opts,s <- linear pgf opts lang t] | t <- ts]
|
||||
_ -> concatMap (optLin pgf opts) ts
|
||||
optLins pgf opts ts = concatMap (optLin pgf opts) ts
|
||||
optLin pgf opts t =
|
||||
case opts of
|
||||
_ | isOpt "treebank" opts && isOpt "chunks" opts ->
|
||||
(showCId (abstractName pgf) ++ ": " ++ showExpr [] t) :
|
||||
[showCId lang ++ ": " ++ li | (lang,li) <- linChunks pgf opts t] --linear pgf opts lang t | lang <- optLangs pgf opts]
|
||||
(abstractName pgf ++ ": " ++ showExpr [] t) :
|
||||
[lang ++ ": " ++ li | (lang,li) <- linChunks pgf opts t] --linear pgf opts lang t | lang <- optLangs pgf opts]
|
||||
_ | isOpt "treebank" opts ->
|
||||
(showCId (abstractName pgf) ++ ": " ++ showExpr [] t) :
|
||||
[showCId lang ++ ": " ++ s | lang <- optLangs pgf opts, s<-linear pgf opts lang t]
|
||||
(abstractName pgf ++ ": " ++ showExpr [] t) :
|
||||
[concreteName concr ++ ": " ++ s | concr <- optLangs pgf opts, s<-linear opts concr t]
|
||||
_ | isOpt "chunks" opts -> map snd $ linChunks pgf opts t
|
||||
_ -> [s | lang <- optLangs pgf opts, s<-linear pgf opts lang t]
|
||||
_ -> [s | concr <- optLangs pgf opts, s <- linear opts concr t]
|
||||
linChunks pgf opts t =
|
||||
[(lang, unwords (intersperse "<+>" (map (unlines . linear pgf opts lang) (treeChunks t)))) | lang <- optLangs pgf opts]
|
||||
[(concreteName concr, unwords (intersperse "<+>" (map (unlines . linear opts concr) (treeChunks t)))) | concr <- optLangs pgf opts]
|
||||
|
||||
linear :: PGF -> [Option] -> CId -> Expr -> [String]
|
||||
linear pgf opts lang = let unl = unlex opts lang in case opts of
|
||||
_ | isOpt "all" opts -> concat . -- intersperse [[]] .
|
||||
map (map (unl . snd)) . tabularLinearizes pgf lang
|
||||
linear :: [Option] -> Concr -> Expr -> [String]
|
||||
linear opts concr = case opts of
|
||||
_ | isOpt "all" opts -> concat .
|
||||
map (map snd) . tabularLinearizeAll concr
|
||||
_ | isOpt "list" opts -> (:[]) . commaList . concat .
|
||||
map (map (unl . snd)) . tabularLinearizes pgf lang
|
||||
_ | isOpt "table" opts -> concat . -- intersperse [[]] .
|
||||
map (map (\(p,v) -> p+++":"+++unl v)) . tabularLinearizes pgf lang
|
||||
_ | isOpt "bracket" opts -> (:[]) . unwords . map showBracketedString . bracketedLinearize pgf lang
|
||||
_ -> (:[]) . unl . linearize pgf lang
|
||||
map (map snd) . tabularLinearizeAll concr
|
||||
_ | isOpt "table" opts -> concat .
|
||||
map (map (\(p,v) -> p+++":"+++v)) . tabularLinearizeAll concr
|
||||
_ | isOpt "bracket" opts -> (:[]) . unwords . map showBracketedString . bracketedLinearize concr
|
||||
_ -> (:[]) . linearize concr
|
||||
|
||||
-- replace each non-atomic constructor with mkC, where C is the val cat
|
||||
tree2mk pgf = showExpr [] . t2m where
|
||||
@@ -791,61 +729,38 @@ pgfCommands = Map.fromList [
|
||||
_ -> t
|
||||
mk f = case functionType pgf f of
|
||||
Just ty -> let (_,cat,_) = unType ty
|
||||
in mkCId ("mk" ++ showCId cat)
|
||||
in "mk" ++ cat
|
||||
Nothing -> f
|
||||
|
||||
unlex opts lang = stringOps Nothing (getUnlex opts lang ++ map prOpt opts) ----
|
||||
|
||||
getUnlex opts lang = case words (valStrOpts "unlexer" "" opts) of
|
||||
lexs -> case lookup lang
|
||||
[(mkCId la,tail le) | lex <- lexs, let (la,le) = span (/='=') lex, not (null le)] of
|
||||
Just le -> chunks ',' le
|
||||
_ -> []
|
||||
|
||||
commaList [] = []
|
||||
commaList ws = concat $ head ws : map (", " ++) (tail ws)
|
||||
|
||||
-- Proposed logic of coding in unlexing:
|
||||
-- - If lang has no coding flag, or -to_utf8 is not in opts, just opts are used.
|
||||
-- - If lang has flag coding=utf8, -to_utf8 is ignored.
|
||||
-- - If lang has coding=other, and -to_utf8 is in opts, from_other is applied first.
|
||||
-- THIS DOES NOT WORK UNFORTUNATELY - can't use the grammar flag properly
|
||||
{-
|
||||
unlexx pgf opts lang = {- trace (unwords optsC) $ -} stringOps Nothing optsC where ----
|
||||
optsC = case lookConcrFlag pgf (mkCId lang) (mkCId "coding") of
|
||||
Just (LStr "utf8") -> filter (/="to_utf8") $ map prOpt opts
|
||||
Just (LStr other) | isOpt "to_utf8" opts ->
|
||||
let cod = ("from_" ++ other)
|
||||
in cod : filter (/=cod) (map prOpt opts)
|
||||
_ -> map prOpt opts
|
||||
-}
|
||||
|
||||
optLang = optLangFlag "lang"
|
||||
optLangs = optLangsFlag "lang"
|
||||
|
||||
optLangsFlag f pgf opts = case valStrOpts f "" opts of
|
||||
"" -> languages pgf
|
||||
lang -> map (completeLang pgf) (chunks ',' lang)
|
||||
completeLang pgf la = let cla = (mkCId la) in
|
||||
if elem cla (languages pgf)
|
||||
then cla
|
||||
else (mkCId (showCId (abstractName pgf) ++ la))
|
||||
optLangFlag flag pgf opts =
|
||||
case optLangsFlag flag pgf opts of
|
||||
[] -> fail "no language specified"
|
||||
(l:ls) -> return l
|
||||
|
||||
optLangsFlag flag pgf opts =
|
||||
case valStrOpts flag "" opts of
|
||||
"" -> Map.elems langs
|
||||
str -> mapMaybe (completeLang pgf) (chunks ',' str)
|
||||
where
|
||||
langs = languages pgf
|
||||
|
||||
completeLang pgf la =
|
||||
mplus (Map.lookup la langs)
|
||||
(Map.lookup (abstractName pgf ++ la) langs)
|
||||
|
||||
optLangFlag f pgf opts = head $ optLangsFlag f pgf opts ++ [wildCId]
|
||||
{-
|
||||
optProbs opts pgf = case valStrOpts "probs" "" opts of
|
||||
"" -> return pgf
|
||||
file -> do
|
||||
probs <- restricted $ readProbabilitiesFromFile file pgf
|
||||
return (setProbabilities probs pgf)
|
||||
-}
|
||||
optFile opts = valStrOpts "file" "_gftmp" opts
|
||||
|
||||
optType pgf opts =
|
||||
let readOpt str = case readType str of
|
||||
Just ty -> case checkType pgf ty of
|
||||
Left tcErr -> error $ render (ppTcError tcErr)
|
||||
Right ty -> ty
|
||||
Left err -> error err
|
||||
Right ty -> ty
|
||||
Nothing -> error ("Can't parse '"++str++"' as a type")
|
||||
in maybeStrOpts "cat" (startCat pgf) readOpt opts
|
||||
optViewFormat opts = valStrOpts "format" "png" opts
|
||||
@@ -858,35 +773,31 @@ pgfCommands = Map.fromList [
|
||||
[] -> pipeMessage "no trees found"
|
||||
_ -> fromExprs es
|
||||
|
||||
prGrammar pgf mos opts
|
||||
prGrammar pgf opts
|
||||
| isOpt "pgf" opts = do
|
||||
let outfile = valStrOpts "file" (showCId (abstractName pgf) ++ ".pgf") opts
|
||||
let outfile = valStrOpts "file" (abstractName pgf ++ ".pgf") opts
|
||||
restricted $ writePGF outfile pgf
|
||||
putStrLn $ "wrote file " ++ outfile
|
||||
return void
|
||||
| isOpt "cats" opts = return $ fromString $ unwords $ map showCId $ categories pgf
|
||||
| isOpt "cats" opts = return $ fromString $ unwords $ categories pgf
|
||||
| isOpt "funs" opts = return $ fromString $ unlines [showFun pgf f ty | f <- functions pgf, Just ty <- [functionType pgf f]]
|
||||
| isOpt "fullform" opts = return $ fromString $ concatMap (morpho mos "" prFullFormLexicon) $ optLangs pgf opts
|
||||
| isOpt "langs" opts = return $ fromString $ unwords $ map showCId $ languages pgf
|
||||
| isOpt "fullform" opts = return $ fromString $ concatMap prFullFormLexicon $ optLangs pgf opts
|
||||
| isOpt "langs" opts = return $ fromString $ unwords $ Map.keys $ languages pgf
|
||||
|
||||
| isOpt "lexc" opts = return $ fromString $ concatMap (morpho mos "" prLexcLexicon) $ optLangs pgf opts
|
||||
| isOpt "missing" opts = return $ fromString $ unlines $ [unwords (showCId la:":":[showCId f | f <- functions pgf, not (hasLinearization pgf la f)]) |
|
||||
la <- optLangs pgf opts]
|
||||
| isOpt "words" opts = return $ fromString $ concatMap (morpho mos "" prAllWords) $ optLangs pgf opts
|
||||
| isOpt "lexc" opts = return $ fromString $ concatMap prLexcLexicon $ optLangs pgf opts
|
||||
| isOpt "missing" opts = return $ fromString $ unlines $ [unwords (concreteName concr:":":[f | f <- functions pgf, not (hasLinearization concr f)]) |
|
||||
concr <- optLangs pgf opts]
|
||||
| isOpt "words" opts = return $ fromString $ concatMap prAllWords $ optLangs pgf opts
|
||||
| otherwise = do fmt <- readOutputFormat (valStrOpts "printer" "pgf_pretty" opts)
|
||||
return $ fromString $ concatMap snd $ exportPGF noOptions fmt pgf
|
||||
|
||||
showFun pgf id ty = kwd++" "++showCId id ++ " : " ++ showType [] ty
|
||||
showFun pgf id ty = kwd++" "++ id ++ " : " ++ showType [] ty
|
||||
where
|
||||
kwd | functionIsDataCon pgf id = "data"
|
||||
| otherwise = "fun"
|
||||
|
||||
morphos pgf mos opts s =
|
||||
[(s,morpho mos [] (\mo -> lookupMorpho mo s) la) | la <- optLangs pgf opts]
|
||||
|
||||
morpho mos z f la = maybe z f $ Map.lookup la mos
|
||||
|
||||
optMorpho pgf mos opts = morpho mos (error "no morpho") id (head (optLangs pgf opts))
|
||||
morphos pgf opts s =
|
||||
[(s,lookupMorpho concr s) | concr <- optLangs pgf opts]
|
||||
|
||||
optClitics opts = case valStrOpts "clitics" "" opts of
|
||||
"" -> []
|
||||
@@ -899,18 +810,28 @@ pgfCommands = Map.fromList [
|
||||
-- ps -f -g s returns g (f s)
|
||||
treeOps pgf opts s = foldr app s (reverse opts) where
|
||||
app (OOpt op) | Just (Left f) <- treeOp pgf op = f
|
||||
app (OFlag op (VId x)) | Just (Right f) <- treeOp pgf op = f (mkCId x)
|
||||
app (OFlag op (VId x)) | Just (Right f) <- treeOp pgf op = f x
|
||||
app _ = id
|
||||
|
||||
morphoMissing :: Concr -> [String] -> [String]
|
||||
morphoMissing = morphoClassify False
|
||||
|
||||
morphoKnown :: Concr -> [String] -> [String]
|
||||
morphoKnown = morphoClassify True
|
||||
|
||||
morphoClassify :: Bool -> Concr -> [String] -> [String]
|
||||
morphoClassify k concr ws = [w | w <- ws, k /= null (lookupMorpho concr w), notLiteral w] where
|
||||
notLiteral w = not (all isDigit w)
|
||||
|
||||
treeOpOptions pgf = [(op,expl) | (op,(expl,Left _)) <- allTreeOps pgf]
|
||||
treeOpFlags pgf = [(op,expl) | (op,(expl,Right _)) <- allTreeOps pgf]
|
||||
|
||||
translationQuiz :: Maybe Expr -> PGF -> Language -> Language -> Type -> IO ()
|
||||
translationQuiz :: Maybe Expr -> PGF -> Concr -> Concr -> Type -> IO ()
|
||||
translationQuiz mex pgf ig og typ = do
|
||||
tts <- translationList mex pgf ig og typ infinity
|
||||
mkQuiz "Welcome to GF Translation Quiz." tts
|
||||
|
||||
morphologyQuiz :: Maybe Expr -> PGF -> Language -> Type -> IO ()
|
||||
morphologyQuiz :: Maybe Expr -> PGF -> Concr -> Type -> IO ()
|
||||
morphologyQuiz mex pgf ig typ = do
|
||||
tts <- morphologyList mex pgf ig typ infinity
|
||||
mkQuiz "Welcome to GF Morphology Quiz." tts
|
||||
@@ -919,28 +840,28 @@ morphologyQuiz mex pgf ig typ = do
|
||||
infinity :: Int
|
||||
infinity = 256
|
||||
|
||||
prLexcLexicon :: Morpho -> String
|
||||
prLexcLexicon mo =
|
||||
unlines $ "Multichar_Symbols":multichars:"":"LEXICON Root" : [prLexc l p ++ ":" ++ w ++ " # ;" | (w,lps) <- morpho, (l,p) <- lps] ++ ["END"]
|
||||
prLexcLexicon :: Concr -> String
|
||||
prLexcLexicon concr =
|
||||
unlines $ "Multichar_Symbols":multichars:"":"LEXICON Root" : [prLexc l p ++ ":" ++ w ++ " # ;" | (w,lps) <- morpho, (l,p,_) <- lps] ++ ["END"]
|
||||
where
|
||||
morpho = fullFormLexicon mo
|
||||
prLexc l p = showCId l ++ concat (mkTags (words p))
|
||||
morpho = fullFormLexicon concr
|
||||
prLexc l p = l ++ concat (mkTags (words p))
|
||||
mkTags p = case p of
|
||||
"s":ws -> mkTags ws --- remove record field
|
||||
ws -> map ('+':) ws
|
||||
|
||||
multichars = unwords $ nub $ concat [mkTags (words p) | (w,lps) <- morpho, (l,p) <- lps]
|
||||
multichars = unwords $ nub $ concat [mkTags (words p) | (w,lps) <- morpho, (l,p,_) <- lps]
|
||||
|
||||
prFullFormLexicon :: Morpho -> String
|
||||
prFullFormLexicon mo =
|
||||
unlines (map prMorphoAnalysis (fullFormLexicon mo))
|
||||
prFullFormLexicon :: Concr -> String
|
||||
prFullFormLexicon concr =
|
||||
unlines (map prMorphoAnalysis (fullFormLexicon concr))
|
||||
|
||||
prAllWords :: Morpho -> String
|
||||
prAllWords mo =
|
||||
unwords [w | (w,_) <- fullFormLexicon mo]
|
||||
prAllWords :: Concr -> String
|
||||
prAllWords concr =
|
||||
unwords [w | (w,_) <- fullFormLexicon concr]
|
||||
|
||||
prMorphoAnalysis (w,lps) =
|
||||
unlines (w:[showCId l ++ " : " ++ p | (l,p) <- lps])
|
||||
unlines (w:[l ++ " : " ++ p ++ show prob | (l,p,prob) <- lps])
|
||||
|
||||
viewGraphviz :: String -> String -> String -> [String] -> SIO CommandOutput
|
||||
viewGraphviz view format name grphs = do
|
||||
|
||||
@@ -1,822 +0,0 @@
|
||||
{-# LANGUAGE FlexibleInstances, UndecidableInstances #-}
|
||||
module GF.Command.Commands2 (
|
||||
PGFEnv,HasPGFEnv(..),pgf,concs,pgfEnv,emptyPGFEnv,pgfCommands,
|
||||
options, flags,
|
||||
) where
|
||||
import Prelude hiding (putStrLn,(<>)) -- GHC 8.4.1 clash with Text.PrettyPrint
|
||||
|
||||
import PGF2
|
||||
import qualified PGF as H
|
||||
import GF.Compile.ToAPI(exprToAPI)
|
||||
import GF.Infra.UseIO(writeUTF8File)
|
||||
import GF.Infra.SIO(MonadSIO,liftSIO,putStrLn,restricted,restrictedSystem)
|
||||
import GF.Command.Abstract
|
||||
import GF.Command.CommandInfo
|
||||
import GF.Data.Operations
|
||||
import Data.List(intersperse,intersect,nub,sortBy)
|
||||
import Data.Maybe
|
||||
import qualified Data.Map as Map
|
||||
import GF.Text.Pretty
|
||||
import Control.Monad(mplus)
|
||||
|
||||
|
||||
data PGFEnv = Env {pgf::Maybe PGF,concs::Map.Map ConcName Concr}
|
||||
|
||||
pgfEnv pgf = Env (Just pgf) (languages pgf)
|
||||
emptyPGFEnv = Env Nothing Map.empty
|
||||
|
||||
class (Monad m,MonadSIO m) => HasPGFEnv m where getPGFEnv :: m PGFEnv
|
||||
|
||||
instance (Monad m,HasPGFEnv m) => TypeCheckArg m where
|
||||
typeCheckArg e = do env <- getPGFEnv
|
||||
case pgf env of
|
||||
Just gr -> either fail
|
||||
(return . hsExpr . fst)
|
||||
(inferExpr gr (cExpr e))
|
||||
Nothing -> fail "Import a grammar before using this command"
|
||||
|
||||
pgfCommands :: HasPGFEnv m => Map.Map String (CommandInfo m)
|
||||
pgfCommands = Map.fromList [
|
||||
("aw", emptyCommandInfo {
|
||||
longname = "align_words",
|
||||
synopsis = "show word alignments between languages graphically",
|
||||
explanation = unlines [
|
||||
"Prints a set of strings in the .dot format (the graphviz format).",
|
||||
"The graph can be saved in a file by the wf command as usual.",
|
||||
"If the -view flag is defined, the graph is saved in a temporary file",
|
||||
"which is processed by graphviz and displayed by the program indicated",
|
||||
"by the flag. The target format is postscript, unless overridden by the",
|
||||
"flag -format."
|
||||
],
|
||||
exec = needPGF $ \opts es env -> do
|
||||
let cncs = optConcs env opts
|
||||
if isOpt "giza" opts
|
||||
then if length cncs == 2
|
||||
then let giz = map (gizaAlignment pgf (snd (cncs !! 0)) (snd (cncs !! 1)) . cExpr) (toExprs es)
|
||||
lsrc = unlines $ map (\(x,_,_) -> x) giz
|
||||
ltrg = unlines $ map (\(_,x,_) -> x) giz
|
||||
align = unlines $ map (\(_,_,x) -> x) giz
|
||||
grph = if null (toExprs es) then [] else lsrc ++ "\n--end_source--\n\n"++ltrg++"\n-end_target--\n\n"++align
|
||||
in return (fromString grph)
|
||||
else error "For giza alignment you need exactly two languages"
|
||||
else let gvOptions=graphvizDefaults{leafFont = valStrOpts "font" "" opts,
|
||||
leafColor = valStrOpts "color" "" opts,
|
||||
leafEdgeStyle = valStrOpts "edgestyle" "" opts
|
||||
}
|
||||
grph = if null (toExprs es) then [] else graphvizWordAlignment (map snd cncs) gvOptions (cExpr (head (toExprs es)))
|
||||
in if isFlag "view" opts || isFlag "format" opts
|
||||
then do let file s = "_grph." ++ s
|
||||
let view = optViewGraph opts
|
||||
let format = optViewFormat opts
|
||||
restricted $ writeUTF8File (file "dot") grph
|
||||
restrictedSystem $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
||||
restrictedSystem $ view ++ " " ++ file format
|
||||
return void
|
||||
else return (fromString grph),
|
||||
examples = [
|
||||
("gr | aw" , "generate a tree and show word alignment as graph script"),
|
||||
("gr | aw -view=\"open\"" , "generate a tree and display alignment on Mac"),
|
||||
("gr | aw -view=\"eog\"" , "generate a tree and display alignment on Ubuntu"),
|
||||
("gt | aw -giza | wf -file=aligns" , "generate trees, send giza alignments to file")
|
||||
],
|
||||
options = [
|
||||
("giza", "show alignments in the Giza format; the first two languages")
|
||||
],
|
||||
flags = [
|
||||
("format","format of the visualization file (default \"png\")"),
|
||||
("lang", "alignments for this list of languages (default: all)"),
|
||||
("view", "program to open the resulting file"),
|
||||
("font", "font for the words"),
|
||||
("color", "color for the words"),
|
||||
("edgestyle", "the style for links between words")
|
||||
]
|
||||
}),
|
||||
{-
|
||||
("eb", emptyCommandInfo {
|
||||
longname = "example_based",
|
||||
syntax = "eb (-probs=FILE | -lang=LANG)* -file=FILE.gfe",
|
||||
synopsis = "converts .gfe files to .gf files by parsing examples to trees",
|
||||
explanation = unlines [
|
||||
"Reads FILE.gfe and writes FILE.gf. Each expression of form",
|
||||
"'%ex CAT QUOTEDSTRING' in FILE.gfe is replaced by a syntax tree.",
|
||||
"This tree is the first one returned by the parser; a biased ranking",
|
||||
"can be used to regulate the order. If there are more than one parses",
|
||||
"the rest are shown in comments, with probabilities if the order is biased.",
|
||||
"The probabilities flag and configuration file is similar to the commands",
|
||||
"gr and rt. Notice that the command doesn't change the environment,",
|
||||
"but the resulting .gf file must be imported separately."
|
||||
],
|
||||
options = [
|
||||
("api","convert trees to overloaded API expressions (using Syntax not Lang)")
|
||||
],
|
||||
flags = [
|
||||
("file","the file to be converted (suffix .gfe must be given)"),
|
||||
("lang","the language in which to parse"),
|
||||
("probs","file with probabilities to rank the parses")
|
||||
],
|
||||
exec = \env@(pgf, mos) opts _ -> do
|
||||
let file = optFile opts
|
||||
pgf <- optProbs opts pgf
|
||||
let printer = if (isOpt "api" opts) then exprToAPI else (H.showExpr [])
|
||||
let conf = configureExBased pgf (optMorpho env opts) (optLang pgf opts) printer
|
||||
(file',ws) <- restricted $ parseExamplesInGrammar conf file
|
||||
if null ws then return () else putStrLn ("unknown words: " ++ unwords ws)
|
||||
return (fromString ("wrote " ++ file')),
|
||||
needsTypeCheck = False
|
||||
}),
|
||||
-}
|
||||
{-
|
||||
("gr", emptyCommandInfo {
|
||||
longname = "generate_random",
|
||||
synopsis = "generate random trees in the current abstract syntax",
|
||||
syntax = "gr [-cat=CAT] [-number=INT]",
|
||||
examples = [
|
||||
mkEx "gr -- one tree in the startcat of the current grammar",
|
||||
mkEx "gr -cat=NP -number=16 -- 16 trees in the category NP",
|
||||
mkEx "gr -lang=LangHin,LangTha -cat=Cl -- Cl, both in LangHin and LangTha",
|
||||
mkEx "gr -probs=FILE -- generate with bias",
|
||||
mkEx "gr (AdjCN ? (UseN ?)) -- generate trees of form (AdjCN ? (UseN ?))"
|
||||
],
|
||||
explanation = unlines [
|
||||
"Generates a list of random trees, by default one tree.",
|
||||
"If a tree argument is given, the command completes the Tree with values to",
|
||||
"all metavariables in the tree. The generation can be biased by probabilities,",
|
||||
"given in a file in the -probs flag."
|
||||
],
|
||||
flags = [
|
||||
("cat","generation category"),
|
||||
("lang","uses only functions that have linearizations in all these languages"),
|
||||
("number","number of trees generated"),
|
||||
("depth","the maximum generation depth"),
|
||||
("probs", "file with biased probabilities (format 'f 0.4' one by line)")
|
||||
],
|
||||
exec = \env@(pgf, mos) opts xs -> do
|
||||
pgf <- optProbs opts (optRestricted opts pgf)
|
||||
gen <- newStdGen
|
||||
let dp = valIntOpts "depth" 4 opts
|
||||
let ts = case mexp xs of
|
||||
Just ex -> H.generateRandomFromDepth gen pgf ex (Just dp)
|
||||
Nothing -> H.generateRandomDepth gen pgf (optType pgf opts) (Just dp)
|
||||
returnFromExprs $ take (optNum opts) ts
|
||||
}),
|
||||
-}
|
||||
("gt", emptyCommandInfo {
|
||||
longname = "generate_trees",
|
||||
synopsis = "generates a list of trees, by default exhaustive",
|
||||
flags = [("cat","the generation category"),
|
||||
("number","the number of trees generated")],
|
||||
examples = [
|
||||
mkEx "gt -- all trees in the startcat",
|
||||
mkEx "gt -cat=NP -number=16 -- 16 trees in the category NP"],
|
||||
exec = needPGF $ \ opts _ env@(pgf,_) ->
|
||||
let ts = map fst (generateAll pgf cat)
|
||||
cat = optType pgf opts
|
||||
in returnFromCExprs (takeOptNum opts ts),
|
||||
needsTypeCheck = False
|
||||
}),
|
||||
("i", emptyCommandInfo {
|
||||
longname = "import",
|
||||
synopsis = "import a grammar from a compiled .pgf file",
|
||||
explanation = unlines [
|
||||
"Reads a grammar from a compiled .pgf file.",
|
||||
"Old modules are discarded.",
|
||||
{-
|
||||
"The grammar parser depends on the file name suffix:",
|
||||
|
||||
" .cf context-free (labelled BNF) source",
|
||||
" .ebnf extended BNF source",
|
||||
" .gfm multi-module GF source",
|
||||
" .gf normal GF source",
|
||||
" .gfo compiled GF source",
|
||||
-}
|
||||
" .pgf precompiled grammar in Portable Grammar Format"
|
||||
],
|
||||
flags = [
|
||||
-- ("probs","file with biased probabilities for generation")
|
||||
],
|
||||
options = [
|
||||
-- ["gfo", "src", "no-cpu", "cpu", "quiet", "verbose"]
|
||||
-- ("retain","retain operations (used for cc command)"),
|
||||
-- ("src", "force compilation from source"),
|
||||
-- ("v", "be verbose - show intermediate status information")
|
||||
],
|
||||
needsTypeCheck = False
|
||||
}),
|
||||
("l", emptyCommandInfo {
|
||||
longname = "linearize",
|
||||
synopsis = "convert an abstract syntax expression to string",
|
||||
explanation = unlines [
|
||||
"Shows the linearization of a Tree by the grammars in scope.",
|
||||
"The -lang flag can be used to restrict this to fewer languages.",
|
||||
"A sequence of string operations (see command ps) can be given",
|
||||
"as options, and works then like a pipe to the ps command, except",
|
||||
"that it only affect the strings, not e.g. the table labels.",
|
||||
"These can be given separately to each language with the unlexer flag",
|
||||
"whose results are prepended to the other lexer flags. The value of the",
|
||||
"unlexer flag is a space-separated list of comma-separated string operation",
|
||||
"sequences; see example."
|
||||
],
|
||||
examples = [
|
||||
mkEx "l -lang=LangSwe,LangNor no_Utt -- linearize a tree to LangSwe and LangNor",
|
||||
mkEx "gr -lang=LangHin -cat=Cl | l -table -to_devanagari -- hindi table",
|
||||
mkEx "l -unlexer=\"LangAra=to_arabic LangHin=to_devanagari\" -- different unlexers"
|
||||
],
|
||||
exec = needPGF $ \ opts arg env ->
|
||||
return . fromStrings . optLins env opts . map cExpr $ toExprs arg,
|
||||
options = [
|
||||
("all", "show all forms and variants, one by line (cf. l -list)"),
|
||||
("bracket","show tree structure with brackets and paths to nodes"),
|
||||
("groups", "all languages, grouped by lang, remove duplicate strings"),
|
||||
("list","show all forms and variants, comma-separated on one line (cf. l -all)"),
|
||||
("multi","linearize to all languages (default)"),
|
||||
("table","show all forms labelled by parameters"),
|
||||
("treebank","show the tree and tag linearizations with language names")
|
||||
],
|
||||
flags = [
|
||||
("lang","the languages of linearization (comma-separated, no spaces)")
|
||||
]
|
||||
}),
|
||||
("ma", emptyCommandInfo {
|
||||
longname = "morpho_analyse",
|
||||
synopsis = "print the morphological analyses of the (multiword) expression in the string",
|
||||
explanation = unlines [
|
||||
"Prints all the analyses of the (multiword) expression in the input string,",
|
||||
"using the morphological analyser of the actual grammar (see command pg)"
|
||||
],
|
||||
exec = needPGF $ \opts args env ->
|
||||
return ((fromString . unlines .
|
||||
map prMorphoAnalysis . concatMap (morphos env opts) . toStrings) args),
|
||||
flags = [
|
||||
("lang","the languages of analysis (comma-separated, no spaces)")
|
||||
]
|
||||
}),
|
||||
{-
|
||||
("mq", emptyCommandInfo {
|
||||
longname = "morpho_quiz",
|
||||
synopsis = "start a morphology quiz",
|
||||
syntax = "mq (-cat=CAT)? (-probs=FILE)? TREE?",
|
||||
exec = \env@(pgf, mos) opts xs -> do
|
||||
let lang = optLang pgf opts
|
||||
let typ = optType pgf opts
|
||||
pgf <- optProbs opts pgf
|
||||
let mt = mexp xs
|
||||
restricted $ morphologyQuiz mt pgf lang typ
|
||||
return void,
|
||||
flags = [
|
||||
("lang","language of the quiz"),
|
||||
("cat","category of the quiz"),
|
||||
("number","maximum number of questions"),
|
||||
("probs","file with biased probabilities for generation")
|
||||
]
|
||||
}),
|
||||
-}
|
||||
("p", emptyCommandInfo {
|
||||
longname = "parse",
|
||||
synopsis = "parse a string to abstract syntax expression",
|
||||
explanation = unlines [
|
||||
"Shows all trees returned by parsing a string in the grammars in scope.",
|
||||
"The -lang flag can be used to restrict this to fewer languages.",
|
||||
"The default start category can be overridden by the -cat flag.",
|
||||
"See also the ps command for lexing and character encoding."
|
||||
],
|
||||
flags = [
|
||||
("cat","target category of parsing"),
|
||||
("lang","the languages of parsing (comma-separated, no spaces)"),
|
||||
("number","maximum number of trees returned")
|
||||
],
|
||||
examples = [
|
||||
mkEx "p \"this fish is fresh\" | l -lang=Swe -- try parsing with all languages and translate the successful parses to Swedish"
|
||||
],
|
||||
exec = needPGF $ \ opts ts env -> return . cParse env opts $ toStrings ts
|
||||
}),
|
||||
("pg", emptyCommandInfo {
|
||||
longname = "print_grammar",
|
||||
synopsis = "prints different information about the grammar",
|
||||
exec = needPGF $ \opts _ env -> prGrammar env opts,
|
||||
options = [
|
||||
("cats", "show just the names of abstract syntax categories"),
|
||||
("fullform", "print the fullform lexicon"),
|
||||
("funs", "show just the names and types of abstract syntax functions"),
|
||||
("langs", "show just the names of top concrete syntax modules"),
|
||||
("lexc", "print the lexicon in Xerox LEXC format"),
|
||||
("missing","show just the names of functions that have no linearization"),
|
||||
("words", "print the list of words")
|
||||
],
|
||||
flags = [
|
||||
("lang","the languages that need to be printed")
|
||||
],
|
||||
examples = [
|
||||
mkEx "pg -langs -- show the names of top concrete syntax modules",
|
||||
mkEx "pg -funs | ? grep \" S ;\" -- show functions with value cat S"
|
||||
]
|
||||
}),
|
||||
|
||||
{-
|
||||
("pt", emptyCommandInfo {
|
||||
longname = "put_tree",
|
||||
syntax = "pt OPT? TREE",
|
||||
synopsis = "return a tree, possibly processed with a function",
|
||||
explanation = unlines [
|
||||
"Returns a tree obtained from its argument tree by applying",
|
||||
"tree processing functions in the order given in the command line",
|
||||
"option list. Thus 'pt -f -g s' returns g (f s). Typical tree processors",
|
||||
"are type checking and semantic computation."
|
||||
],
|
||||
examples = [
|
||||
mkEx "pt -compute (plus one two) -- compute value",
|
||||
mkEx "p \"4 dogs love 5 cats\" | pt -transfer=digits2numeral | l -- four...five..."
|
||||
],
|
||||
exec = \env@(pgf, mos) opts ->
|
||||
returnFromExprs . takeOptNum opts . treeOps pgf opts,
|
||||
options = treeOpOptions undefined{-pgf-},
|
||||
flags = [("number","take at most this many trees")] ++ treeOpFlags undefined{-pgf-}
|
||||
}),
|
||||
-}
|
||||
("rf", emptyCommandInfo {
|
||||
longname = "read_file",
|
||||
synopsis = "read string or tree input from a file",
|
||||
explanation = unlines [
|
||||
"Reads input from file. The filename must be in double quotes.",
|
||||
"The input is interpreted as a string by default, and can hence be",
|
||||
"piped e.g. to the parse command. The option -tree interprets the",
|
||||
"input as a tree, which can be given e.g. to the linearize command.",
|
||||
"The option -lines will result in a list of strings or trees, one by line."
|
||||
],
|
||||
options = [
|
||||
("lines","return the list of lines, instead of the singleton of all contents"),
|
||||
("tree","convert strings into trees")
|
||||
],
|
||||
exec = needPGF $ \opts _ env@(pgf, mos) -> do
|
||||
let file = optFile opts
|
||||
let exprs [] = ([],empty)
|
||||
exprs ((n,s):ls) | null s
|
||||
= exprs ls
|
||||
exprs ((n,s):ls) = case readExpr s of
|
||||
Just e -> let (es,err) = exprs ls
|
||||
in case inferExpr pgf e of
|
||||
Right (e,t) -> (e:es,err)
|
||||
Left msg -> (es,"on line" <+> n <> ':' $$ msg $$ err)
|
||||
Nothing -> let (es,err) = exprs ls
|
||||
in (es,"on line" <+> n <> ':' <+> "parse error" $$ err)
|
||||
returnFromLines ls = case exprs ls of
|
||||
(es, err) | null es -> return $ pipeMessage $ render (err $$ "no trees found")
|
||||
| otherwise -> return $ pipeWithMessage (map hsExpr es) (render err)
|
||||
|
||||
s <- restricted $ readFile file
|
||||
case opts of
|
||||
_ | isOpt "lines" opts && isOpt "tree" opts ->
|
||||
returnFromLines (zip [1::Int ..] (lines s))
|
||||
_ | isOpt "tree" opts ->
|
||||
returnFromLines [(1::Int,s)]
|
||||
_ | isOpt "lines" opts -> return (fromStrings $ lines s)
|
||||
_ -> return (fromString s),
|
||||
flags = [("file","the input file name")]
|
||||
}),
|
||||
("rt", emptyCommandInfo {
|
||||
longname = "rank_trees",
|
||||
synopsis = "show trees in an order of decreasing probability",
|
||||
explanation = unlines [
|
||||
"Order trees from the most to the least probable, using either",
|
||||
"even distribution in each category (default) or biased as specified",
|
||||
"by the file given by flag -probs=FILE, where each line has the form",
|
||||
"'function probability', e.g. 'youPol_Pron 0.01'."
|
||||
],
|
||||
exec = needPGF $ \opts es env@(pgf, _) -> do
|
||||
let tds = sortBy (\(_,p) (_,q) -> compare p q)
|
||||
[(t, treeProbability pgf t) | t <- map cExpr (toExprs es)]
|
||||
if isOpt "v" opts
|
||||
then putStrLn $
|
||||
unlines [PGF2.showExpr [] t ++ "\t--" ++ show d | (t,d) <- tds]
|
||||
else return ()
|
||||
returnFromExprs $ map (hsExpr . fst) tds,
|
||||
flags = [
|
||||
("probs","probabilities from this file (format 'f 0.6' per line)")
|
||||
],
|
||||
options = [
|
||||
("v","show all trees with their probability scores")
|
||||
],
|
||||
examples = [
|
||||
mkEx "p \"you are here\" | rt -probs=probs | pt -number=1 -- most probable result"
|
||||
]
|
||||
}),
|
||||
{-
|
||||
("tq", emptyCommandInfo {
|
||||
longname = "translation_quiz",
|
||||
syntax = "tq -from=LANG -to=LANG (-cat=CAT)? (-probs=FILE)? TREE?",
|
||||
synopsis = "start a translation quiz",
|
||||
exec = \env@(pgf, mos) opts xs -> do
|
||||
let from = optLangFlag "from" pgf opts
|
||||
let to = optLangFlag "to" pgf opts
|
||||
let typ = optType pgf opts
|
||||
let mt = mexp xs
|
||||
pgf <- optProbs opts pgf
|
||||
restricted $ translationQuiz mt pgf from to typ
|
||||
return void,
|
||||
flags = [
|
||||
("from","translate from this language"),
|
||||
("to","translate to this language"),
|
||||
("cat","translate in this category"),
|
||||
("number","the maximum number of questions"),
|
||||
("probs","file with biased probabilities for generation")
|
||||
],
|
||||
examples = [
|
||||
mkEx ("tq -from=Eng -to=Swe -- any trees in startcat"),
|
||||
mkEx ("tq -from=Eng -to=Swe (AdjCN (PositA ?2) (UseN ?)) -- only trees of this form")
|
||||
]
|
||||
}),
|
||||
("vd", emptyCommandInfo {
|
||||
longname = "visualize_dependency",
|
||||
synopsis = "show word dependency tree graphically",
|
||||
explanation = unlines [
|
||||
"Prints a dependency tree in the .dot format (the graphviz format, default)",
|
||||
"or the CoNLL/MaltParser format (flag -output=conll for training, malt_input",
|
||||
"for unanalysed input).",
|
||||
"By default, the last argument is the head of every abstract syntax",
|
||||
"function; moreover, the head depends on the head of the function above.",
|
||||
"The graph can be saved in a file by the wf command as usual.",
|
||||
"If the -view flag is defined, the graph is saved in a temporary file",
|
||||
"which is processed by graphviz and displayed by the program indicated",
|
||||
"by the flag. The target format is png, unless overridden by the",
|
||||
"flag -format."
|
||||
],
|
||||
exec = \env@(pgf, mos) opts es -> do
|
||||
let debug = isOpt "v" opts
|
||||
let file = valStrOpts "file" "" opts
|
||||
let outp = valStrOpts "output" "dot" opts
|
||||
mlab <- case file of
|
||||
"" -> return Nothing
|
||||
_ -> (Just . H.getDepLabels . lines) `fmap` restricted (readFile file)
|
||||
let lang = optLang pgf opts
|
||||
let grphs = unlines $ map (H.graphvizDependencyTree outp debug mlab Nothing pgf lang) es
|
||||
if isFlag "view" opts || isFlag "format" opts then do
|
||||
let file s = "_grphd." ++ s
|
||||
let view = optViewGraph opts
|
||||
let format = optViewFormat opts
|
||||
restricted $ writeUTF8File (file "dot") grphs
|
||||
restrictedSystem $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
||||
restrictedSystem $ view ++ " " ++ file format
|
||||
return void
|
||||
else return $ fromString grphs,
|
||||
examples = [
|
||||
mkEx "gr | vd -- generate a tree and show dependency tree in .dot",
|
||||
mkEx "gr | vd -view=open -- generate a tree and display dependency tree on a Mac",
|
||||
mkEx "gr -number=1000 | vd -file=dep.labels -output=malt -- generate training treebank",
|
||||
mkEx "gr -number=100 | vd -file=dep.labels -output=malt_input -- generate test sentences"
|
||||
],
|
||||
options = [
|
||||
("v","show extra information")
|
||||
],
|
||||
flags = [
|
||||
("file","configuration file for labels per fun, format 'fun l1 ... label ... l2'"),
|
||||
("format","format of the visualization file (default \"png\")"),
|
||||
("output","output format of graph source (default \"dot\")"),
|
||||
("view","program to open the resulting file (default \"open\")"),
|
||||
("lang","the language of analysis")
|
||||
]
|
||||
}),
|
||||
-}
|
||||
|
||||
("vp", emptyCommandInfo {
|
||||
longname = "visualize_parse",
|
||||
synopsis = "show parse tree graphically",
|
||||
explanation = unlines [
|
||||
"Prints a parse tree in the .dot format (the graphviz format).",
|
||||
"The graph can be saved in a file by the wf command as usual.",
|
||||
"If the -view flag is defined, the graph is saved in a temporary file",
|
||||
"which is processed by graphviz and displayed by the program indicated",
|
||||
"by the flag. The target format is png, unless overridden by the",
|
||||
"flag -format."
|
||||
],
|
||||
exec = needPGF $ \opts arg env@(pgf, concs) ->
|
||||
do let es = toExprs arg
|
||||
let concs = optConcs env opts
|
||||
|
||||
let gvOptions=graphvizDefaults{noLeaves = isOpt "noleaves" opts && not (isOpt "showleaves" opts),
|
||||
noFun = isOpt "nofun" opts || not (isOpt "showfun" opts),
|
||||
noCat = isOpt "nocat" opts && not (isOpt "showcat" opts),
|
||||
nodeFont = valStrOpts "nodefont" "" opts,
|
||||
leafFont = valStrOpts "leaffont" "" opts,
|
||||
nodeColor = valStrOpts "nodecolor" "" opts,
|
||||
leafColor = valStrOpts "leafcolor" "" opts,
|
||||
nodeEdgeStyle = valStrOpts "nodeedgestyle" "solid" opts,
|
||||
leafEdgeStyle = valStrOpts "leafedgestyle" "dashed" opts
|
||||
}
|
||||
|
||||
let grph= if null es || null concs
|
||||
then []
|
||||
else graphvizParseTree (snd (head concs)) gvOptions (cExpr (head es))
|
||||
if isFlag "view" opts || isFlag "format" opts then do
|
||||
let file s = "_grph." ++ s
|
||||
let view = optViewGraph opts
|
||||
let format = optViewFormat opts
|
||||
restricted $ writeUTF8File (file "dot") grph
|
||||
restrictedSystem $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
||||
restrictedSystem $ view ++ " " ++ file format
|
||||
return void
|
||||
else return $ fromString grph,
|
||||
examples = [
|
||||
mkEx "p -lang=Eng \"John walks\" | vp -- generate a tree and show parse tree as .dot script",
|
||||
mkEx "gr | vp -view=\"open\" -- generate a tree and display parse tree on a Mac"
|
||||
],
|
||||
options = [
|
||||
("showcat","show categories in the tree nodes (default)"),
|
||||
("nocat","don't show categories"),
|
||||
("showfun","show function names in the tree nodes"),
|
||||
("nofun","don't show function names (default)"),
|
||||
("showleaves","show the leaves of the tree (default)"),
|
||||
("noleaves","don't show the leaves of the tree (i.e., only the abstract tree)")
|
||||
],
|
||||
flags = [
|
||||
("lang","the language to visualize"),
|
||||
("format","format of the visualization file (default \"png\")"),
|
||||
("view","program to open the resulting file (default \"open\")"),
|
||||
("nodefont","font for tree nodes (default: Times -- graphviz standard font)"),
|
||||
("leaffont","font for tree leaves (default: nodefont)"),
|
||||
("nodecolor","color for tree nodes (default: black -- graphviz standard color)"),
|
||||
("leafcolor","color for tree leaves (default: nodecolor)"),
|
||||
("nodeedgestyle","edge style between tree nodes (solid/dashed/dotted/bold, default: solid)"),
|
||||
("leafedgestyle","edge style for links to leaves (solid/dashed/dotted/bold, default: dashed)")
|
||||
]
|
||||
}),
|
||||
|
||||
("vt", emptyCommandInfo {
|
||||
longname = "visualize_tree",
|
||||
synopsis = "show a set of trees graphically",
|
||||
explanation = unlines [
|
||||
"Prints a set of trees in the .dot format (the graphviz format).",
|
||||
"The graph can be saved in a file by the wf command as usual.",
|
||||
"If the -view flag is defined, the graph is saved in a temporary file",
|
||||
"which is processed by graphviz and displayed by the program indicated",
|
||||
"by the flag. The target format is postscript, unless overridden by the",
|
||||
"flag -format."
|
||||
],
|
||||
exec = needPGF $ \opts arg env@(pgf, _) ->
|
||||
let es = toExprs arg in
|
||||
if isOpt "api" opts
|
||||
then do
|
||||
mapM_ (putStrLn . exprToAPI) es
|
||||
return void
|
||||
else do
|
||||
let gvOptions=graphvizDefaults{noFun = isOpt "nofun" opts,
|
||||
noCat = isOpt "nocat" opts,
|
||||
nodeFont = valStrOpts "nodefont" "" opts,
|
||||
nodeColor = valStrOpts "nodecolor" "" opts,
|
||||
nodeEdgeStyle = valStrOpts "nodeedgestyle" "solid" opts
|
||||
}
|
||||
let grph = unlines (map (graphvizAbstractTree pgf gvOptions . cExpr) es)
|
||||
if isFlag "view" opts || isFlag "format" opts then do
|
||||
let file s = "_grph." ++ s
|
||||
let view = optViewGraph opts
|
||||
let format = optViewFormat opts
|
||||
restricted $ writeUTF8File (file "dot") grph
|
||||
restrictedSystem $ "dot -T" ++ format ++ " " ++ file "dot" ++ " > " ++ file format
|
||||
restrictedSystem $ view ++ " " ++ file format
|
||||
return void
|
||||
else return $ fromString grph,
|
||||
examples = [
|
||||
mkEx "p \"hello\" | vt -- parse a string and show trees as graph script",
|
||||
mkEx "p \"hello\" | vt -view=\"open\" -- parse a string and display trees on a Mac"
|
||||
],
|
||||
options = [
|
||||
("api", "show the tree with function names converted to 'mkC' with value cats C"),
|
||||
("nofun","don't show functions but only categories"),
|
||||
("nocat","don't show categories but only functions")
|
||||
],
|
||||
flags = [
|
||||
("format","format of the visualization file (default \"png\")"),
|
||||
("view","program to open the resulting file (default \"open\")"),
|
||||
("nodefont","font for tree nodes (default: Times -- graphviz standard font)"),
|
||||
("nodecolor","color for tree nodes (default: black -- graphviz standard color)"),
|
||||
("nodeedgestyle","edge style between tree nodes (solid/dashed/dotted/bold, default: solid)")
|
||||
]
|
||||
}),
|
||||
|
||||
("ai", emptyCommandInfo {
|
||||
longname = "abstract_info",
|
||||
syntax = "ai IDENTIFIER or ai EXPR",
|
||||
synopsis = "Provides an information about a function, an expression or a category from the abstract syntax",
|
||||
explanation = unlines [
|
||||
"The command has one argument which is either function, expression or",
|
||||
"a category defined in the abstract syntax of the current grammar. ",
|
||||
"If the argument is a function then its type is printed out.",
|
||||
"If it is a category then the category definition is printed.",
|
||||
"If a whole expression is given it prints the expression with refined",
|
||||
"metavariables and the type of the expression."
|
||||
],
|
||||
exec = needPGF $ \opts args env@(pgf,cncs) ->
|
||||
case map cExpr (toExprs args) of
|
||||
[e] -> case unApp e of
|
||||
Just (id,[]) -> return (fromString
|
||||
(case functionType pgf id of
|
||||
Just ty -> showFun id ty
|
||||
Nothing -> let funs = functionsByCat pgf id
|
||||
in showCat id funs))
|
||||
where
|
||||
showCat c funs = "cat "++c++
|
||||
" ;\n\n"++
|
||||
unlines [showFun f ty| f<-funs,
|
||||
Just ty <- [functionType pgf f]]
|
||||
showFun f ty = "fun "++f++" : "++showType [] ty++" ;"
|
||||
_ -> case inferExpr pgf e of
|
||||
Left msg -> error msg
|
||||
Right (e,ty) -> do putStrLn ("Expression: "++PGF2.showExpr [] e)
|
||||
putStrLn ("Type: "++PGF2.showType [] ty)
|
||||
putStrLn ("Probability: "++show (treeProbability pgf e))
|
||||
return void
|
||||
_ -> do putStrLn "a single function name or category name is expected"
|
||||
return void,
|
||||
needsTypeCheck = False
|
||||
})
|
||||
]
|
||||
where
|
||||
cParse env@(pgf,_) opts ss =
|
||||
parsed [ parse cnc cat s | s<-ss,(lang,cnc)<-cncs]
|
||||
where
|
||||
cat = optType pgf opts
|
||||
cncs = optConcs env opts
|
||||
parsed rs = Piped (Exprs ts,unlines msgs)
|
||||
where
|
||||
ts = [hsExpr t|ParseOk ts<-rs,(t,p)<-takeOptNum opts ts]
|
||||
msgs = concatMap mkMsg rs
|
||||
|
||||
mkMsg (ParseOk ts) = (map (PGF2.showExpr [] . fst).takeOptNum opts) ts
|
||||
mkMsg (ParseFailed _ tok) = ["Parse failed: "++tok]
|
||||
mkMsg (ParseIncomplete) = ["The sentence is incomplete"]
|
||||
|
||||
optLins env opts ts = case opts of
|
||||
_ | isOpt "groups" opts ->
|
||||
concatMap snd $ groupResults
|
||||
[[(lang, s) | (lang,concr) <- optConcs env opts,s <- linear opts lang concr t] | t <- ts]
|
||||
_ -> concatMap (optLin env opts) ts
|
||||
optLin env@(pgf,_) opts t =
|
||||
case opts of
|
||||
_ | isOpt "treebank" opts ->
|
||||
(abstractName pgf ++ ": " ++ PGF2.showExpr [] t) :
|
||||
[lang ++ ": " ++ s | (lang,concr) <- optConcs env opts, s<-linear opts lang concr t]
|
||||
_ -> [s | (lang,concr) <- optConcs env opts, s<-linear opts lang concr t]
|
||||
|
||||
linear :: [Option] -> ConcName -> Concr -> PGF2.Expr -> [String]
|
||||
linear opts lang concr = case opts of
|
||||
_ | isOpt "all" opts -> concat . map (map snd) . tabularLinearizeAll concr
|
||||
_ | isOpt "list" opts -> (:[]) . commaList .
|
||||
concatMap (map snd) . tabularLinearizeAll concr
|
||||
_ | isOpt "table" opts -> concatMap (map (\(p,v) -> p+++":"+++v)) . tabularLinearizeAll concr
|
||||
_ | isOpt "bracket" opts -> (:[]) . unwords . map showBracketedString . bracketedLinearize concr
|
||||
_ -> (:[]) . linearize concr
|
||||
|
||||
groupResults :: [[(ConcName,String)]] -> [(ConcName,[String])]
|
||||
groupResults = Map.toList . foldr more Map.empty . start . concat
|
||||
where
|
||||
start ls = [(l,[s]) | (l,s) <- ls]
|
||||
more (l,s) =
|
||||
Map.insertWith (\ [x] xs -> if elem x xs then xs else (x : xs)) l s
|
||||
|
||||
optConcs = optConcsFlag "lang"
|
||||
|
||||
optConcsFlag f (pgf,cncs) opts =
|
||||
case valStrOpts f "" opts of
|
||||
"" -> Map.toList cncs
|
||||
lang -> mapMaybe pickLang (chunks ',' lang)
|
||||
where
|
||||
pickLang l = pick l `mplus` pick fl
|
||||
where
|
||||
fl = abstractName pgf++l
|
||||
pick l = (,) l `fmap` Map.lookup l cncs
|
||||
|
||||
{-
|
||||
-- replace each non-atomic constructor with mkC, where C is the val cat
|
||||
tree2mk pgf = H.showExpr [] . t2m where
|
||||
t2m t = case H.unApp t of
|
||||
Just (cid,ts@(_:_)) -> H.mkApp (mk cid) (map t2m ts)
|
||||
_ -> t
|
||||
mk = H.mkCId . ("mk" ++) . H.showCId . H.lookValCat (H.abstract pgf)
|
||||
|
||||
unlex opts lang = stringOps Nothing (getUnlex opts lang ++ map prOpt opts) ----
|
||||
|
||||
getUnlex opts lang = case words (valStrOpts "unlexer" "" opts) of
|
||||
lexs -> case lookup lang
|
||||
[(H.mkCId la,tail le) | lex <- lexs, let (la,le) = span (/='=') lex, not (null le)] of
|
||||
Just le -> chunks ',' le
|
||||
_ -> []
|
||||
-}
|
||||
commaList [] = []
|
||||
commaList ws = concat $ head ws : map (", " ++) (tail ws)
|
||||
|
||||
optFile opts = valStrOpts "file" "_gftmp" opts
|
||||
|
||||
optType pgf opts =
|
||||
case listFlags "cat" opts of
|
||||
v:_ -> let str = valueString v
|
||||
in case readType str of
|
||||
Just ty -> case checkType pgf ty of
|
||||
Left msg -> error msg
|
||||
Right ty -> ty
|
||||
Nothing -> error ("Can't parse '"++str++"' as a type")
|
||||
_ -> startCat pgf
|
||||
|
||||
optViewFormat opts = valStrOpts "format" "png" opts
|
||||
optViewGraph opts = valStrOpts "view" "open" opts
|
||||
{-
|
||||
optNum opts = valIntOpts "number" 1 opts
|
||||
-}
|
||||
optNumInf opts = valIntOpts "number" 1000000000 opts ---- 10^9
|
||||
takeOptNum opts = take (optNumInf opts)
|
||||
|
||||
returnFromCExprs = returnFromExprs . map hsExpr
|
||||
returnFromExprs es =
|
||||
return $ case es of
|
||||
[] -> pipeMessage "no trees found"
|
||||
_ -> fromExprs es
|
||||
|
||||
prGrammar env@(pgf,cncs) opts
|
||||
| isOpt "langs" opts = return . fromString . unwords $ (map fst (optConcs env opts))
|
||||
| isOpt "cats" opts = return . fromString . unwords $ categories pgf
|
||||
| isOpt "funs" opts = return . fromString . unwords $ functions pgf
|
||||
| isOpt "missing" opts = return . fromString . unwords $
|
||||
[f | f <- functions pgf, not (and [hasLinearization concr f | (_,concr) <- optConcs env opts])]
|
||||
| isOpt "fullform" opts = return $ fromString $ concatMap (prFullFormLexicon . snd) $ optConcs env opts
|
||||
| isOpt "words" opts = return $ fromString $ concatMap (prAllWords . snd) $ optConcs env opts
|
||||
| isOpt "lexc" opts = return $ fromString $ concatMap (prLexcLexicon . snd) $ optConcs env opts
|
||||
| otherwise = return void
|
||||
|
||||
gizaAlignment pgf src_cnc tgt_cnc e =
|
||||
let src_res = alignWords src_cnc e
|
||||
tgt_res = alignWords tgt_cnc e
|
||||
alignment = [show i++"-"++show j | (i,(_,src_fids)) <- zip [0..] src_res, (j,(_,tgt_fids)) <- zip [0..] tgt_res, not (null (intersect src_fids tgt_fids))]
|
||||
in (unwords (map fst src_res), unwords (map fst tgt_res), unwords alignment)
|
||||
|
||||
morphos env opts s =
|
||||
[(s,res) | (lang,concr) <- optConcs env opts, let res = lookupMorpho concr s, not (null res)]
|
||||
{-
|
||||
mexp xs = case xs of
|
||||
t:_ -> Just t
|
||||
_ -> Nothing
|
||||
-}
|
||||
-- ps -f -g s returns g (f s)
|
||||
{-
|
||||
treeOps pgf opts s = foldr app s (reverse opts) where
|
||||
app (OOpt op) | Just (Left f) <- treeOp pgf op = f
|
||||
app (OFlag op (VId x)) | Just (Right f) <- treeOp pgf op = f (H.mkCId x)
|
||||
app _ = id
|
||||
|
||||
treeOpOptions pgf = [(op,expl) | (op,(expl,Left _)) <- allTreeOps pgf]
|
||||
treeOpFlags pgf = [(op,expl) | (op,(expl,Right _)) <- allTreeOps pgf]
|
||||
|
||||
translationQuiz :: Maybe H.Expr -> H.PGF -> H.Language -> H.Language -> H.Type -> IO ()
|
||||
translationQuiz mex pgf ig og typ = do
|
||||
tts <- translationList mex pgf ig og typ infinity
|
||||
mkQuiz "Welcome to GF Translation Quiz." tts
|
||||
|
||||
morphologyQuiz :: Maybe H.Expr -> H.PGF -> H.Language -> H.Type -> IO ()
|
||||
morphologyQuiz mex pgf ig typ = do
|
||||
tts <- morphologyList mex pgf ig typ infinity
|
||||
mkQuiz "Welcome to GF Morphology Quiz." tts
|
||||
|
||||
-- | the maximal number of precompiled quiz problems
|
||||
infinity :: Int
|
||||
infinity = 256
|
||||
-}
|
||||
prLexcLexicon :: Concr -> String
|
||||
prLexcLexicon concr =
|
||||
unlines $ "Multichar_Symbols":multichars:"":"LEXICON Root" : [prLexc l p ++ ":" ++ w ++ " # ;" | (w,lps) <- morpho, (l,p,_) <- lps] ++ ["END"]
|
||||
where
|
||||
morpho = fullFormLexicon concr
|
||||
prLexc l p = l ++ concat (mkTags (words p))
|
||||
mkTags p = case p of
|
||||
"s":ws -> mkTags ws --- remove record field
|
||||
ws -> map ('+':) ws
|
||||
|
||||
multichars = unwords $ nub $ concat [mkTags (words p) | (w,lps) <- morpho, (l,p,_) <- lps]
|
||||
-- thick_A+(AAdj+Posit+Gen):thick's # ;
|
||||
|
||||
prFullFormLexicon :: Concr -> String
|
||||
prFullFormLexicon concr =
|
||||
unlines (map prMorphoAnalysis (fullFormLexicon concr))
|
||||
|
||||
prAllWords :: Concr -> String
|
||||
prAllWords concr =
|
||||
unwords [w | (w,_) <- fullFormLexicon concr]
|
||||
|
||||
prMorphoAnalysis :: (String,[MorphoAnalysis]) -> String
|
||||
prMorphoAnalysis (w,lps) =
|
||||
unlines (w:[fun ++ " : " ++ cat | (fun,cat,p) <- lps])
|
||||
|
||||
hsExpr c =
|
||||
case unApp c of
|
||||
Just (f,cs) -> H.mkApp (H.mkCId f) (map hsExpr cs)
|
||||
_ -> case unStr c of
|
||||
Just str -> H.mkStr str
|
||||
_ -> error $ "GF.Command.Commands2.hsExpr "++show c
|
||||
|
||||
cExpr e =
|
||||
case H.unApp e of
|
||||
Just (f,es) -> mkApp (H.showCId f) (map cExpr es)
|
||||
_ -> case H.unStr e of
|
||||
Just str -> mkStr str
|
||||
_ -> error $ "GF.Command.Commands2.cExpr "++show e
|
||||
|
||||
needPGF exec opts ts =
|
||||
do Env mb_pgf cncs <- getPGFEnv
|
||||
case mb_pgf of
|
||||
Just pgf -> liftSIO $ exec opts ts (pgf,cncs)
|
||||
_ -> fail "Import a grammar before using this command"
|
||||
@@ -15,7 +15,7 @@ import GF.Text.Pretty
|
||||
import GF.Text.Transliterations
|
||||
import GF.Text.Lexing(stringOp,opInEnv)
|
||||
|
||||
import qualified PGF as H(showCId,showExpr,toATree,toTrie,Trie(..))
|
||||
import PGF2(showExpr)
|
||||
|
||||
extend old new = Map.union (Map.fromList new) old -- Map.union is left-biased
|
||||
|
||||
@@ -101,9 +101,7 @@ commonCommands = fmap (mapCommandExec liftSIO) $ Map.fromList [
|
||||
"To see transliteration tables, use command ut."
|
||||
],
|
||||
examples = [
|
||||
-- mkEx "l (EAdd 3 4) | ps -code -- linearize code-like output",
|
||||
mkEx "l (EAdd 3 4) | ps -unlexcode -- linearize code-like output",
|
||||
-- mkEx "ps -lexer=code | p -cat=Exp -- parse code-like input",
|
||||
mkEx "ps -lexcode | p -cat=Exp -- parse code-like input",
|
||||
mkEx "gr -cat=QCl | l | ps -bind -- linearization output from LangFin",
|
||||
mkEx "ps -to_devanagari \"A-p\" -- show Devanagari in UTF8 terminal",
|
||||
@@ -175,12 +173,6 @@ commonCommands = fmap (mapCommandExec liftSIO) $ Map.fromList [
|
||||
mkEx "gt | l | ? wc -- generate trees, linearize, and count words"
|
||||
]
|
||||
}),
|
||||
("tt", emptyCommandInfo {
|
||||
longname = "to_trie",
|
||||
syntax = "to_trie",
|
||||
synopsis = "combine a list of trees into a trie",
|
||||
exec = \ _ -> return . fromString . trie . toExprs
|
||||
}),
|
||||
("ut", emptyCommandInfo {
|
||||
longname = "unicode_table",
|
||||
synopsis = "show a transliteration table for a unicode character set",
|
||||
@@ -228,7 +220,6 @@ envFlag fs =
|
||||
_ -> Nothing
|
||||
|
||||
stringOpOptions = sort $ [
|
||||
("bind","bind tokens separated by Prelude.BIND, i.e. &+"),
|
||||
("chars","lexer that makes every non-space character a token"),
|
||||
("from_cp1251","decode from cp1251 (Cyrillic used in Bulgarian resource)"),
|
||||
("from_utf8","decode from utf8 (default)"),
|
||||
@@ -253,19 +244,6 @@ stringOpOptions = sort $ [
|
||||
("to_" ++ p, "from GF " ++ n ++ " transliteration to unicode")] |
|
||||
(p,n) <- transliterationPrintNames]
|
||||
|
||||
trie = render . pptss . H.toTrie . map H.toATree
|
||||
where
|
||||
pptss [ts] = "*"<+>nest 2 (ppts ts)
|
||||
pptss tss = vcat [i<+>nest 2 (ppts ts)|(i,ts)<-zip [(1::Int)..] tss]
|
||||
|
||||
ppts = vcat . map ppt
|
||||
|
||||
ppt t =
|
||||
case t of
|
||||
H.Oth e -> pp (H.showExpr [] e)
|
||||
H.Ap f [[]] -> pp (H.showCId f)
|
||||
H.Ap f tss -> H.showCId f $$ nest 2 (pptss tss)
|
||||
|
||||
-- ** Converting command input
|
||||
toString = unwords . toStrings
|
||||
toLines = unlines . toStrings
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
module GF.Command.Importing (importGrammar, importSource) where
|
||||
|
||||
import PGF
|
||||
import PGF.Internal(unionPGF)
|
||||
import PGF2
|
||||
import PGF2.Internal(unionPGF)
|
||||
|
||||
import GF.Compile
|
||||
import GF.Compile.Multi (readMulti)
|
||||
|
||||
@@ -6,8 +6,8 @@ module GF.Command.Interpreter (
|
||||
import GF.Command.CommandInfo
|
||||
import GF.Command.Abstract
|
||||
import GF.Command.Parse
|
||||
import PGF
|
||||
import GF.Infra.UseIO(putStrLnE)
|
||||
import PGF2
|
||||
|
||||
import Control.Monad(when)
|
||||
import qualified Data.Map as Map
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
module GF.Command.Parse(readCommandLine, pCommand) where
|
||||
|
||||
import PGF(pExpr,pIdent)
|
||||
import PGF2(pExpr,pIdent)
|
||||
import GF.Grammar.Parser(runPartial,pTerm)
|
||||
import GF.Command.Abstract
|
||||
|
||||
@@ -22,7 +22,7 @@ pCommandLine =
|
||||
pPipe = sepBy1 (skipSpaces >> pCommand) (skipSpaces >> char '|')
|
||||
|
||||
pCommand = (do
|
||||
cmd <- pIdent <++ (char '%' >> fmap ('%':) pIdent)
|
||||
cmd <- readS_to_P pIdent <++ (char '%' >> fmap ('%':) (readS_to_P pIdent))
|
||||
skipSpaces
|
||||
opts <- sepBy pOption skipSpaces
|
||||
arg <- if getCommandOp cmd == "cc" then pArgTerm else pArgument
|
||||
@@ -37,7 +37,7 @@ pCommand = (do
|
||||
|
||||
pOption = do
|
||||
char '-'
|
||||
flg <- pIdent
|
||||
flg <- readS_to_P pIdent
|
||||
option (OOpt flg) (fmap (OFlag flg) (char '=' >> pValue))
|
||||
|
||||
pValue = do
|
||||
@@ -52,9 +52,9 @@ pFilename = liftM2 (:) (satisfy isFileFirst) (munch (not . isSpace)) where
|
||||
|
||||
pArgument =
|
||||
option ANoArg
|
||||
(fmap AExpr pExpr
|
||||
(fmap AExpr (readS_to_P pExpr)
|
||||
<++
|
||||
(skipSpaces >> char '%' >> fmap AMacro pIdent))
|
||||
(skipSpaces >> char '%' >> fmap AMacro (readS_to_P pIdent)))
|
||||
|
||||
pArgTerm = ATerm `fmap` readS_to_P sTerm
|
||||
where
|
||||
|
||||
@@ -4,15 +4,15 @@ module GF.Command.TreeOperations (
|
||||
treeChunks
|
||||
) where
|
||||
|
||||
import PGF(Expr,PGF,CId,compute,mkApp,unApp,unapply,unMeta,exprSize,exprFunctions)
|
||||
import PGF2(Expr,PGF,Fun,compute,mkApp,unApp,unapply,unMeta,exprSize,exprFunctions)
|
||||
import Data.List
|
||||
|
||||
type TreeOp = [Expr] -> [Expr]
|
||||
|
||||
treeOp :: PGF -> String -> Maybe (Either TreeOp (CId -> TreeOp))
|
||||
treeOp :: PGF -> String -> Maybe (Either TreeOp (Fun -> TreeOp))
|
||||
treeOp pgf f = fmap snd $ lookup f $ allTreeOps pgf
|
||||
|
||||
allTreeOps :: PGF -> [(String,(String,Either TreeOp (CId -> TreeOp)))]
|
||||
allTreeOps :: PGF -> [(String,(String,Either TreeOp (Fun -> TreeOp)))]
|
||||
allTreeOps pgf = [
|
||||
("compute",("compute by using semantic definitions (def)",
|
||||
Left $ map (compute pgf))),
|
||||
|
||||
Reference in New Issue
Block a user