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/CF/PrLBNF.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/CF/PrLBNF.hs')
| -rw-r--r-- | src-3.0/GF/CF/PrLBNF.hs | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/src-3.0/GF/CF/PrLBNF.hs b/src-3.0/GF/CF/PrLBNF.hs new file mode 100644 index 000000000..4ba2019bc --- /dev/null +++ b/src-3.0/GF/CF/PrLBNF.hs @@ -0,0 +1,150 @@ +---------------------------------------------------------------------- +-- | +-- Module : PrLBNF +-- Maintainer : AR +-- Stability : (stable) +-- Portability : (portable) +-- +-- > CVS $Date: 2005/06/17 14:15:16 $ +-- > CVS $Author: bringert $ +-- > CVS $Revision: 1.11 $ +-- +-- Printing CF grammars generated from GF as LBNF grammar for BNFC. +-- AR 26/1/2000 -- 9/6/2003 (PPrCF) -- 8/11/2003 -- 27/9/2004. +-- With primitive error messaging, by rules and rule tails commented out +----------------------------------------------------------------------------- + +module GF.CF.PrLBNF (prLBNF,prBNF) where + +import GF.CF.CF +import GF.CF.CFIdent +import GF.Canon.AbsGFC +import GF.Infra.Ident +import GF.Grammar.PrGrammar +import GF.Compile.ShellState +import GF.Canon.GFC +import GF.Canon.Look + +import GF.Data.Operations +import GF.Infra.Modules + +import Data.Char +import Data.List (nub) + +prLBNF :: Bool -> StateGrammar -> String +prLBNF new gr = unlines $ pragmas ++ (map (prCFRule cs) rules') + where + cs = map IC ["Int","String"] ++ [catIdPlus c | (_,(c,_)) <- rules] + cf = stateCF gr + (pragmas,rules) = if new -- tries to treat precedence levels + then mkLBNF (stateGrammarST gr) $ rulesOfCF cf + else ([],rulesOfCF cf) -- "normal" behaviour + rules' = concatMap expand rules + expand (f,(c,its)) = [(f,(c,it)) | it <- combinations (map expIt its)] + expIt i = case i of + CFTerm (RegAlts ss) -> [CFTerm (RegAlts [s]) | s <- ss] + _ -> [i] + +-- | a hack to hide the LBNF details +prBNF :: Bool -> StateGrammar -> String +prBNF b = unlines . (map (unwords . unLBNF . drop 1 . words)) . lines . prLBNF b + where + unLBNF r = case r of + "---":ts -> ts + ";":"---":ts -> ts + c:ts -> c : unLBNF ts + _ -> r + +--- | awful low level code without abstraction over label names etc +mkLBNF :: CanonGrammar -> [CFRule] -> ([String],[CFRule]) +mkLBNF gr rules = (coercions, nub $ concatMap mkRule rules) where + coercions = ["coercions" +++ prt_ c +++ show n +++ ";" | + (_,ModMod m) <- modules gr, + (c,CncCat (RecType ls) _ _) <- tree2list $ jments m, + Lbg (L (IC "p")) (TInts n) <- ls + ] + precedences = [(f,(prec,assoc)) | + (_,ModMod m) <- modules gr, + (f,CncFun _ _ (R lin) _) <- tree2list $ jments m, + (Just prec, Just assoc) <- [( + lookup "p" [(lab,p) | Ass (L (IC lab)) (EInt p) <- lin], + lookup "a" [(lab,a) | Ass (L (IC lab)) (Par (CIQ _ (IC a)) []) <- lin] + )] + ] + precfuns = map fst precedences + mkRule r@(fun@(CFFun (t, p)),(cat,its)) = case t of + AC (CIQ _ c) -> case lookup c precedences of + Just (prec,assoc) -> [(fun,(mkCat prec cat,mkIts cat prec assoc 0 its))] + _ -> return r + AD (CIQ _ c) -> case lookup c precedences of + Just (prec,assoc) -> [(fun,(mkCat prec cat,mkIts cat prec assoc 0 its))] + _ -> return r + _ -> return r + mkIts cat prec assoc i its = case its of + CFTerm (RegAlts ["("]):n@(CFNonterm k):CFTerm (RegAlts [")"]):rest | k==cat -> + mkIts cat prec assoc i $ n:rest -- remove variants with parentheses + CFNonterm k:rest | k==cat -> + CFNonterm (mkNonterm prec assoc i k) : mkIts cat prec assoc (i+1) rest + it:rest -> it:mkIts cat prec assoc i rest + [] -> [] + + mkCat prec (CFCat ((CIQ m (IC c)),l)) = CFCat ((CIQ m (IC (c ++ show prec ++ "+"))),l) + mkNonterm prec assoc i cat = mkCat prec' cat + where + prec' = case (assoc,i) of + ("PL",0) -> prec + ("PR",0) -> prec + 1 + ("PR",_) -> prec + _ -> prec + 1 + +catId ((CFCat ((CIQ _ c),l))) = c + +catIdPlus ((CFCat ((CIQ _ c@(IC s)),l))) = case reverse s of + '+':cs -> IC $ reverse $ dropWhile isDigit cs + _ -> c + +prCFRule :: [Ident] -> CFRule -> String +prCFRule cs (fun,(cat,its)) = + prCFFun cat fun ++ "." +++ prCFCat True cat +++ "::=" +++ --- err in cat -> in syntax + unwords (map (prCFItem cs) its) +++ ";" + +prCFFun :: CFCat -> CFFun -> String +prCFFun (CFCat (_,l)) (CFFun (t, p)) = case t of + AC (CIQ _ x) -> let f = prId True x in (f ++ lab +++ f2 f +++ prP p) + AD (CIQ _ x) -> let f = prId True x in (f ++ lab +++ f2 f +++ prP p) + _ -> prErr True $ prt t + where + lab = prLab l + f2 f = if null lab then "" else f + prP = concatMap show + +prId b i = case i of + IC "Int" -> "Integer" + IC "#Var" -> "Ident" + IC "Var" -> "Ident" + IC "id_" -> "_" + IC s@(c:_) | last s == '+' -> init s -- hack to save precedence information + IC s@(c:_) | isUpper c -> s ++ if isDigit (last s) then "_" else "" + _ -> prErr b $ prt i + +prLab i = case i of + L (IC "s") -> "" --- + L (IC "_") -> "" --- + _ -> let x = prt i in "_" ++ x ++ if isDigit (last x) then "_" else "" + +-- | just comment out the rest if you cannot interpret the function name in LBNF +-- two versions, depending on whether in the beginning of a rule or elsewhere; +-- in the latter case, error just terminates the rule +prErr :: Bool -> String -> String +prErr b s = (if b then "" else " ;") +++ "---" +++ s + +prCFCat :: Bool -> CFCat -> String +prCFCat b (CFCat ((CIQ _ c),l)) = prId b c ++ prLab l ---- + +-- | if a category does not have a production of its own, we replace it by Ident +prCFItem cs (CFNonterm c) = if elem (catIdPlus c) cs then prCFCat False c else "Ident" +prCFItem _ (CFTerm a) = prRegExp a + +prRegExp (RegAlts tt) = case tt of + [t] -> prQuotedString t + _ -> prErr False $ prParenth (prTList " | " (map prQuotedString tt)) |
