---------------------------------------------------------------------- -- | -- Maintainer : PL -- Stability : (stable) -- Portability : (portable) -- -- > CVS $Date: 2005/08/08 09:01:25 $ -- > CVS $Author: peb $ -- > CVS $Revision: 1.4 $ -- -- MCFG parsing, through context-free approximation ----------------------------------------------------------------------------- module GF.Parsing.MCFG.ViaCFG where -- Haskell modules import Data.List import Control.Monad -- GF modules import ConvertMCFGtoDecoratedCFG import qualified DecoratedCFParser as CFP import qualified DecoratedGrammar as CFG import Examples import GF.OldParsing.GeneralChart import qualified GF.OldParsing.MCFGrammar as MCFG import MCFParser import Nondet import Parser import GF.Parsing.MCFG.Range {-- Datatypes ----------------------------------------------------------------- Chart Item Key Item : Four different Items are used. PreMCFG for MCFG Pre Items, Pre are the Items returned by the pre-Functions and Mark are the corresponding Items for the mark-Functions. For convenience correctly marked Mark Items are converted to Passive Items. I use dottedrule for convenience to keep track of wich daughter's RangeRec to look for. AChart: A RedBlackMap with Items and Keys AKey : ------------------------------------------------------------------------------} --Ev ta bort några typer av Item och bara nyckla på det som är unikt för den typen... data Item n c l = PreMCFG (n, c) (RangeRec l) [RangeRec l] | Pre (n, c) (RangeRec l) [l] [RangeRec l] | Mark (n, c) (RangeRec l) (RangeRec l) [RangeRec l] | Passive (n, c) (RangeRec l) (RangeRec l) deriving (Eq, Ord, Show) type AChart n c l = ParseChart (Item n c l) (AKey n c l) data AKey n c l = Pr (n, c) l | Pm (n, c) l | Mk (RangeRec l) | Ps (RangeRec l) | Useless deriving (Eq, Ord, Show) {-- Parsing ------------------------------------------------------------------- recognize: parse : The Agenda consists of the Passive Items from context-free approximation (as PreMCFG Items) and the Pre Items inferred by pre-prediction. keyof : Given an Item returns an appropriate Key for the Chart ------------------------------------------------------------------------------} recognize strategy mcfg toks = chartMember (parse strategy mcfg toks) (Passive ("f", S) [("s" , MCFG.Range (0, n))] [("p" , MCFG.Range (0, n2)), ("q", MCFG.Range (n2, n))]) (Ps [("s" , MCFG.Range (0, n))]) where n = length toks n2 = n `div` 2 --parse :: (Ord n, Ord NT, Ord String, Eq t) => CFP.Strategy -> MCFG.Grammar n NT String t -> [t] -- -> AChart n NT String parse strategy mcfg toks = buildChart keyof [preCombine, markPredict, markCombine, convert] (makePreItems (CFP.parse strategy (CFG.pInfo (convertGrammar mcfg)) [(S, "s")] toks) ++ (prePredict mcfg)) keyof :: Item n c l -> AKey n c l keyof (PreMCFG head [(lbl, rng)] _) = Pm head lbl keyof (Pre head _ (lbl:lbls) _) = Pr head lbl keyof (Mark _ _ _ (rec:recs)) = Mk rec keyof (Passive _ rec _) = Ps rec keyof _ = Useless {-- Initializing agenda ------------------------------------------------------- makePreItems: ------------------------------------------------------------------------------} makePreItems :: (Eq c, Ord i) => CFG.Grammar n (Edge (c, l)) i t -> [Item n c l] makePreItems cfchart = [ PreMCFG (fun, cat) [(lbl, MCFG.makeRange (i, j))] (symToRec beta) | CFG.Rule (Edge i j (cat,lbl)) beta fun <- cfchart ] prePredict :: (Ord n, Ord c, Ord l) => MCFG.Grammar n c l t -> [Item n c l] prePredict mcfg = [ Pre (f, nt) [] (getLables lins) (replicate (nrOfCats (head lins)) []) | MCFG.Rule nt nts lins f <- mcfg ] {-- Inference rules --------------------------------------------------------- prePredict : preCombine : markPredict: markCombine: convert : ----------------------------------------------------------------------------} preCombine :: (Ord n, Ord c, Ord l) => ParseChart (Item n c l) (AKey n c l) -> Item n c l -> [Item n c l] preCombine chart (Pre head rec (l:ls) recs) = [ Pre head (rec ++ [(l, r)]) ls recs'' | PreMCFG head [(l, r)] recs' <- chartLookup chart (Pm head l), recs'' <- solutions (unifyRangeRecs recs recs') ] preCombine chart (PreMCFG head [(l, r)] recs) = [ Pre head (rec ++ [(l, r)]) ls recs'' | Pre head rec (l:ls) recs' <- chartLookup chart (Pr head l), recs'' <- solutions (unifyRangeRecs recs recs') ] preCombine _ _ = [] markPredict :: (Ord n, Ord c, Ord l) => ParseChart (Item n c l) (AKey n c l) -> Item n c l -> [Item n c l] markPredict _ (Pre (n, c) rec [] recs) = [Mark (n, c) rec [] recs] markPredict _ _ = [] markCombine :: (Ord n, Ord c, Ord l) => ParseChart (Item n c l) (AKey n c l) -> Item n c l -> [Item n c l] markCombine chart (Mark (f, c) rec mRec (r:recs)) = [ Mark (f, c) rec (mRec ++ r) recs | Passive _ r _ <- chartLookup chart (Ps r)] markCombine chart (Passive _ r _) = [ Mark (f, c) rec (mRec++r) recs | Mark (f, c) rec mRec (r:recs) <- chartLookup chart (Mk r) ] markCombine _ _ = [] convert :: (Ord n, Ord c, Ord l) => ParseChart (Item n c l) (AKey n c l) -> Item n c l -> [Item n c l] convert _ (Mark (f, c) r rec []) = [Passive (f, c) r rec] convert _ _ = [] {-- Help functions ---------------------------------------------------------------- getRHS : getLables: symToRec : ----------------------------------------------------------------------------------} -- FULKOD ! nrOfCats :: Eq c => MCFG.Lin c l t -> Int nrOfCats (MCFG.Lin l syms) = length $ nub [(c, i) | Cat (c, l, i) <- syms] -- getLables :: LinRec c l t -> [l] getLables lins = [l | MCFG.Lin l syms <- lins] -- symToRec :: Ord i => [Symbol (Edge (c, l), i) d] -> [[(l, MCFG.Range)]] symToRec beta = map makeLblRng $ groupBy (\(_, d) (_, d') -> (d == d')) $ sortBy sBd [(Edge i j (c, l) , d) | Cat (Edge i j (c, l), d) <- beta] where makeLblRng edges = [(l, (MCFG.makeRange (i, j))) | (Edge i j (_, l), _) <- edges] sBd (_, d) (_, d') | d < d' = LT | d > d' = GT | otherwise = EQ