From ab3cc776566847998fdca67714d40693f3f7b26c Mon Sep 17 00:00:00 2001 From: hallgren Date: Thu, 7 Apr 2016 13:40:05 +0000 Subject: GF shell: fix a parsing problem with the cc command This patch fixes a problem introduced last year when the GF shell was refactored to allow more commands to be treated uniformly and be part of pipes. The cc command was one of those commands, but unfortunately this introduced a parsing problem, e.g. > cc "last" constant not found: last > cc "last"++"year" command not parsed: cc "last"++"year" This happened because the generic command line parser in GF.Command.{Abstract,Parse} assumes that all commands have an argument of type PGF.Expr. Commands that expect other types of arguments have to use PGF.showExpr combined with other conversion to the argument type they expect. The cc command excpets a GF.Grammar.Term, and unfortunately not all terms survice the roundtrip through PGF.Expr, in part because of an additional hack to allow strings to be roundtripped through PGF.Expr without adding superfluous double quotes. To solve the problem, this patch + makes room for arguments of type Term in the Argument type in GF.Command.Abstract. + makes a special case for the cc command in GF.Command.Parse, by calling the partial parser 'runPartial pTerm' recently added in GF.Grammar.Lexer and GF.Grammar.Parser. Care was taken so that that "|" and ";" can be used both inside terms and as separators between commands in the shell, e.g. things like the following now work: > cc ("a"|"b") | ps -lexcode variants { "a" ; "b" } + introduces a type CommandArgument that replaces [Expr] as the type of values passed between commands in pipes. It has room for values of type [Expr], [String] and Term, thus eliminating the need to roundtrip through the Expr type all the time. The hack to avoid adding superfluous quotes when strings are roundtripped through Expr has been left in place for now, but can probably be removed. --- src/compiler/GF/Command/CommandInfo.hs | 51 ++++++++++++++++++++++++---------- 1 file changed, 37 insertions(+), 14 deletions(-) (limited to 'src/compiler/GF/Command/CommandInfo.hs') diff --git a/src/compiler/GF/Command/CommandInfo.hs b/src/compiler/GF/Command/CommandInfo.hs index 7d68f9221..b0b5869c3 100644 --- a/src/compiler/GF/Command/CommandInfo.hs +++ b/src/compiler/GF/Command/CommandInfo.hs @@ -1,10 +1,13 @@ module GF.Command.CommandInfo where -import GF.Command.Abstract(Option,Expr) +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 qualified PGF as H(showExpr) import qualified PGF.Internal as H(Literal(LStr),Expr(ELit)) ---- data CommandInfo m = CommandInfo { - exec :: [Option] -> [Expr] -> m CommandOutput, + exec :: [Option] -> CommandArguments -> m CommandOutput, synopsis :: String, syntax :: String, explanation :: String, @@ -35,26 +38,46 @@ class Monad m => TypeCheckArg m where typeCheckArg :: Expr -> m Expr -------------------------------------------------------------------------------- -newtype CommandOutput = Piped {fromPipe :: ([Expr],String)} ---- errors, etc +data CommandArguments = Exprs [Expr] | Strings [String] | Term Term + +newtype CommandOutput = Piped (CommandArguments,String) ---- errors, etc -- ** Converting command output -fromStrings ss = Piped (map stringAsExpr ss, unlines ss) -fromExprs es = Piped (es,unlines (map (H.showExpr []) es)) -fromString s = Piped ([stringAsExpr s], s) -pipeWithMessage es msg = Piped (es,msg) -pipeMessage msg = Piped ([],msg) -pipeExprs es = Piped (es,[]) -- only used in emptyCommandInfo -void = Piped ([],"") +fromStrings ss = Piped (Strings ss, unlines ss) +fromExprs es = Piped (Exprs es,unlines (map (H.showExpr []) es)) +fromString s = Piped (Strings [s], s) +pipeWithMessage es msg = Piped (Exprs es,msg) +pipeMessage msg = Piped (Exprs [],msg) +pipeExprs es = Piped (Exprs es,[]) -- only used in emptyCommandInfo +void = Piped (Exprs [],"") stringAsExpr = H.ELit . H.LStr -- should be a pattern macro -- ** Converting command input -toStrings = map showAsString +toStrings args = + case args of + Strings ss -> ss + Exprs es -> zipWith showAsString (True:repeat False) es + Term t -> [render t] where - showAsString t = case t of - H.ELit (H.LStr s) -> s - _ -> "\n" ++ H.showExpr [] t ---newline needed in other cases than the first + showAsString first t = + case t of + H.ELit (H.LStr s) -> s + _ -> ['\n'|not first] ++ + H.showExpr [] t ---newline needed in other cases than the first + +toExprs args = + case args of + Exprs es -> es + Strings ss -> map stringAsExpr ss + Term t -> [stringAsExpr (render t)] + +toTerm args = + case args of + Term t -> t + Strings ss -> string2term $ unwords ss -- hmm + Exprs es -> string2term $ unwords $ map (H.showExpr []) es -- hmm -- ** Creating documentation -- cgit v1.2.3