diff options
Diffstat (limited to 'src/GF/UseGrammar/Linear.hs')
| -rw-r--r-- | src/GF/UseGrammar/Linear.hs | 195 |
1 files changed, 195 insertions, 0 deletions
diff --git a/src/GF/UseGrammar/Linear.hs b/src/GF/UseGrammar/Linear.hs new file mode 100644 index 000000000..da1bfce52 --- /dev/null +++ b/src/GF/UseGrammar/Linear.hs @@ -0,0 +1,195 @@ +module Linear where + +import GFC +import AbsGFC +import qualified Abstract as A +import MkGFC (rtQIdent) ---- +import Ident +import PrGrammar +import CMacros +import Look +import Str +import Unlex +----import TypeCheck -- to annotate + +import Operations +import Zipper + +import Monad + +-- Linearization for canonical GF. AR 7/6/2003 + +-- The worker function: linearize a Tree, return +-- a record. Possibly mark subtrees. + +-- NB. Constants in trees are annotated by the name of the abstract module. +-- A concrete module name must be given to find (and choose) linearization rules. + +linearizeToRecord :: CanonGrammar -> Marker -> Ident -> A.Tree -> Err Term +linearizeToRecord gr mk m = lin [] where + + lin ts t = errIn ("lint" +++ prt t) $ ---- + if A.isFocusNode (A.nodeTree t) + then liftM markFocus $ lint ts t + else lint ts t + + lint ts t@(Tr (n,xs)) = do + + let binds = A.bindsNode n + at = A.atomNode n + c <- A.val2cat $ A.valNode n + xs' <- mapM (\ (i,x) -> lin (i:ts) x) $ zip [0..] xs + + r <- case at of + A.AtC f -> look f >>= comp xs' + A.AtL s -> return $ recS $ tK $ prt at + A.AtI i -> return $ recS $ tK $ prt at + A.AtV x -> lookCat c >>= comp [tK (prt at)] + A.AtM m -> lookCat c >>= comp [tK (prt at)] + + return $ mk ts $ mkBinds binds r + + look = lookupLin gr . redirectIdent m . rtQIdent + comp = ccompute gr + mkBinds bs bdy = case bdy of + R fs -> R $ [Ass (LV i) (tK (prt t)) | (i,(t,_)) <- zip [0..] bs] ++ fs + + recS t = R [Ass (L (identC "s")) t] ---- + + lookCat = return . errVal defLindef . look + ---- should always be given in the module + +type Marker = [Int] -> Term -> Term + +-- if no marking is wanted, use the following + +noMark :: [Int] -> Term -> Term +noMark = const id + +-- thus the special case: + +linearizeNoMark :: CanonGrammar -> Ident -> A.Tree -> Err Term +linearizeNoMark gr = linearizeToRecord gr noMark + +-- expand tables in linearized term to full, normal-order tables +-- NB expand from inside-out so that values are not looked up in copies of branches + +expandLinTables :: CanonGrammar -> Term -> Err Term +expandLinTables gr t = case t of + R rs -> liftM (R . map (uncurry Ass)) $ mapPairsM exp [(l,r) | Ass l r <- rs] + T ty rs -> do + rs' <- mapPairsM exp [(l,r) | Cas l r <- rs] -- expand from inside-out + let t' = T ty $ map (uncurry Cas) rs' + vs <- alls ty + ps <- mapM term2patt vs + ts' <- mapM (comp . S t') $ vs + return $ T ty [Cas [p] t | (p,t) <- zip ps ts'] + FV ts -> liftM FV $ mapM exp ts + _ -> return t + where + alls = allParamValues gr + exp = expandLinTables gr + comp = ccompute gr [] + +-- from records, one can get to records of tables of strings + +rec2strTables :: Term -> Err [[(Label,[([Patt],[Str])])]] +rec2strTables r = do + vs <- allLinValues r + mapM (mapPairsM (mapPairsM strsFromTerm)) vs + +-- from these tables, one may want to extract the ones for the "s" label + +strTables2sTables :: [[(Label,[([Patt],[Str])])]] -> [[([Patt],[Str])]] +strTables2sTables ts = [t | r <- ts, (l,t) <- r, l == linLab0] + +linLab0 :: Label +linLab0 = L (identC "s") + +-- to get lists of token lists is easy +sTables2strs :: [[([Patt],[Str])]] -> [[Str]] +sTables2strs = map snd . concat + +-- from this, to get a list of strings --- customize unlexer +strs2strings :: [[Str]] -> [String] +strs2strings = map unlex + +-- finally, a top-level function to get a string from an expression +linTree2string :: CanonGrammar -> Ident -> A.Tree -> String +linTree2string gr m e = err id id $ do + t <- linearizeNoMark gr m e + r <- expandLinTables gr t + ts <- rec2strTables r + let ss = strs2strings $ sTables2strs $ strTables2sTables ts + ifNull (prtBad "empty linearization of" e) (return . head) ss + + +-- argument is a Tree, value is a list of strs; needed in Parsing + +allLinsOfTree :: CanonGrammar -> Ident -> A.Tree -> [Str] +allLinsOfTree gr a e = err (singleton . str) id $ do + e' <- return e ---- annotateExp gr e + r <- linearizeNoMark gr a e' + r' <- expandLinTables gr r + ts <- rec2strTables r' + return $ concat $ sTables2strs $ strTables2sTables ts + +{- +-- the value is a list of strs +allLinStrings :: CanonGrammar -> Tree -> [Str] +allLinStrings gr ft = case allLinsAsStrs gr ft of + Ok ts -> map snd $ concat $ map snd $ concat ts + Bad s -> [str s] + +-- the value is a list of strs, not forgetting their arguments +allLinsAsStrs :: CanonGrammar -> Tree -> Err [[(Label,[([Patt],Str)])]] +allLinsAsStrs gr ft = do + lpts <- allLinearizations gr ft + return $ concat $ mapM (mapPairsM (mapPairsM strsFromTerm)) lpts + +-- the value is a list of terms of type Str, not forgetting their arguments +allLinearizations :: CanonGrammar -> Tree -> Err [[(Label,[([Patt],Term)])]] +allLinearizations gr ft = linearizeTree gr ft >>= allLinValues + +-- to a list of strings +linearizeToStrings :: CanonGrammar -> ([Int] ->Term -> Term) -> Tree -> Err [String] +linearizeToStrings gr mk = liftM (map unlex) . linearizeToStrss gr mk + +-- to a list of token lists +linearizeToStrss :: CanonGrammar -> ([Int] -> Term -> Term) -> Tree -> Err [[Str]] +linearizeToStrss gr mk e = do + R rs <- linearizeToRecord gr mk e ---- + t <- lookupErr linLab0 [(r,s) | Ass r s <- rs] + return $ map strsFromTerm $ allInTable t + + +-- the value is a list of strings, not forgetting their arguments +allLinsOfFun :: CanonGrammar -> CIdent -> Err [[(Label,[([Patt],Term)])]] +allLinsOfFun gr f = do + t <- lookupLin gr f + allLinValues t + + + +-} + + + + +{- ---- +-- returns printname if one exists; otherwise linearizes with metas +printOrLinearize :: CanonGrammar -> Fun -> String +printOrLinearize gr f = +{- ---- + errVal (prtt f) $ case lookupPrintname cnc f of + Ok s -> return s + _ -> -} + + unlines $ take 1 $ err singleton id $ + do + t <- lookupFunType gr f + f' <- ref2exp [] t (AC f) --- [] + lin f' + where + lin = linearizeToStrings gr (const id) ---- +-} |
