diff options
| author | aarne <aarne@cs.chalmers.se> | 2008-05-21 09:26:44 +0000 |
|---|---|---|
| committer | aarne <aarne@cs.chalmers.se> | 2008-05-21 09:26:44 +0000 |
| commit | 055c0d0d5a5bb0dc75904fe53df7f2e4f5732a8f (patch) | |
| tree | 0e63fb68c69c8f6ad0f78893c63420f0a3600e1c /src-3.0/GF/Conversion/Prolog.hs | |
| parent | 915a1de71783ab8446b1af9e72c7ba7dfbc12d3f (diff) | |
GF/src is now for 2.9, and the new sources are in src-3.0 - keep it this way until the release of GF 3
Diffstat (limited to 'src-3.0/GF/Conversion/Prolog.hs')
| -rw-r--r-- | src-3.0/GF/Conversion/Prolog.hs | 205 |
1 files changed, 205 insertions, 0 deletions
diff --git a/src-3.0/GF/Conversion/Prolog.hs b/src-3.0/GF/Conversion/Prolog.hs new file mode 100644 index 000000000..b930cb476 --- /dev/null +++ b/src-3.0/GF/Conversion/Prolog.hs @@ -0,0 +1,205 @@ +---------------------------------------------------------------------- +-- | +-- Maintainer : PL +-- Stability : (stable) +-- Portability : (portable) +-- +-- > CVS $Date: 2005/09/14 09:51:18 $ +-- > CVS $Author: peb $ +-- > CVS $Revision: 1.4 $ +-- +-- Converting/Printing different grammar formalisms in Prolog-readable format +----------------------------------------------------------------------------- + + +module GF.Conversion.Prolog (prtSGrammar, prtSMulti, prtSHeader, prtSRule, + prtMGrammar, prtMMulti, prtMHeader, prtMRule, + prtCGrammar, prtCMulti, prtCHeader, prtCRule) where + +import GF.Formalism.GCFG +import GF.Formalism.SimpleGFC +import GF.Formalism.MCFG +import GF.Formalism.CFG +import GF.Formalism.Utilities +import GF.Conversion.Types +import qualified GF.Conversion.GFC as Cnv + +import GF.Data.Operations ((++++), (+++++)) +import GF.Infra.Print +import qualified GF.Infra.Modules as Mod +import qualified GF.Infra.Option as Option +import GF.Data.Operations (okError) +import GF.Canon.AbsGFC (Flag(..)) +import GF.Canon.GFC (CanonGrammar) +import GF.Infra.Ident (Ident(..)) + +import Data.Maybe (maybeToList, listToMaybe) +import Data.Char (isLower, isAlphaNum) + +import GF.System.Tracing + +---------------------------------------------------------------------- +-- | printing multiple languages at the same time + +prtSMulti, prtMMulti, prtCMulti :: Option.Options -> CanonGrammar -> String +prtSMulti = prtMulti prtSHeader prtSRule Cnv.gfc2simple "gfc_" +prtMMulti = prtMulti prtMHeader prtMRule Cnv.gfc2mcfg "mcfg_" +prtCMulti = prtMulti prtCHeader prtCRule Cnv.gfc2cfg "cfg_" + +-- code and ideas stolen from GF.CFGM.PrintCFGrammar + +prtMulti prtHeader prtRule conversion prefix opts gr + = prtHeader ++++ unlines + [ "\n\n" ++ prtLine ++++ + "%% Language module: " ++ prtQ langmod +++++ + unlines (map (prtRule langmod) rules) | + lang <- maybe [] (Mod.allConcretes gr) (Mod.greatestAbstract gr), + let Mod.ModMod (Mod.Module{Mod.flags=fs}) = okError (Mod.lookupModule gr lang), + let cnvopts = Option.Opts $ map Option.gfcConversion $ getFlag fs "conversion", + let rules = conversion cnvopts (gr, lang), + let langmod = (let IC lg = lang in prefix ++ lg) ] + +getFlag :: [Flag] -> String -> [String] +getFlag fs x = [v | Flg (IC k) (IC v) <- fs, k == x] + +---------------------------------------------------------------------- +-- | SimpleGFC to Prolog +-- +-- assumes that the profiles in the Simple GFC names are trivial +prtSGrammar :: SGrammar -> String +prtSGrammar rules = prtSHeader +++++ unlines (map (prtSRule "") rules) + +prtSHeader :: String +prtSHeader = prtLine ++++ + "%% Simple GFC grammar in Prolog-readable format" ++++ + "%% Autogenerated from the Grammatical Framework" +++++ + "%% The following predicate is defined:" ++++ + "%% \t rule(Fun, Cat, c(Cat,...), LinTerm)" + +prtSRule :: String -> SRule -> String +prtSRule lang (Rule (Abs cat cats (Name fun _prof)) (Cnc _ _ mterm)) + = (if null lang then "" else prtQ lang ++ " : ") ++ + prtFunctor "rule" [plfun, plcat, plcats, plcnc] ++ "." + where plfun = prtQ fun + plcat = prtSDecl cat + plcats = prtFunctor "c" (map prtSDecl cats) + plcnc = "\n\t" ++ prtSTerm (maybe Empty id mterm) + +prtSTerm (Arg n c p) = prtFunctor "arg" [prtQ c, prt (n+1), prtSPath p] +-- prtSTerm (c :^ []) = prtQ c +prtSTerm (c :^ ts) = prtOper "^" (prtQ c) (prtPList (map prtSTerm ts)) +prtSTerm (Rec rec) = prtFunctor "rec" [prtPList [ prtOper "=" (prtQ l) (prtSTerm t) | (l, t) <- rec ]] +prtSTerm (Tbl tbl) = prtFunctor "tbl" [prtPList [ prtOper "=" (prtSTerm p) (prtSTerm t) | (p, t) <- tbl ]] +prtSTerm (Variants ts) = prtFunctor "variants" [prtPList (map prtSTerm ts)] +prtSTerm (t1 :++ t2) = prtOper "+" (prtSTerm t1) (prtSTerm t2) +prtSTerm (Token t) = prtFunctor "tok" [prtQ t] +prtSTerm (Empty) = "empty" +prtSTerm (term :. lbl) = prtOper "*" (prtSTerm term) (prtQ lbl) +prtSTerm (term :! sel) = prtOper "/" (prtSTerm term) (prtSTerm sel) +-- prtSTerm (Wildcard) = "wildcard" +-- prtSTerm (Var var) = prtFunctor "var" [prtQ var] + +prtSPath (Path path) = prtPList (map (either prtQ prtSTerm) path) + +prtSDecl (Decl var typ) | var == anyVar = prtSAbsType typ + | otherwise = "_" ++ prtVar var ++ ":" ++ prtSAbsType typ + + +prtSAbsType ([] ::--> typ) = prtSFOType typ +prtSAbsType (args ::--> typ) = prtOper ":->" (prtPList (map prtSFOType args)) (prtSFOType typ) + +prtSFOType (cat ::@ args) = prtFunctor (prtQ cat) (map prtSTTerm args) + +prtSTTerm (con :@ args) = prtFunctor (prtQ con) (map prtSTTerm args) +prtSTTerm (TVar var) = "_" ++ prtVar var + +---------------------------------------------------------------------- +-- | MCFG to Prolog +prtMGrammar :: MGrammar -> String +prtMGrammar rules = prtMHeader +++++ unlines (map (prtMRule "") rules) + +prtMHeader :: String +prtMHeader = prtLine ++++ + "%% Multiple context-free grammar in Prolog-readable format" ++++ + "%% Autogenerated from the Grammatical Framework" +++++ + "%% The following predicate is defined:" ++++ + "%% \t rule(Profile, Cat, c(Cat,...), [Lbl=Symbols,...])" + +prtMRule :: String -> MRule -> String +prtMRule lang (Rule (Abs cat cats name) (Cnc _lcat _lcats lins)) + = (if null lang then "" else prtQ lang ++ " : ") ++ + prtFunctor "rule" [plname, plcat, plcats, pllins] ++ "." + where plname = prtName name + plcat = prtQ cat + plcats = prtFunctor "c" (map prtQ cats) + pllins = "\n\t[ " ++ prtSep "\n\t, " (map prtMLin lins) ++ " ]" + +prtMLin (Lin lbl lin) = prtOper "=" (prtQ lbl) (prtPList (map prtMSymbol lin)) + +prtMSymbol (Cat (cat, lbl, nr)) = prtFunctor "arg" [prtQ cat, show (nr+1), prtQ lbl] +prtMSymbol (Tok tok) = prtFunctor "tok" [prtQ tok] + +---------------------------------------------------------------------- +-- | CFG to Prolog +prtCGrammar :: CGrammar -> String +prtCGrammar rules = prtCHeader +++++ unlines (map (prtCRule "") rules) + +prtCHeader :: String +prtCHeader = prtLine ++++ + "%% Context-free grammar in Prolog-readable format" ++++ + "%% Autogenerated from the Grammatical Framework" +++++ + "%% The following predicate is defined:" ++++ + "%% \t rule(Profile, Cat, [Symbol,...])" + +prtCRule :: String -> CRule -> String +prtCRule lang (CFRule cat syms name) + = (if null lang then "" else prtQ lang ++ " : ") ++ + prtFunctor "cfgrule" [plname, plcat, plsyms] ++ "." + where plname = prtName name + plcat = prtQ cat + plsyms = prtPList (map prtCSymbol syms) + +prtCSymbol (Cat cat) = prtFunctor "cat" [prtQ cat] +prtCSymbol (Tok tok) = prtFunctor "tok" [prtQ tok] + +---------------------------------------------------------------------- +-- profiles, quoted strings and more + +prtFunctor f xs = f ++ if null xs then "" else "(" ++ prtSep ", " xs ++ ")" +prtPList xs = "[" ++ prtSep ", " xs ++ "]" +prtOper f x y = "(" ++ x ++ " " ++ f ++ " " ++ y ++ ")" + +prtName name@(Name fun profiles) + | name == coercionName = "1" + | and (zipWith (==) profiles (map (Unify . return) [0..])) = prtQ fun + | otherwise = prtFunctor (prtQ fun) (map prtProfile profiles) + +prtProfile (Unify []) = " ? " +prtProfile (Unify args) = foldr1 (prtOper "=") (map (show . succ) args) +prtProfile (Constant forest) = prtForest forest + +prtForest (FMeta) = " ? " +prtForest (FNode fun [fs]) = prtFunctor (prtQ fun) (map prtForest fs) +prtForest (FNode fun fss) = prtPList [ prtFunctor (prtQ fun) (map prtForest fs) | + fs <- fss ] + +prtQ atom = prtQStr (prt atom) + +prtQStr atom@(x:xs) + | isLower x && all isAlphaNumUnder xs = atom + where isAlphaNumUnder '_' = True + isAlphaNumUnder x = isAlphaNum x +prtQStr atom = "'" ++ concatMap esc (prt atom) ++ "'" + where esc '\'' = "\\'" + esc '\n' = "\\n" + esc '\t' = "\\t" + esc c = [c] + +prtVar var = reprime (prt var) + where reprime "" = "" + reprime ('\'' : cs) = "_0" ++ reprime cs + reprime (c:cs) = c : reprime cs + +prtLine = replicate 70 '%' + + |
