diff --git a/src/compiler/GF/Compile/PGFtoPython.hs b/src/compiler/GF/Compile/PGFtoPython.hs index 57412a0d0..f65b73eae 100644 --- a/src/compiler/GF/Compile/PGFtoPython.hs +++ b/src/compiler/GF/Compile/PGFtoPython.hs @@ -1,4 +1,5 @@ ---------------------------------------------------------------------- +-- | -- Module : PGFtoPython -- Maintainer : Peter Ljunglöf -- @@ -11,6 +12,8 @@ import PGF.CId import PGF.Data import qualified PGF.Macros as M +import GF.Data.Operations + import qualified Data.Array.IArray as Array import qualified Data.Set as Set import qualified Data.Map as Map @@ -18,91 +21,96 @@ import qualified Data.IntMap as IntMap import Data.List (intersperse) pgf2python :: PGF -> String -pgf2python pgf = "# -*- coding: UTF-8 -*-\n" ++ - "# This file was automatically generated by GF\n\n" ++ - showCId name ++ " = " ++ grammar ++ "\n" +pgf2python pgf = ("# -*- coding: UTF-8 -*-" ++++ + "# This file was automatically generated by GF" +++++ + showCId name +++ "=" +++ + pyDict 1 pyStr id [ + ("flags", pyDict 2 pyCId pyLiteral (Map.assocs (gflags pgf))), + ("abstract", pyDict 2 pyStr id [ + ("name", pyCId name), + ("start", pyCId start), + ("flags", pyDict 3 pyCId pyLiteral (Map.assocs (aflags abs))), + ("funs", pyDict 3 pyCId pyAbsdef (Map.assocs (funs abs))) + ]), + ("concretes", pyDict 2 pyCId pyConcrete (Map.assocs cncs)) + ] ++ "\n") where name = absname pgf start = M.lookStartCat pgf abs = abstract pgf cncs = concretes pgf - grammar = pyDict 1 [(qs "abstract", pyDict 2 [(qs "name", qcid name), - (qs "start", qcid start), - (qs "flags", pyDict 0 [(qcid k, lit2py v) | - (k, v) <- Map.toList (aflags abs)]), - (qs "funs", pyDict 3 [(qcid f, absdef2py def) | - (f, def) <- Map.assocs (funs abs)])]), - (qs "concretes", pyDict 2 [(qcid cname, concrete2py cnc) | - (cname, cnc) <- Map.assocs cncs])] -absdef2py :: (Type, Int, Maybe [Equation], Double) -> String -absdef2py (typ, _, _, _) = pyTuple 0 [qcid cat, pyList 0 (map qcid args)] +pyAbsdef :: (Type, Int, Maybe [Equation], Double) -> String +pyAbsdef (typ, _, _, _) = pyTuple 0 id [pyCId cat, pyTuple 0 pyCId args] where (args, cat) = M.catSkeleton typ -lit2py :: Literal -> String -lit2py (LStr s) = qs s -lit2py (LInt n) = show n -lit2py (LFlt d) = show d +pyLiteral :: Literal -> String +pyLiteral (LStr s) = pyStr s +pyLiteral (LInt n) = show n +pyLiteral (LFlt d) = show d -concrete2py :: Concr -> String -concrete2py cnc = pyDict 3 [(qs "flags", pyDict 0 [(qcid k, lit2py v) | (k, v) <- Map.toList (cflags cnc)]), - (qs "prods", pyDict 4 [(show cat, pyList 0 (map frule2py (Set.toList set))) | - (cat, set) <- IntMap.toList (productions cnc)]), - (qs "cfuns", pyList 4 [ffun2py f | f <- Array.elems (cncfuns cnc)]), - (qs "seqs", pyList 4 [seq2py s | s <- Array.elems (sequences cnc)]), - (qs "ccats", pyDict 4 [(qcid cat, pyTuple 0 [show start, show end]) | - (cat, CncCat start end _) <- Map.assocs (cnccats cnc)]), - (qs "size", show (totalCats cnc))] +pyConcrete :: Concr -> String +pyConcrete cnc = pyDict 3 pyStr id [ + ("flags", pyDict 0 pyCId pyLiteral (Map.assocs (cflags cnc))), + ("printnames", pyDict 4 pyCId pyStr (Map.assocs (printnames cnc))), + ("lindefs", pyDict 4 pyCat (pyTuple 0 pyFun) (IntMap.assocs (lindefs cnc))), + ("productions", pyDict 4 pyCat pyProds (IntMap.assocs (productions cnc))), + ("cncfuns", pyDict 4 pyFun pyCncFun (Array.assocs (cncfuns cnc))), + ("sequences", pyDict 4 pySeq pySymbols (Array.assocs (sequences cnc))), + ("cnccats", pyDict 4 pyCId pyCncCat (Map.assocs (cnccats cnc))), + ("size", show (totalCats cnc)) + ] + where pyProds prods = pyTuple 5 pyProduction (Set.toList prods) + pyCncCat (CncCat start end _) = pyTuple 0 pyCat [start..end] + pyCncFun (CncFun f lins) = pyTuple 0 id [pyTuple 0 pySeq (Array.elems lins), pyCId f] + pySymbols syms = pyTuple 0 pySymbol (Array.elems syms) -frule2py :: Production -> String -frule2py (PApply funid args) = pyTuple 0 [show funid, pyList 0 (map parg2py args)] -frule2py (PCoerce arg) = show arg +pyProduction :: Production -> String +pyProduction (PCoerce arg) = pyTuple 0 id [pyStr "", pyTuple 0 pyCat [arg]] +pyProduction (PApply funid args) = pyTuple 0 id [pyFun funid, pyTuple 0 pyPArg args] + where pyPArg (PArg [] fid) = pyCat fid + pyPArg (PArg hypos fid) = pyTuple 0 pyCat (fid : map snd hypos) -parg2py :: PArg -> String -parg2py (PArg [] fid) = show fid -parg2py (PArg hypos fid) = pyTuple 0 (show fid : map (show . snd) hypos) - -ffun2py :: CncFun -> String -ffun2py (CncFun f lins) = pyTuple 0 [pyList 0 (map show (Array.elems lins)), qcid f] - -seq2py :: Array.Array DotPos Symbol -> String -seq2py seq = pyList 0 [sym2py s | s <- Array.elems seq] - -sym2py :: Symbol -> String -sym2py (SymCat n l) = pyTuple 0 [show n, show l] -sym2py (SymLit n l) = pyDict 0 [(qs "lit", pyTuple 0 [show n, show l])] -sym2py (SymVar n l) = pyDict 0 [(qs "var", pyTuple 0 [show n, show l])] -sym2py (SymKS ts) = join "," (map qs ts) -sym2py (SymKP ts alts) = pyDict 0 [(qs "pre", pyList 0 (map show ts)), - (qs "alts", pyList 0 (map alt2py alts))] - where alt2py (Alt ps ts) = pyTuple 0 [pyList 0 (map show ps), pyList 0 (map show ts)] +pySymbol :: Symbol -> String +pySymbol (SymCat n l) = pyTuple 0 show [n, l] +pySymbol (SymLit n l) = pyDict 0 pyStr id [("lit", pyTuple 0 show [n, l])] +pySymbol (SymVar n l) = pyDict 0 pyStr id [("var", pyTuple 0 show [n, l])] +pySymbol (SymKS ts) = prTList "," (map pyStr ts) +pySymbol (SymKP ts alts) = pyDict 0 pyStr id [("pre", pyTuple 0 pyStr ts), ("alts", pyTuple 0 alt2py alts)] + where alt2py (Alt ps ts) = pyTuple 0 (pyTuple 0 pyStr) [ps, ts] ---------------------------------------------------------------------- -- python helpers -pyDict :: Int -> [(String, String)] -> String -pyDict n xys = "{" ++ indent n ++ join ("," ++ indent n) [x ++ ":" ++ y | (x, y) <- xys] ++ indent n ++ "}" +pyDict :: Int -> (k -> String) -> (v -> String) -> [(k, v)] -> String +pyDict n pk pv [] = "{}" +pyDict n pk pv kvlist = prCurly (pyIndent n ++ prTList ("," ++ pyIndent n) (map pyKV kvlist) ++ pyIndent n) + where pyKV (k, v) = pk k ++ ":" ++ pv v -pyList :: Int -> [String] -> String -pyList n xs = "[" ++ indent n ++ join ("," ++ indent n) xs ++ indent n ++ "]" +pyList :: Int -> (v -> String) -> [v] -> String +pyList n pv [] = "[]" +pyList n pv xs = prBracket (pyIndent n ++ prTList ("," ++ pyIndent n) (map pv xs) ++ pyIndent n) -pyTuple :: Int -> [String] -> String -pyTuple n [x] = "(" ++ indent n ++ x ++ "," ++ indent n ++ ")" -pyTuple n xs = "(" ++ indent n ++ join ("," ++ indent n) xs ++ indent n ++ ")" +pyTuple :: Int -> (v -> String) -> [v] -> String +pyTuple n pv [] = "()" +pyTuple n pv [x] = prParenth (pyIndent n ++ pv x ++ "," ++ pyIndent n) +pyTuple n pv xs = prParenth (pyIndent n ++ prTList ("," ++ pyIndent n) (map pv xs) ++ pyIndent n) -qs :: String -> String -qs s = "u\"" ++ qs' s - where qs' ('"':s) = "\\\"" ++ qs' s - qs' ('\\':s) = "\\\\" ++ qs' s - qs' (c:s) = c : qs' s - qs' [] = "\"" +pyCat :: Int -> String +pyCat n = pyStr ('C' : show n) -qcid :: CId -> String -qcid = qs . showCId +pyFun :: Int -> String +pyFun n = pyStr ('F' : show n) -indent :: Int -> String -indent n | n > 0 = "\n" ++ replicate n ' ' - | otherwise = "" +pySeq :: Int -> String +pySeq n = pyStr ('S' : show n) -join :: String -> [String] -> String -join a bs = concat (intersperse a bs) +pyStr :: String -> String +pyStr s = 'u' : prQuotedString s + +pyCId :: CId -> String +pyCId = pyStr . showCId + +pyIndent :: Int -> String +pyIndent n | n > 0 = "\n" ++ replicate n ' ' + | otherwise = ""