summaryrefslogtreecommitdiff
path: root/src-3.0/GF/Parsing/MCFG
diff options
context:
space:
mode:
authoraarne <aarne@cs.chalmers.se>2008-05-21 09:26:44 +0000
committeraarne <aarne@cs.chalmers.se>2008-05-21 09:26:44 +0000
commit055c0d0d5a5bb0dc75904fe53df7f2e4f5732a8f (patch)
tree0e63fb68c69c8f6ad0f78893c63420f0a3600e1c /src-3.0/GF/Parsing/MCFG
parent915a1de71783ab8446b1af9e72c7ba7dfbc12d3f (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/Parsing/MCFG')
-rw-r--r--src-3.0/GF/Parsing/MCFG/Active.hs318
-rw-r--r--src-3.0/GF/Parsing/MCFG/Active2.hs237
-rw-r--r--src-3.0/GF/Parsing/MCFG/FastActive.hs176
-rw-r--r--src-3.0/GF/Parsing/MCFG/Incremental.hs178
-rw-r--r--src-3.0/GF/Parsing/MCFG/Incremental2.hs157
-rw-r--r--src-3.0/GF/Parsing/MCFG/Naive.hs142
-rw-r--r--src-3.0/GF/Parsing/MCFG/PInfo.hs162
-rw-r--r--src-3.0/GF/Parsing/MCFG/Range.hs206
-rw-r--r--src-3.0/GF/Parsing/MCFG/ViaCFG.hs186
9 files changed, 1762 insertions, 0 deletions
diff --git a/src-3.0/GF/Parsing/MCFG/Active.hs b/src-3.0/GF/Parsing/MCFG/Active.hs
new file mode 100644
index 000000000..c6e9c6b06
--- /dev/null
+++ b/src-3.0/GF/Parsing/MCFG/Active.hs
@@ -0,0 +1,318 @@
+----------------------------------------------------------------------
+-- |
+-- Maintainer : PL
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- > CVS $Date: 2005/08/08 09:01:25 $
+-- > CVS $Author: peb $
+-- > CVS $Revision: 1.5 $
+--
+-- MCFG parsing, the active algorithm
+-----------------------------------------------------------------------------
+
+module GF.Parsing.MCFG.Active (parse, parseR) where
+
+import GF.Data.GeneralDeduction
+import GF.Data.Assoc
+
+import GF.Formalism.GCFG
+import GF.Formalism.MCFG
+import GF.Formalism.Utilities
+
+import GF.Parsing.MCFG.Range
+import GF.Parsing.MCFG.PInfo
+
+import GF.System.Tracing
+
+import Control.Monad (guard)
+
+import GF.Infra.Print
+
+----------------------------------------------------------------------
+-- * parsing
+
+parse :: (Ord n, Ord c, Ord l, Ord t) => String -> MCFParser c n l t
+parse strategy pinfo starts toks =
+ accumAssoc groupSyntaxNodes $
+ [ ((cat, found), SNode fun (zip rhs rrecs)) |
+ Final (Abs cat rhs fun) found rrecs <- chartLookup chart Fin ]
+ where chart = process strategy pinfo starts toks
+
+-- parseR :: (Ord n, Ord c, Ord l, Ord t) => String -> MCFParser c n l t
+parseR strategy pinfo starts =
+ accumAssoc groupSyntaxNodes $
+ [ ((cat, found), SNode fun (zip rhs rrecs)) |
+ Final (Abs cat rhs fun) found rrecs <- chartLookup chart Fin ]
+ where chart = processR strategy pinfo starts
+
+process :: (Ord n, Ord c, Ord l, Ord t) =>
+ String -> MCFPInfo c n l t -> [c] -> Input t -> AChart c n l
+process strategy pinfo starts toks
+ = tracePrt "MCFG.Active - chart size" prtSizes $
+ buildChart keyof (complete : combine : convert : rules) axioms
+ where rules | isNil strategy = [scan]
+ | isBU strategy = [scan, predictKilbury pinfo toks]
+ | isTD strategy = [scan, predictEarley pinfo toks]
+ axioms | isNil strategy = predict pinfo toks
+ | isBU strategy = {- terminal pinfo toks ++ -} initialScan pinfo toks
+ | isTD strategy = initial pinfo starts toks
+
+--processR :: (Ord n, Ord c, Ord l) =>
+-- String -> MCFPInfo c n l Range -> [c] -> AChart c n l
+processR strategy pinfo starts
+ = tracePrt "MCFG.Active Range - chart size" prtSizes $
+ -- tracePrt "MCFG.Active Range - final chart" prtChart $
+ buildChart keyof (complete : combine : convert : rules) axioms
+ where rules | isNil strategy = [scan]
+ | isBU strategy = [scan, predictKilburyR pinfo]
+ | isTD strategy = [scan, predictEarleyR pinfo]
+ axioms | isNil strategy = predictR pinfo
+ | isBU strategy = {- terminalR pinfo ++ -} initialScanR pinfo
+ | isTD strategy = initialR pinfo starts
+
+isNil s = s=="n"
+isBU s = s=="b"
+isTD s = s=="t"
+
+-- used in prediction
+emptyChildren :: Abstract c n -> [RangeRec l]
+emptyChildren (Abs _ rhs _) = replicate (length rhs) []
+
+makeMaxRange (Range (_, j)) = Range (j, j)
+makeMaxRange EmptyRange = EmptyRange
+
+
+----------------------------------------------------------------------
+-- * inference rules
+
+-- completion
+complete :: (Ord c, Ord n, Ord l) => AChart c n l -> Item c n l -> [Item c n l]
+complete _ (Active rule found rng (Lin l []) (lin:lins) recs) =
+ return $ Active rule (found ++ [(l, rng)]) EmptyRange lin lins recs
+complete _ _ = []
+
+-- scanning
+scan :: (Ord c, Ord n, Ord l) => AChart c n l -> Item c n l -> [Item c n l]
+scan _ (Active rule found rng (Lin l (Tok rng':syms)) lins recs) =
+ do rng'' <- concatRange rng rng'
+ return $ Active rule found rng'' (Lin l syms) lins recs
+scan _ _ = []
+
+-- | Creates an Active Item every time it is possible to combine
+-- an Active Item from the agenda with a Passive Item from the Chart
+combine :: (Ord c, Ord n, Ord l) => AChart c n l -> Item c n l -> [Item c n l]
+combine chart item@(Active _ _ _ (Lin _ (Cat (c,_,_):_)) _ _) =
+ do Passive _c found <- chartLookup chart (Pass c)
+ combine2 chart found item
+combine chart (Passive c found) =
+ do item <- chartLookup chart (Act c)
+ combine2 chart found item
+combine _ _ = []
+
+combine2 chart found' (Active rule found rng (Lin l (Cat (c, r, d):syms)) lins recs) =
+ do rng' <- projection r found'
+ rng'' <- concatRange rng rng'
+ recs' <- unifyRec recs d found'
+ return $ Active rule found rng'' (Lin l syms) lins recs'
+
+-- | Active Items with nothing to find are converted to Final items,
+-- which in turn are converted to Passive Items
+convert :: (Ord c, Ord n, Ord l) => AChart c n l -> Item c n l -> [Item c n l]
+convert _ (Active rule found rng (Lin lbl []) [] recs) =
+ return $ Final rule (found ++ [(lbl,rng)]) recs
+convert _ (Final (Abs cat _ _) found _) =
+ return $ Passive cat found
+convert _ _ = []
+
+
+----------------------------------------------------------------------
+-- Naive --
+
+predict :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> Input t -> [Item c n l]
+predict pinfo toks = tracePrt "MCFG.Active (Naive) - predicted rules" (prt . length) $
+ do (Rule abs (Cnc _ _ lins)) <- rulesMatchingInput pinfo toks
+ (lin':lins') <- rangeRestRec toks lins
+ return $ Active abs [] EmptyRange lin' lins' (emptyChildren abs)
+
+
+----------------------------------------------------------------------
+-- NaiveR --
+
+predictR :: (Ord c, Ord n, Ord l) => MCFPInfo c n l Range -> [Item c n l]
+predictR pinfo = tracePrt "MCFG.Active (Naive Range) - predicted rules" (prt . length) $
+ do (Rule abs (Cnc _ _ (lin:lins))) <- allRules pinfo
+ return $ Active abs [] EmptyRange lin lins (emptyChildren abs)
+
+
+----------------------------------------------------------------------
+-- Earley --
+
+-- anropas med alla startkategorier
+initial :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> [c] -> Input t -> [Item c n l]
+initial pinfo starts toks =
+ tracePrt "MCFG.Active (Earley) - initial rules" (prt . length) $
+ do cat <- starts
+ Rule abs (Cnc _ _ lins) <- topdownRules pinfo ? cat
+ lin' : lins' <- rangeRestRec toks lins
+ return $ Active abs [] (Range (0, 0)) lin' lins' (emptyChildren abs)
+
+predictEarley :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> Input t
+ -> AChart c n l -> Item c n l -> [Item c n l]
+predictEarley pinfo toks _ item@(Active (Abs _ _ f) _ rng (Lin _ (Cat (cat,_,_):_)) _ _) =
+ topdownRules pinfo ? cat >>= predictEarley2 toks rng
+predictEarley _ _ _ _ = []
+
+predictEarley2 :: (Ord c, Ord n, Ord l, Ord t) => Input t -> Range -> MCFRule c n l t -> [Item c n l]
+predictEarley2 toks _ (Rule abs@(Abs _ [] _) (Cnc _ _ lins)) =
+ do lins' <- rangeRestRec toks lins
+ return $ Final abs (makeRangeRec lins') []
+predictEarley2 toks rng (Rule abs (Cnc _ _ lins)) =
+ do lin' : lins' <- rangeRestRec toks lins
+ return $ Active abs [] EmptyRange lin' lins' (emptyChildren abs)
+
+
+----------------------------------------------------------------------
+-- Earley Range --
+
+initialR :: (Ord c, Ord n, Ord l) => MCFPInfo c n l Range -> [c] -> [Item c n l]
+initialR pinfo starts =
+ tracePrt "MCFG.Active (Earley Range) - initial rules" (prt . length) $
+ do cat <- starts
+ Rule abs (Cnc _ _ (lin : lins)) <- topdownRules pinfo ? cat
+ return $ Active abs [] (Range (0, 0)) lin lins (emptyChildren abs)
+
+predictEarleyR :: (Ord c, Ord n, Ord l) => MCFPInfo c n l Range
+ -> AChart c n l -> Item c n l -> [Item c n l]
+predictEarleyR pinfo _ item@(Active (Abs _ _ f) _ rng (Lin _ (Cat (cat,_,_):_)) _ _) =
+ topdownRules pinfo ? cat >>= predictEarleyR2 rng
+predictEarleyR _ _ _ = []
+
+predictEarleyR2 :: (Ord c, Ord n, Ord l) => Range -> MCFRule c n l Range -> [Item c n l]
+predictEarleyR2 _ (Rule abs@(Abs _ [] _) (Cnc _ _ lins)) =
+ return $ Final abs (makeRangeRec lins) []
+predictEarleyR2 rng (Rule abs (Cnc _ _ (lin : lins))) =
+ return $ Active abs [] EmptyRange lin lins (emptyChildren abs)
+
+
+----------------------------------------------------------------------
+-- Kilbury --
+
+-- terminal :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> Input t -> [Item c n l]
+-- terminal pinfo toks =
+-- tracePrt "MCFG.Active (Kilbury) - initial terminal rules" (prt . length) $
+-- do Rule abs (Cnc _ _ lins) <- emptyRules pinfo
+-- lins' <- rangeRestRec toks lins
+-- return $ Final abs (makeRangeRec lins') []
+
+initialScan :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> Input t -> [Item c n l]
+initialScan pinfo toks =
+ tracePrt "MCFG.Active (Kilbury) - initial scanned rules + epsilon rules" (prt . length) $
+ do tok <- aElems (inputToken toks)
+ Rule abs (Cnc _ _ lins) <-
+ leftcornerTokens pinfo ? tok ++
+ epsilonRules pinfo
+ lin' : lins' <- rangeRestRec toks lins
+ return $ Active abs [] EmptyRange lin' lins' (emptyChildren abs)
+
+predictKilbury :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> Input t
+ -> AChart c n l -> Item c n l -> [Item c n l]
+predictKilbury pinfo toks _ (Passive cat found) =
+ do Rule abs (Cnc _ _ (Lin l (Cat (_,r,i):syms) : lins)) <- leftcornerCats pinfo ? cat
+ lin' : lins' <- rangeRestRec toks (Lin l syms : lins)
+ rng <- projection r found
+ children <- unifyRec (emptyChildren abs) i found
+ return $ Active abs [] rng lin' lins' children
+predictKilbury _ _ _ _ = []
+
+
+
+----------------------------------------------------------------------
+-- KilburyR --
+
+-- terminalR :: (Ord c, Ord n, Ord l) => MCFPInfo c n l Range -> [Item c n l]
+-- terminalR pinfo =
+-- tracePrt "MCFG.Active (Kilbury Range) - initial terminal rules" (prt . length) $
+-- do Rule abs (Cnc _ _ lins) <- emptyRules pinfo
+-- return $ Final abs (makeRangeRec lins) []
+
+initialScanR :: (Ord c, Ord n, Ord l) => MCFPInfo c n l Range -> [Item c n l]
+initialScanR pinfo =
+ tracePrt "MCFG.Active (Kilbury Range) - initial scanned rules" (prt . length) $
+ do Rule abs (Cnc _ _ (lin : lins)) <-
+ concatMap snd (aAssocs (leftcornerTokens pinfo)) ++
+ epsilonRules pinfo
+ return $ Active abs [] EmptyRange lin lins (emptyChildren abs)
+
+predictKilburyR :: (Ord c, Ord n, Ord l) => MCFPInfo c n l Range
+ -> AChart c n l -> Item c n l -> [Item c n l]
+predictKilburyR pinfo _ (Passive cat found) =
+ do Rule abs (Cnc _ _ (Lin l (Cat (_,r,i):syms) : lins)) <- leftcornerCats pinfo ? cat
+ rng <- projection r found
+ children <- unifyRec (emptyChildren abs) i found
+ return $ Active abs [] rng (Lin l syms) lins children
+predictKilburyR _ _ _ = []
+
+
+----------------------------------------------------------------------
+-- * type definitions
+
+type AChart c n l = ParseChart (Item c n l) (AKey c)
+
+data Item c n l = Active (Abstract c n)
+ (RangeRec l)
+ Range
+ (Lin c l Range)
+ (LinRec c l Range)
+ [RangeRec l]
+ | Final (Abstract c n) (RangeRec l) [RangeRec l]
+ | Passive c (RangeRec l)
+ deriving (Eq, Ord, Show)
+
+data AKey c = Act c
+ | Pass c
+ | Useless
+ | Fin
+ deriving (Eq, Ord, Show)
+
+
+keyof :: Item c n l -> AKey c
+keyof (Active _ _ _ (Lin _ (Cat (next, _, _):_)) _ _) = Act next
+keyof (Final _ _ _) = Fin
+keyof (Passive cat _) = Pass cat
+keyof _ = Useless
+
+
+----------------------------------------------------------------------
+-- for tracing purposes
+
+prtSizes chart = "final=" ++ show (length (chartLookup chart Fin)) ++
+ ", passive=" ++ show (sum [length (chartLookup chart k) |
+ k@(Pass _) <- chartKeys chart ]) ++
+ ", active=" ++ show (sum [length (chartLookup chart k) |
+ k@(Act _) <- chartKeys chart ]) ++
+ ", useless=" ++ show (length (chartLookup chart Useless))
+
+prtChart chart = concat [ "\n*** KEY: " ++ prt k ++
+ prtBefore "\n " (chartLookup chart k) |
+ k <- chartKeys chart ]
+
+prtFinals chart = prtBefore "\n " (chartLookup chart Fin)
+
+instance (Print c, Print n, Print l) => Print (Item c n l) where
+ prt (Active abs found rng lin tofind children) =
+ "? " ++ prt abs ++ ";\n\t" ++
+ "{" ++ prtSep " " found ++ "} " ++ prt rng ++ " . " ++
+ prt lin ++ " {" ++ prtSep " " tofind ++ "}" ++
+ ( if null children then ";" else ";\n\t" ++
+ "{" ++ prtSep "} {" (map (prtSep " ") children) ++ "}" )
+ prt (Passive c rrec) = "- " ++ prt c ++ "; {" ++ prtSep " " rrec ++ "}"
+ prt (Final abs rr rrs) = ": " ++ prt abs ++ ";\n\t{" ++ prtSep " " rr ++ "}" ++
+ ( if null rrs then ";" else ";\n\t" ++
+ "{" ++ prtSep "} {" (map (prtSep " ") rrs) ++ "}" )
+
+instance Print c => Print (AKey c) where
+ prt (Act c) = "Active " ++ prt c
+ prt (Pass c) = "Passive " ++ prt c
+ prt (Fin) = "Final"
+ prt (Useless) = "Useless"
diff --git a/src-3.0/GF/Parsing/MCFG/Active2.hs b/src-3.0/GF/Parsing/MCFG/Active2.hs
new file mode 100644
index 000000000..7ad8627bc
--- /dev/null
+++ b/src-3.0/GF/Parsing/MCFG/Active2.hs
@@ -0,0 +1,237 @@
+----------------------------------------------------------------------
+-- |
+-- Maintainer : PL
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- > CVS $Date: 2005/08/08 09:01:25 $
+-- > CVS $Author: peb $
+-- > CVS $Revision: 1.2 $
+--
+-- MCFG parsing, the active algorithm (alternative version)
+-----------------------------------------------------------------------------
+
+module GF.Parsing.MCFG.Active2 (parse) where
+
+import GF.Data.GeneralDeduction
+import GF.Data.Assoc
+
+import GF.Formalism.GCFG
+import GF.Formalism.MCFG
+import GF.Formalism.Utilities
+
+import GF.Parsing.MCFG.Range
+import GF.Parsing.MCFG.PInfo
+
+import GF.System.Tracing
+
+import Control.Monad (guard)
+
+import GF.Infra.Print
+
+----------------------------------------------------------------------
+-- * parsing
+
+--parse :: (Ord n, Ord c, Ord l, Ord t) => String -> MCFParser c n l t
+parse strategy pinfo starts toks =
+ accumAssoc groupSyntaxNodes $
+ [ ((cat, found), SNode fun (zip rhs rrecs)) |
+ Final (Abs cat rhs fun) found rrecs <- chartLookup chart Fin ]
+ where chart = process strategy pinfo starts toks
+
+process :: (Ord n, Ord c, Ord l, Ord t) =>
+ String -> MCFPInfo c n l t -> [c] -> Input t -> AChart c n l t
+process strategy pinfo starts toks
+ = tracePrt "MCFG.Active - chart size" prtSizes $
+ buildChart keyof (complete : combine : convert : rules) axioms
+ where rules | isNil strategy = [scan toks]
+ | isBU strategy = [scan toks, predictKilbury pinfo toks]
+ | isTD strategy = [scan toks, predictEarley pinfo toks]
+ axioms | isNil strategy = predict pinfo toks
+ | isBU strategy = terminal pinfo toks ++ initialScan pinfo toks
+ | isTD strategy = initial pinfo starts toks
+
+isNil s = s=="n"
+isBU s = s=="b"
+isTD s = s=="t"
+
+-- used in prediction
+emptyChildren :: Abstract c n -> [RangeRec l]
+emptyChildren (Abs _ rhs _) = replicate (length rhs) []
+
+makeMaxRange (Range (_, j)) = Range (j, j)
+makeMaxRange EmptyRange = EmptyRange
+
+
+----------------------------------------------------------------------
+-- * inference rules
+
+-- completion
+complete :: (Ord c, Ord n, Ord l, Ord t) => AChart c n l t -> Item c n l t -> [Item c n l t]
+complete _ (Active rule found rng (Lin l []) (lin:lins) recs) =
+ return $ Active rule (found ++ [(l, rng)]) EmptyRange lin lins recs
+complete _ _ = []
+
+-- scanning
+--scan :: (Ord c, Ord n, Ord l, Ord t) => AChart c n l t -> Item c n l t -> [Item c n l t]
+scan inp _ (Active rule found rng (Lin l (Tok tok:syms)) lins recs) =
+ do rng' <- map makeRange (inputToken inp ? tok)
+ rng'' <- concatRange rng rng'
+ return $ Active rule found rng'' (Lin l syms) lins recs
+scan _ _ _ = []
+
+-- | Creates an Active Item every time it is possible to combine
+-- an Active Item from the agenda with a Passive Item from the Chart
+combine :: (Ord c, Ord n, Ord l, Ord t) => AChart c n l t -> Item c n l t -> [Item c n l t]
+combine chart item@(Active _ _ _ (Lin _ (Cat (c,_,_):_)) _ _) =
+ do Passive _c found <- chartLookup chart (Pass c)
+ combine2 chart found item
+combine chart (Passive c found) =
+ do item <- chartLookup chart (Act c)
+ combine2 chart found item
+combine _ _ = []
+
+combine2 chart found' (Active rule found rng (Lin l (Cat (c, r, d):syms)) lins recs) =
+ do rng' <- projection r found'
+ rng'' <- concatRange rng rng'
+ recs' <- unifyRec recs d found'
+ return $ Active rule found rng'' (Lin l syms) lins recs'
+
+-- | Active Items with nothing to find are converted to Final items,
+-- which in turn are converted to Passive Items
+convert :: (Ord c, Ord n, Ord l, Ord t) => AChart c n l t -> Item c n l t -> [Item c n l t]
+convert _ (Active rule found rng (Lin lbl []) [] recs) =
+ return $ Final rule (found ++ [(lbl,rng)]) recs
+convert _ (Final (Abs cat _ _) found _) =
+ return $ Passive cat found
+convert _ _ = []
+
+
+----------------------------------------------------------------------
+-- Naive --
+
+predict :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> Input t -> [Item c n l t]
+predict pinfo toks = tracePrt "MCFG.Active (Naive) - predicted rules" (prt . length) $
+ do Rule abs (Cnc _ _ (lin:lins)) <- rulesMatchingInput pinfo toks
+ return $ Active abs [] EmptyRange lin lins (emptyChildren abs)
+
+
+----------------------------------------------------------------------
+-- Earley --
+
+-- anropas med alla startkategorier
+initial :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> [c] -> Input t -> [Item c n l t]
+initial pinfo starts toks =
+ tracePrt "MCFG.Active (Earley) - initial rules" (prt . length) $
+ do cat <- starts
+ Rule abs (Cnc _ _ (lin:lins)) <- topdownRules pinfo ? cat
+ return $ Active abs [] (Range (0, 0)) lin lins (emptyChildren abs)
+
+predictEarley :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> Input t
+ -> AChart c n l t -> Item c n l t -> [Item c n l t]
+predictEarley pinfo toks _ item@(Active (Abs _ _ f) _ rng (Lin _ (Cat (cat,_,_):_)) _ _) =
+ topdownRules pinfo ? cat >>= predictEarley2 toks rng
+predictEarley _ _ _ _ = []
+
+predictEarley2 :: (Ord c, Ord n, Ord l, Ord t) => Input t -> Range -> MCFRule c n l t -> [Item c n l t]
+predictEarley2 toks _ (Rule abs@(Abs _ [] _) (Cnc _ _ lins)) =
+ do lins' <- rangeRestRec toks lins
+ return $ Final abs (makeRangeRec lins') []
+predictEarley2 toks rng (Rule abs (Cnc _ _ (lin:lins))) =
+ return $ Active abs [] EmptyRange lin lins (emptyChildren abs)
+
+
+----------------------------------------------------------------------
+-- Kilbury --
+
+terminal :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> Input t -> [Item c n l t]
+terminal pinfo toks =
+ tracePrt "MCFG.Active (Kilbury) - initial terminal rules" (prt . length) $
+ do Rule abs (Cnc _ _ lins) <- emptyRules pinfo
+ lins' <- rangeRestRec toks lins
+ return $ Final abs (makeRangeRec lins') []
+
+initialScan :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> Input t -> [Item c n l t]
+initialScan pinfo toks =
+ tracePrt "MCFG.Active (Kilbury) - initial scanned rules" (prt . length) $
+ do tok <- aElems (inputToken toks)
+ Rule abs (Cnc _ _ (lin:lins)) <- leftcornerTokens pinfo ? tok
+ return $ Active abs [] EmptyRange lin lins (emptyChildren abs)
+
+predictKilbury :: (Ord c, Ord n, Ord l, Ord t) => MCFPInfo c n l t -> Input t
+ -> AChart c n l t -> Item c n l t -> [Item c n l t]
+predictKilbury pinfo toks _ (Passive cat found) =
+ do Rule abs (Cnc _ _ (Lin l (Cat (_,r,i):syms) : lins)) <- leftcornerCats pinfo ? cat
+ rng <- projection r found
+ children <- unifyRec (emptyChildren abs) i found
+ return $ Active abs [] rng (Lin l syms) lins children
+predictKilbury _ _ _ _ = []
+
+
+----------------------------------------------------------------------
+-- * type definitions
+
+type AChart c n l t = ParseChart (Item c n l t) (AKey c t)
+
+data Item c n l t = Active (Abstract c n)
+ (RangeRec l)
+ Range
+ (Lin c l t)
+ (LinRec c l t)
+ [RangeRec l]
+ | Final (Abstract c n) (RangeRec l) [RangeRec l]
+ | Passive c (RangeRec l)
+ deriving (Eq, Ord, Show)
+
+data AKey c t = Act c
+ | ActTok t
+ | Pass c
+ | Useless
+ | Fin
+ deriving (Eq, Ord, Show)
+
+
+keyof :: Item c n l t -> AKey c t
+keyof (Active _ _ _ (Lin _ (Cat (next, _, _):_)) _ _) = Act next
+keyof (Active _ _ _ (Lin _ (Tok tok:_)) _ _) = ActTok tok
+keyof (Final _ _ _) = Fin
+keyof (Passive cat _) = Pass cat
+keyof _ = Useless
+
+
+----------------------------------------------------------------------
+-- for tracing purposes
+
+prtSizes chart = "final=" ++ show (length (chartLookup chart Fin)) ++
+ ", passive=" ++ show (sum [length (chartLookup chart k) |
+ k@(Pass _) <- chartKeys chart ]) ++
+ ", active=" ++ show (sum [length (chartLookup chart k) |
+ k@(Act _) <- chartKeys chart ]) ++
+ ", active-tok=" ++ show (sum [length (chartLookup chart k) |
+ k@(ActTok _) <- chartKeys chart ]) ++
+ ", useless=" ++ show (length (chartLookup chart Useless))
+
+prtChart chart = concat [ "\n*** KEY: " ++ prt k ++
+ prtBefore "\n " (chartLookup chart k) |
+ k <- chartKeys chart ]
+
+prtFinals chart = prtBefore "\n " (chartLookup chart Fin)
+
+instance (Print c, Print n, Print l, Print t) => Print (Item c n l t) where
+ prt (Active abs found rng lin tofind children) =
+ "? " ++ prt abs ++ ";\n\t" ++
+ "{" ++ prtSep " " found ++ "} " ++ prt rng ++ " . " ++
+ prt lin ++ " {" ++ prtSep " " tofind ++ "}" ++
+ ( if null children then ";" else ";\n\t" ++
+ "{" ++ prtSep "} {" (map (prtSep " ") children) ++ "}" )
+ prt (Passive c rrec) = "- " ++ prt c ++ "; {" ++ prtSep " " rrec ++ "}"
+ prt (Final abs rr rrs) = ": " ++ prt abs ++ ";\n\t{" ++ prtSep " " rr ++ "}" ++
+ ( if null rrs then ";" else ";\n\t" ++
+ "{" ++ prtSep "} {" (map (prtSep " ") rrs) ++ "}" )
+
+instance (Print c, Print t) => Print (AKey c t) where
+ prt (Act c) = "Active " ++ prt c
+ prt (ActTok t) = "Active-Tok " ++ prt t
+ prt (Pass c) = "Passive " ++ prt c
+ prt (Fin) = "Final"
+ prt (Useless) = "Useless"
diff --git a/src-3.0/GF/Parsing/MCFG/FastActive.hs b/src-3.0/GF/Parsing/MCFG/FastActive.hs
new file mode 100644
index 000000000..0a8e24b55
--- /dev/null
+++ b/src-3.0/GF/Parsing/MCFG/FastActive.hs
@@ -0,0 +1,176 @@
+----------------------------------------------------------------------
+-- |
+-- Maintainer : Peter Ljunglöf
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- MCFG parsing, the active algorithm, optimized version
+-- structure stolen from Krasimir Angelov's GF.Parsing.FCFG.Active
+-----------------------------------------------------------------------------
+
+module GF.Parsing.MCFG.FastActive (parse) where
+
+import GF.Data.GeneralDeduction
+import GF.Data.Assoc
+import GF.Data.Utilities
+
+import GF.Formalism.GCFG
+import GF.Formalism.MCFG
+import GF.Formalism.Utilities
+
+import GF.Infra.Ident
+
+import GF.Parsing.MCFG.Range
+import GF.Parsing.MCFG.PInfo
+
+import GF.System.Tracing
+
+import Control.Monad (guard)
+
+import GF.Infra.Print
+
+import qualified Data.List as List
+import qualified Data.Map as Map
+import qualified Data.Set as Set
+import Data.Array
+
+----------------------------------------------------------------------
+-- * parsing
+
+-- parse :: (Ord c, Ord n, Ord l, Ord t) => String -> MCFParser c n l t
+parse strategy pinfo starts =
+ accumAssoc groupSyntaxNodes $
+ [ ((cat, found), SNode fun (zip rhs rrecs)) |
+ Final (Abs cat rhs fun) found rrecs <- listXChartFinal chart ]
+ where chart = process strategy pinfo axioms emptyXChart
+
+ -- axioms | isBU strategy = terminal pinfo toks ++ initialScan pinfo toks
+ axioms | isBU strategy = initialBU pinfo
+ | isTD strategy = initialTD pinfo starts
+
+isBU s = s=="b"
+isTD s = s=="t"
+
+-- used in prediction
+emptyChildren :: Abstract c n -> [RangeRec l]
+emptyChildren (Abs _ rhs _) = replicate (length rhs) []
+
+updateChildren :: Eq l => [RangeRec l] -> Int -> RangeRec l -> [[RangeRec l]]
+updateChildren recs i rec = updateNthM update i recs
+ where update rec' = do guard (null rec' || rec' == rec)
+ return rec
+
+process :: (Ord c, Ord n, Ord l) => String -> MCFPInfo c n l Range -> [Item c n l] -> XChart c n l -> XChart c n l
+process strategy pinfo [] chart = chart
+process strategy pinfo (item:items) chart = process strategy pinfo items $! univRule item chart
+ where
+ univRule item@(Active abs found rng (Lin l syms) lins recs) chart
+ = case syms of
+ Cat(c,r,d) : syms' ->
+ case insertXChart chart item c of
+ Nothing -> chart
+ Just chart ->
+ let items = -- predict topdown
+ [ Active abs [] EmptyRange lin lins (emptyChildren abs) |
+ isTD strategy,
+ Rule abs (Cnc _ _ (lin:lins)) <- topdownRules pinfo ? c ] ++
+
+ -- combine
+ [ Active abs found rng'' (Lin l syms') lins recs' |
+ Final _ found' _ <- lookupXChartFinal chart c,
+ rng' <- projection r found',
+ rng'' <- concatRange rng rng',
+ recs' <- updateChildren recs d found' ]
+ in process strategy pinfo items chart
+
+ -- scan
+ Tok rng' : syms' ->
+ let items = [ Active abs found rng'' (Lin l syms') lins recs |
+ rng'' <- concatRange rng rng' ]
+ in process strategy pinfo items chart
+
+ -- complete
+ [] -> case lins of
+ (lin':lins') -> univRule (Active abs ((l,rng):found) EmptyRange lin' lins' recs) chart
+ [] -> univRule (Final abs (reverse ((l,rng):found)) recs) chart
+
+ univRule item@(Final abs@(Abs cat _ _) found' recs) chart =
+ case insertXChart chart item cat of
+ Nothing -> chart
+ Just chart ->
+ let items = -- predict bottomup
+ [ Active abs [] rng (Lin l syms') lins children |
+ isBU strategy,
+ Rule abs (Cnc _ _ (Lin l (Cat(c,r,d):syms') : lins)) <- leftcornerCats pinfo ? cat,
+ -- lin' : lins' <- rangeRestRec toks (Lin l syms' : lins),
+ rng <- projection r found',
+ children <- unifyRec (emptyChildren abs) d found' ] ++
+
+ -- combine
+ [ Active abs found rng'' (Lin l syms') lins recs' |
+ Active abs found rng (Lin l (Cat(c,r,d):syms')) lins recs <- lookupXChartAct chart cat,
+ rng' <- projection r found',
+ rng'' <- concatRange rng rng',
+ recs' <- updateChildren recs d found' ]
+ in process strategy pinfo items chart
+
+----------------------------------------------------------------------
+-- * XChart
+
+data XChart c n l = XChart !(AChart c n l) !(AChart c n l)
+type AChart c n l = ParseChart (Item c n l) c
+
+data Item c n l = Active (Abstract c n)
+ (RangeRec l)
+ Range
+ (Lin c l Range)
+ (LinRec c l Range)
+ [RangeRec l]
+ | Final (Abstract c n) (RangeRec l) [RangeRec l]
+-- | Passive c (RangeRec l)
+ deriving (Eq, Ord, Show)
+
+emptyXChart :: (Ord c, Ord n, Ord l) => XChart c n l
+emptyXChart = XChart emptyChart emptyChart
+
+insertXChart (XChart actives finals) item@(Active _ _ _ _ _ _) c =
+ case chartInsert actives item c of
+ Nothing -> Nothing
+ Just actives -> Just (XChart actives finals)
+
+insertXChart (XChart actives finals) item@(Final _ _ _) c =
+ case chartInsert finals item c of
+ Nothing -> Nothing
+ Just finals -> Just (XChart actives finals)
+
+lookupXChartAct (XChart actives finals) c = chartLookup actives c
+lookupXChartFinal (XChart actives finals) c = chartLookup finals c
+
+listXChartAct (XChart actives finals) = chartList actives
+listXChartFinal (XChart actives finals) = chartList finals
+
+
+----------------------------------------------------------------------
+-- Earley --
+
+-- called with all starting categories
+initialTD :: (Ord c, Ord n, Ord l) => MCFPInfo c n l Range -> [c] -> [Item c n l]
+initialTD pinfo starts =
+ [ Active abs [] (Range (0, 0)) lin' lins' (emptyChildren abs) |
+ cat <- starts,
+ Rule abs (Cnc _ _ (lin':lins')) <- topdownRules pinfo ? cat ]
+ -- lin' : lins' <- rangeRestRec toks lins
+
+
+----------------------------------------------------------------------
+-- Kilbury --
+
+initialBU :: (Ord c, Ord n, Ord l) => MCFPInfo c n l Range -> [Item c n l]
+initialBU pinfo =
+ [ Active abs [] EmptyRange lin' lins' (emptyChildren abs) |
+ -- do tok <- aElems (inputToken toks)
+ Rule abs (Cnc _ _ (lin':lins')) <-
+ concatMap snd (aAssocs (leftcornerTokens pinfo)) ++
+ -- leftcornerTokens pinfo ? tok ++
+ epsilonRules pinfo ]
+ -- lin' : lins' <- rangeRestRec toks lins
diff --git a/src-3.0/GF/Parsing/MCFG/Incremental.hs b/src-3.0/GF/Parsing/MCFG/Incremental.hs
new file mode 100644
index 000000000..bd5b4114d
--- /dev/null
+++ b/src-3.0/GF/Parsing/MCFG/Incremental.hs
@@ -0,0 +1,178 @@
+----------------------------------------------------------------------
+-- |
+-- Maintainer : PL
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- > CVS $Date: 2005/08/08 09:01:25 $
+-- > CVS $Author: peb $
+-- > CVS $Revision: 1.4 $
+--
+-- MCFG parsing, the incremental algorithm
+-----------------------------------------------------------------------------
+
+module GF.Parsing.MCFG.Incremental (parse, parseR) where
+
+import Data.List
+import Control.Monad (guard)
+
+import GF.Data.Utilities (select)
+import GF.Data.GeneralDeduction
+import GF.Data.Assoc
+
+import GF.Formalism.GCFG
+import GF.Formalism.MCFG
+import GF.Formalism.Utilities
+
+import GF.Parsing.MCFG.Range
+import GF.Parsing.MCFG.PInfo
+
+import GF.System.Tracing
+import GF.Infra.Print
+
+----------------------------------------------------------------------
+-- parsing
+
+parse :: (Ord n, Ord c, Ord l, Ord t) => MCFParser c n l t
+parse pinfo starts toks =
+ accumAssoc groupSyntaxNodes $
+ [ ((cat, found), SNode fun (zip rhs rrecs)) |
+ Final (Abs cat rhs fun) found rrecs <- chartLookup chart Fin ]
+ where chart = process pinfo toks ntoks
+ ntoks = snd (inputBounds toks)
+
+-- parseR :: (Ord n, Ord c, Ord l, Ord t) => MCFParser c n l t
+parseR pinfo starts ntoks =
+ accumAssoc groupSyntaxNodes $
+ [ ((cat, found), SNode fun (zip rhs rrecs)) |
+ Final (Abs cat rhs fun) found rrecs <- chartLookup chart Fin ]
+ where chart = processR pinfo ntoks
+
+process :: (Ord n, Ord c, Ord l, Ord t) => MCFPInfo c n l t -> Input t -> Int -> IChart c n l
+process pinfo toks ntoks
+ = tracePrt "MCFG.Incremental - chart size" prtSizes $
+ buildChart keyof [complete ntoks, scan, combine, convert] (predict pinfo toks ntoks)
+
+processR :: (Ord n, Ord c, Ord l) => MCFPInfo c n l Range -> Int -> IChart c n l
+processR pinfo ntoks
+ = tracePrt "MCFG.Incremental Range - chart size" prtSizes $
+ buildChart keyof [complete ntoks, scan, combine, convert] (predictR pinfo ntoks)
+
+complete :: (Ord n, Ord c, Ord l) => Int -> IChart c n l -> Item c n l -> [Item c n l]
+complete ntoks _ (Active rule found rng (Lin l []) lins recs) =
+ do (lin, lins') <- select lins
+ k <- [minRange rng .. ntoks]
+ return $ Active rule (found ++ [(l, rng)]) (Range (k,k)) lin lins' recs
+complete _ _ _ = []
+
+
+predict :: (Ord n, Ord c, Ord l, Ord t) => MCFPInfo c n l t -> Input t -> Int -> [Item c n l]
+predict pinfo toks n =
+ tracePrt "MCFG.Incremental - predicted rules" (prt . length) $
+ do Rule abs@(Abs _ rhs _) (Cnc _ _ lins) <- rulesMatchingInput pinfo toks
+ let daughters = replicate (length rhs) []
+ lins' <- rangeRestRec toks lins
+ (lin', lins'') <- select lins'
+ k <- [0..n]
+ return $ Active abs [] (Range (k,k)) lin' lins'' daughters
+
+
+predictR :: (Ord n, Ord c, Ord l) => MCFPInfo c n l Range -> Int -> [Item c n l]
+predictR pinfo n =
+ tracePrt "MCFG.Incremental Range - predicted rules" (prt . length) $
+ do Rule abs@(Abs _ rhs _) (Cnc _ _ lins) <- allRules pinfo
+ let daughters = replicate (length rhs) []
+ (lin, lins') <- select lins
+ k <- [0..n]
+ return $ Active abs [] (Range (k,k)) lin lins' daughters
+
+
+scan :: (Ord n, Ord c, Ord l) => IChart c n l -> Item c n l -> [Item c n l]
+scan _ (Active abs found rng (Lin l (Tok rng':syms)) lins recs) =
+ do rng'' <- concatRange rng rng'
+ return $ Active abs found rng'' (Lin l syms) lins recs
+scan _ _ = []
+
+
+combine :: (Ord n, Ord c, Ord l) => IChart c n l -> Item c n l -> [Item c n l]
+combine chart active@(Active _ _ rng (Lin _ (Cat (c,l,_):_)) _ _) =
+ do passive <- chartLookup chart (Pass c l (maxRange rng))
+ combine2 active passive
+combine chart passive@(Active (Abs c _ _) _ rng (Lin l []) _ _) =
+ do active <- chartLookup chart (Act c l (minRange rng))
+ combine2 active passive
+combine _ _ = []
+
+combine2 (Active abs found rng (Lin l (Cat (c,l',d):syms)) lins recs)
+ (Active _ found' rng' _ _ _)
+ = do rng'' <- concatRange rng rng'
+ recs' <- unifyRec recs d found''
+ return $ Active abs found rng'' (Lin l syms) lins recs'
+ where found'' = found' ++ [(l',rng')]
+
+
+convert _ (Active rule found rng (Lin lbl []) [] recs) =
+ return $ Final rule (found ++ [(lbl,rng)]) recs
+convert _ _ = []
+
+----------------------------------------------------------------------
+-- type definitions
+
+type IChart c n l = ParseChart (Item c n l) (IKey c l)
+
+data Item c n l = Active (Abstract c n)
+ (RangeRec l)
+ Range
+ (Lin c l Range)
+ (LinRec c l Range)
+ [RangeRec l]
+ | Final (Abstract c n) (RangeRec l) [RangeRec l]
+-- | Passive c (RangeRec l)
+ deriving (Eq, Ord, Show)
+
+data IKey c l = Act c l Int
+ | Pass c l Int
+ | Useless
+ | Fin
+ deriving (Eq, Ord, Show)
+
+keyof :: Item c n l -> IKey c l
+keyof (Active _ _ rng (Lin _ (Cat (next,lbl,_):_)) _ _)
+ = Act next lbl (maxRange rng)
+keyof (Active (Abs cat _ _) found rng (Lin lbl []) _ _)
+ = Pass cat lbl (minRange rng)
+keyof (Final _ _ _) = Fin
+keyof _
+ = Useless
+
+
+----------------------------------------------------------------------
+-- for tracing purposes
+prtSizes chart = "final=" ++ show (length (chartLookup chart Fin)) ++
+ ", passive=" ++ show (sum [length (chartLookup chart k) |
+ k@(Pass _ _ _) <- chartKeys chart ]) ++
+ ", active=" ++ show (sum [length (chartLookup chart k) |
+ k@(Act _ _ _) <- chartKeys chart ]) ++
+ ", useless=" ++ show (length (chartLookup chart Useless))
+
+prtChart chart = concat [ "\n*** KEY: " ++ prt k ++
+ prtBefore "\n " (chartLookup chart k) |
+ k <- chartKeys chart ]
+
+instance (Print c, Print n, Print l) => Print (Item c n l) where
+ prt (Active abs found rng lin tofind children) =
+ "? " ++ prt abs ++ ";\n\t" ++
+ "{" ++ prtSep " " found ++ "} " ++ prt rng ++ " . " ++
+ prt lin ++ "{" ++ prtSep " " tofind ++ "}" ++
+ ( if null children then ";" else ";\n\t" ++
+ "{" ++ prtSep "} {" (map (prtSep " ") children) ++ "}" )
+-- prt (Passive c rrec) = "- " ++ prt c ++ "; {" ++ prtSep " " rrec ++ "}"
+ prt (Final abs rr rrs) = ": " ++ prt abs ++ ";\n\t{" ++ prtSep " " rr ++ "}" ++
+ ( if null rrs then ";" else ";\n\t" ++
+ "{" ++ prtSep "} {" (map (prtSep " ") rrs) ++ "}" )
+
+instance (Print c, Print l) => Print (IKey c l) where
+ prt (Act c l i) = "Active " ++ prt c ++ " " ++ prt l ++ " @ " ++ prt i
+ prt (Pass c l i) = "Passive " ++ prt c ++ " " ++ prt l ++ " @ " ++ prt i
+ prt (Fin) = "Final"
+ prt (Useless) = "Useless"
diff --git a/src-3.0/GF/Parsing/MCFG/Incremental2.hs b/src-3.0/GF/Parsing/MCFG/Incremental2.hs
new file mode 100644
index 000000000..db6c3084e
--- /dev/null
+++ b/src-3.0/GF/Parsing/MCFG/Incremental2.hs
@@ -0,0 +1,157 @@
+----------------------------------------------------------------------
+-- |
+-- Maintainer : PL
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- > CVS $Date: 2005/08/08 09:01:25 $
+-- > CVS $Author: peb $
+-- > CVS $Revision: 1.3 $
+--
+-- MCFG parsing, the incremental algorithm (alternative version)
+-----------------------------------------------------------------------------
+
+module GF.Parsing.MCFG.Incremental2 (parse) where
+
+import Data.List
+import Data.Array
+import Control.Monad (guard)
+
+import GF.Data.Utilities (select)
+import GF.Data.Assoc
+import GF.Data.IncrementalDeduction
+
+import GF.Formalism.GCFG
+import GF.Formalism.MCFG
+import GF.Formalism.Utilities
+
+import GF.Parsing.MCFG.Range
+import GF.Parsing.MCFG.PInfo
+
+import GF.System.Tracing
+import GF.Infra.Print
+
+----------------------------------------------------------------------
+-- parsing
+
+-- parseR :: (Ord n, Ord c, Ord l, Ord t) => MCFParser c n l t
+parse pinfo starts inp =
+ accumAssoc groupSyntaxNodes $
+ [ ((cat, found), SNode fun (zip rhs rrecs)) |
+ k <- uncurry enumFromTo (inputBounds inp),
+ Final (Abs cat rhs fun) found rrecs <- chartLookup chart k Fin ]
+ where chart = process pinfo inp
+
+--process :: (Ord n, Ord c, Ord l) => MCFPInfo c n l Range -> (Int, Int) -> IChart c n l
+process pinfo inp
+ = tracePrt "MCFG.Incremental - chart size"
+ (prt . map (prtSizes finalChart . fst) . assocs) $
+ finalChart
+ where finalChart = buildChart keyof rules axioms inBounds
+ axioms k = tracePrt ("MCFG.Incremental - axioms for " ++ show k) (prt . length) $
+ predict k ++ scan k ++ complete1 k
+ rules k item = complete2 k item ++ combine k item ++ convert k item
+ inBounds = inputBounds inp
+
+ -- axioms: predict + scan + complete
+ predict k = do Rule abs@(Abs _ rhs _) (Cnc _ _ lins) <- rulesMatchingInput pinfo inp
+ let daughters = replicate (length rhs) []
+ (lin, lins') <- select lins
+ return $ Active abs [] k lin lins' daughters
+
+ scan k = do (tok, js) <- aAssocs (inputTo inp ! k)
+ j <- js
+ Active abs found i (Lin l (Tok _tok:syms)) lins recs <-
+ chartLookup finalChart j (ActTok tok)
+ return $ Active abs found i (Lin l syms) lins recs
+
+ complete1 k = do j <- [fst inBounds .. k-1]
+ Active abs found i (Lin l _Nil) lins recs <-
+ chartLookup finalChart j Pass
+ let found' = found ++ [(l, makeRange (i,j))]
+ (lin, lins') <- select lins
+ return $ Active abs found' k lin lins' recs
+
+ -- rules: convert + combine + complete
+ convert k (Active rule found j (Lin lbl []) [] recs) =
+ let found' = found ++ [(lbl, makeRange (j,k))]
+ in return $ Final rule found' recs
+ convert _ _ = []
+
+ combine k (Active (Abs cat _ _) found' j (Lin lbl []) _ _) =
+ do guard (j < k) ---- cannot handle epsilon-rules
+ Active abs found i (Lin l (Cat (_cat,_lbl,nr):syms)) lins recs <-
+ chartLookup finalChart j (Act cat lbl)
+ let found'' = found' ++ [(lbl, makeRange (j,k))]
+ recs' <- unifyRec recs nr found''
+ return $ Active abs found i (Lin l syms) lins recs'
+ combine _ _ = []
+
+ complete2 k (Active abs found i (Lin l []) lins recs) =
+ do let found' = found ++ [(l, makeRange (i,k))]
+ (lin, lins') <- select lins
+ return $ Active abs found' k lin lins' recs
+ complete2 _ _ = []
+
+----------------------------------------------------------------------
+-- type definitions
+
+type IChart c n l t = IncrementalChart (Item c n l t) (IKey c l t)
+
+data Item c n l t = Active (Abstract c n)
+ (RangeRec l)
+ Int
+ (Lin c l t)
+ (LinRec c l t)
+ [RangeRec l]
+ | Final (Abstract c n) (RangeRec l) [RangeRec l]
+ ---- | Passive c (RangeRec l)
+ deriving (Eq, Ord, Show)
+
+data IKey c l t = Act c l
+ | ActTok t
+ ---- | Useless
+ | Pass
+ | Fin
+ deriving (Eq, Ord, Show)
+
+keyof :: Item c n l t -> IKey c l t
+keyof (Active _ _ _ (Lin _ (Cat (next,lbl,_):_)) _ _) = Act next lbl
+keyof (Active _ _ _ (Lin _ (Tok tok:_)) _ _) = ActTok tok
+keyof (Active _ _ _ (Lin _ []) _ _) = Pass
+keyof (Final _ _ _) = Fin
+-- keyof _ = Useless
+
+
+----------------------------------------------------------------------
+-- for tracing purposes
+prtSizes chart k = "f=" ++ show (length (chartLookup chart k Fin)) ++
+ " p=" ++ show (length (chartLookup chart k Pass)) ++
+ " a=" ++ show (sum [length (chartLookup chart k key) |
+ key@(Act _ _) <- chartKeys chart k ]) ++
+ " t=" ++ show (sum [length (chartLookup chart k key) |
+ key@(ActTok _) <- chartKeys chart k ])
+ -- " u=" ++ show (length (chartLookup chart k Useless))
+
+-- prtChart chart = concat [ "\n*** KEY: " ++ prt k ++
+-- prtBefore "\n " (chartLookup chart k) |
+-- k <- chartKeys chart ]
+
+instance (Print c, Print n, Print l, Print t) => Print (Item c n l t) where
+ prt (Active abs found rng lin tofind children) =
+ "? " ++ prt abs ++ ";\n\t" ++
+ "{" ++ prtSep " " found ++ "} " ++ prt rng ++ " . " ++
+ prt lin ++ "{" ++ prtSep " " tofind ++ "}" ++
+ ( if null children then ";" else ";\n\t" ++
+ "{" ++ prtSep "} {" (map (prtSep " ") children) ++ "}" )
+ -- prt (Passive c rrec) = "- " ++ prt c ++ "; {" ++ prtSep " " rrec ++ "}"
+ prt (Final abs rr rrs) = ": " ++ prt abs ++ ";\n\t{" ++ prtSep " " rr ++ "}" ++
+ ( if null rrs then ";" else ";\n\t" ++
+ "{" ++ prtSep "} {" (map (prtSep " ") rrs) ++ "}" )
+
+instance (Print c, Print l, Print t) => Print (IKey c l t) where
+ prt (Act c l) = "Active " ++ prt c ++ " " ++ prt l
+ prt (ActTok t) = "ActiveTok " ++ prt t
+ -- prt (Pass c l i) = "Passive " ++ prt c ++ " " ++ prt l ++ " @ " ++ prt i
+ prt (Fin) = "Final"
+ -- prt (Useless) = "Useless"
diff --git a/src-3.0/GF/Parsing/MCFG/Naive.hs b/src-3.0/GF/Parsing/MCFG/Naive.hs
new file mode 100644
index 000000000..7d1fa0a8a
--- /dev/null
+++ b/src-3.0/GF/Parsing/MCFG/Naive.hs
@@ -0,0 +1,142 @@
+----------------------------------------------------------------------
+-- |
+-- Maintainer : PL
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- > CVS $Date: 2005/08/08 09:01:25 $
+-- > CVS $Author: peb $
+-- > CVS $Revision: 1.5 $
+--
+-- MCFG parsing, the naive algorithm
+-----------------------------------------------------------------------------
+
+module GF.Parsing.MCFG.Naive (parse, parseR) where
+
+import Control.Monad (guard)
+
+-- GF modules
+import GF.Data.GeneralDeduction
+import GF.Formalism.GCFG
+import GF.Formalism.MCFG
+import GF.Formalism.Utilities
+import GF.Parsing.MCFG.Range
+import GF.Parsing.MCFG.PInfo
+import GF.Data.SortedList
+import GF.Data.Assoc
+import GF.System.Tracing
+
+import GF.Infra.Print
+
+----------------------------------------------------------------------
+-- * parsing
+
+-- | Builds a chart from the initial agenda, given by prediction, and the inference rules
+parse :: (Ord t, Ord n, Ord c, Ord l) => MCFParser c n l t
+parse pinfo starts toks
+ = accumAssoc groupSyntaxNodes $
+ [ ((cat, makeRangeRec lins), SNode fun (zip rhs rrecs)) |
+ Active (Abs cat _Nil fun, rhs) lins rrecs <- chartLookup chart Final ]
+ where chart = process pinfo toks
+
+-- | Builds a chart from the initial agenda, given by prediction, and the inference rules
+-- parseR :: (Ord t, Ord n, Ord c, Ord l) => MCFParser c n l t
+parseR pinfo starts
+ = accumAssoc groupSyntaxNodes $
+ [ ((cat, makeRangeRec lins), SNode fun (zip rhs rrecs)) |
+ Active (Abs cat _Nil fun, rhs) lins rrecs <- chartLookup chart Final ]
+ where chart = processR pinfo
+
+process :: (Ord t, Ord n, Ord c, Ord l) => MCFPInfo c n l t -> Input t -> NChart c n l
+process pinfo toks
+ = tracePrt "MCFG.Naive - chart size" prtSizes $
+ buildChart keyof [convert, combine] (predict pinfo toks)
+
+processR :: (Ord n, Ord c, Ord l) => MCFPInfo c n l Range -> NChart c n l
+processR pinfo
+ = tracePrt "MCFG.Naive Range - chart size" prtSizes $
+ buildChart keyof [convert, combine] (predictR pinfo)
+
+
+----------------------------------------------------------------------
+-- * inference rules
+
+-- Creates an Active Item of every Rule in the Grammar to give the initial Agenda
+predict :: (Ord l, Ord t) => MCFPInfo c n l t -> Input t -> [Item c n l]
+predict pinfo toks = tracePrt "MCFG.Naive - predicted rules" (prt . length) $
+ do Rule abs (Cnc _ _ lins) <- rulesMatchingInput pinfo toks
+ lins' <- rangeRestRec toks lins
+ return $ Active (abs, []) lins' []
+
+-- Creates an Active Item of every Rule in the Grammar to give the initial Agenda
+predictR :: (Ord l) => MCFPInfo c n l Range -> [Item c n l]
+predictR pinfo = tracePrt "MCFG.Naive Range - predicted rules" (prt . length) $
+ do Rule abs (Cnc _ _ lins) <- allRules pinfo
+ return $ Active (abs, []) lins []
+
+-- | Creates an Active Item every time it is possible to combine
+-- an Active Item from the agenda with a Passive Item from the Chart
+combine :: (Ord n, Ord c, Ord l) => NChart c n l -> Item c n l -> [Item c n l]
+combine chart item@(Active (Abs _ (c:_) _, _) _ _) =
+ do Passive _c rrec <- chartLookup chart (Pass c)
+ combine2 chart rrec item
+combine chart (Passive c rrec) =
+ do item <- chartLookup chart (Act c)
+ combine2 chart rrec item
+combine _ _ = []
+
+combine2 chart rrec (Active (Abs nt (c:find) f, found) lins rrecs) =
+ do lins' <- substArgRec (length found) rrec lins
+ return $ Active (Abs nt find f, found ++ [c]) lins' (rrecs ++ [rrec])
+
+-- | Active Items with nothing to find are converted to Passive Items
+convert :: (Ord n, Ord c, Ord l) => NChart c n l -> Item c n l -> [Item c n l]
+convert _ (Active (Abs cat [] fun, _) lins _) = [Passive cat (makeRangeRec lins)]
+convert _ _ = []
+
+
+----------------------------------------------------------------------
+-- * type definitions
+
+type NChart c n l = ParseChart (Item c n l) (NKey c)
+
+data Item c n l = Active (DottedRule c n) (LinRec c l Range) [RangeRec l]
+ | Passive c (RangeRec l)
+ deriving (Eq, Ord, Show)
+
+type DottedRule c n = (Abstract c n, [c])
+
+data NKey c = Act c
+ | Pass c
+ | Final
+ deriving (Eq, Ord, Show)
+
+keyof :: Item c n l -> NKey c
+keyof (Active (Abs _ (next:_) _, _) _ _) = Act next
+keyof (Passive cat _) = Pass cat
+keyof _ = Final
+
+-- for tracing purposes
+prtSizes chart = "final=" ++ show (length (chartLookup chart Final)) ++
+ ", passive=" ++ show (sum [length (chartLookup chart k) |
+ k@(Pass _) <- chartKeys chart ]) ++
+ ", active=" ++ show (sum [length (chartLookup chart k) |
+ k@(Act _) <- chartKeys chart ])
+
+prtChart chart = concat [ "\n*** KEY: " ++ prt k ++
+ prtBefore "\n " (chartLookup chart k) |
+ k <- chartKeys chart ]
+
+instance (Print c, Print n, Print l) => Print (Item c n l) where
+ prt (Active (abs, cs) lrec rrecs) = "? " ++ prt abs ++ " . " ++ prtSep " " cs ++ ";\n\t" ++
+ "{" ++ prtSep " " lrec ++ "}" ++
+ ( if null rrecs then ";" else ";\n\t" ++
+ "{" ++ prtSep "} {" (map (prtSep " ") rrecs) ++ "}" )
+ prt (Passive c rrec) = "- " ++ prt c ++ "; {" ++ prtSep " " rrec ++ "}"
+
+instance Print c => Print (NKey c) where
+ prt (Act c) = "Active " ++ prt c
+ prt (Pass c) = "Passive " ++ prt c
+ prt (Final) = "Final"
+
+
diff --git a/src-3.0/GF/Parsing/MCFG/PInfo.hs b/src-3.0/GF/Parsing/MCFG/PInfo.hs
new file mode 100644
index 000000000..56119dcec
--- /dev/null
+++ b/src-3.0/GF/Parsing/MCFG/PInfo.hs
@@ -0,0 +1,162 @@
+---------------------------------------------------------------------
+-- |
+-- Maintainer : PL
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- > CVS $Date: 2005/05/13 12:40:19 $
+-- > CVS $Author: peb $
+-- > CVS $Revision: 1.5 $
+--
+-- MCFG parsing, parser information
+-----------------------------------------------------------------------------
+
+module GF.Parsing.MCFG.PInfo where
+
+import GF.System.Tracing
+import GF.Infra.Print
+
+import GF.Formalism.Utilities
+import GF.Formalism.GCFG
+import GF.Formalism.MCFG
+import GF.Data.SortedList
+import GF.Data.Assoc
+import GF.Parsing.MCFG.Range
+
+----------------------------------------------------------------------
+-- type declarations
+
+-- | the list of categories = possible starting categories
+type MCFParser c n l t = MCFPInfo c n l t
+ -> [c]
+ -> Input t
+ -> SyntaxChart n (c, RangeRec l)
+
+makeFinalEdge :: c -> l -> (Int, Int) -> (c, RangeRec l)
+makeFinalEdge cat lbl bnds = (cat, [(lbl, makeRange bnds)])
+
+
+------------------------------------------------------------
+-- parser information
+
+data MCFPInfo c n l t
+ = MCFPInfo { grammarTokens :: SList t
+ , nameRules :: Assoc n (SList (MCFRule c n l t))
+ , topdownRules :: Assoc c (SList (MCFRule c n l t))
+ -- ^ used in 'GF.Parsing.MCFG.Active' (Earley):
+ , epsilonRules :: [MCFRule c n l t]
+ -- ^ used in 'GF.Parsing.MCFG.Active' (Kilbury):
+ , leftcornerCats :: Assoc c (SList (MCFRule c n l t))
+ , leftcornerTokens :: Assoc t (SList (MCFRule c n l t))
+ -- ^ used in 'GF.Parsing.MCFG.Active' (Kilbury):
+ , grammarCats :: SList c
+ -- ^ used when calculating starting categories
+ , rulesByToken :: Assoc t (SList (MCFRule c n l t, SList t))
+ , rulesWithoutTokens :: SList (MCFRule c n l t)
+ -- ^ used by 'rulesMatchingInput'
+ , allRules :: MCFGrammar c n l t
+ -- ^ used by any unoptimized algorithm
+
+ --bottomupRules :: Assoc (Symbol c t) (SList (CFRule c n t)),
+ --emptyLeftcornerRules :: Assoc c (SList (CFRule c n t)),
+ --emptyCategories :: Set c,
+ }
+
+
+rangeRestrictPInfo :: (Ord c, Ord n, Ord l, Ord t) =>
+ MCFPInfo c n l t -> Input t -> MCFPInfo c n l Range
+rangeRestrictPInfo (pinfo{-::MCFPInfo c n l t-}) inp =
+ tracePrt "MCFG.PInfo - Restricting the parser information" (prt . grammarTokens)
+ MCFPInfo { grammarTokens = nubsort (map edgeRange (inputEdges inp))
+ , nameRules = rrAssoc (nameRules pinfo)
+ , topdownRules = rrAssoc (topdownRules pinfo)
+ , epsilonRules = rrRules (epsilonRules pinfo)
+ , leftcornerCats = rrAssoc (leftcornerCats pinfo)
+ , leftcornerTokens = lctokens
+ , grammarCats = grammarCats pinfo
+ , rulesByToken = emptyAssoc -- error "MCFG.PInfo.rulesByToken - no range restriction"
+ , rulesWithoutTokens = [] -- error "MCFG.PInfo.rulesByToken - no range restriction"
+ , allRules = allrules -- rrRules (allRules pinfo)
+ }
+
+ where lctokens = accumAssoc id
+ [ (rng, rule) | (tok, rules) <- aAssocs (leftcornerTokens pinfo),
+ inputToken inp ?= tok,
+ rule@(Rule _ (Cnc _ _ (Lin _ (Tok rng:_) : _)))
+ <- concatMap (rangeRestrictRule inp) rules ]
+
+ allrules = rrRules $ rulesMatchingInput pinfo inp
+
+ rrAssoc assoc = filterNull $ fmap rrRules assoc
+ filterNull assoc = assocFilter (not . null) assoc
+ rrRules rules = concatMap (rangeRestrictRule inp) rules
+
+
+buildMCFPInfo :: (Ord c, Ord n, Ord l, Ord t) => MCFGrammar c n l t -> MCFPInfo c n l t
+buildMCFPInfo grammar =
+ traceCalcFirst grammar $
+ tracePrt "MCFG.PInfo - parser info" (prt) $
+ MCFPInfo { grammarTokens = grammartokens
+ , nameRules = namerules
+ , topdownRules = topdownrules
+ , epsilonRules = epsilonrules
+ , leftcornerCats = leftcorncats
+ , leftcornerTokens = leftcorntoks
+ , grammarCats = grammarcats
+ , rulesByToken = rulesbytoken
+ , rulesWithoutTokens = ruleswithouttokens
+ , allRules = allrules
+ }
+
+ where allrules = concatMap expandVariants grammar
+ grammartokens = union (map fst ruletokens)
+ namerules = accumAssoc id
+ [ (name, rule) | rule@(Rule (Abs _ _ name) _) <- allrules ]
+ topdownrules = accumAssoc id
+ [ (cat, rule) | rule@(Rule (Abs cat _ _) _) <- allrules ]
+ epsilonrules = [ rule | rule@(Rule _ (Cnc _ _ (Lin _ [] : _))) <- allrules ]
+ leftcorncats = accumAssoc id
+ [ (cat, rule) |
+ rule@(Rule _ (Cnc _ _ (Lin _ (Cat(cat,_,_):_) : _))) <- allrules ]
+ leftcorntoks = accumAssoc id
+ [ (tok, rule) |
+ rule@(Rule _ (Cnc _ _ (Lin _ (Tok tok:_) : _))) <- allrules ]
+ grammarcats = aElems topdownrules
+ ruletokens = [ (toksoflins lins, rule) |
+ rule@(Rule _ (Cnc _ _ lins)) <- allrules ]
+ toksoflins lins = nubsort [ tok | Lin _ syms <- lins, Tok tok <- syms ]
+ rulesbytoken = accumAssoc id
+ [ (tok, (rule, toks)) | (tok:toks, rule) <- ruletokens ]
+ ruleswithouttokens = nubsort [ rule | ([], rule) <- ruletokens ]
+
+
+-- | return only the rules for which all tokens are in the input string
+rulesMatchingInput :: Ord t => MCFPInfo c n l t -> Input t -> [MCFRule c n l t]
+rulesMatchingInput pinfo inp =
+ [ rule | tok <- toks,
+ (rule, ruletoks) <- rulesByToken pinfo ? tok,
+ ruletoks `subset` toks ]
+ ++ rulesWithoutTokens pinfo
+ where toks = aElems (inputToken inp)
+
+
+----------------------------------------------------------------------
+-- pretty-printing of statistics
+
+instance (Ord c, Ord n, Ord l, Ord t) => Print (MCFPInfo c n l t) where
+ prt pI = "[ tokens=" ++ sl grammarTokens ++
+ "; categories=" ++ sl grammarCats ++
+ "; nameRules=" ++ sla nameRules ++
+ "; tdRules=" ++ sla topdownRules ++
+ "; epsilonRules=" ++ sl epsilonRules ++
+ "; lcCats=" ++ sla leftcornerCats ++
+ "; lcTokens=" ++ sla leftcornerTokens ++
+ "; byToken=" ++ sla rulesByToken ++
+ "; noTokens=" ++ sl rulesWithoutTokens ++
+ "; allRules=" ++ sl allRules ++
+ " ]"
+
+ where sl f = show $ length $ f pI
+ sla f = let (as, bs) = unzip $ aAssocs $ f pI
+ in show (length as) ++ "/" ++ show (length (concat bs))
+
diff --git a/src-3.0/GF/Parsing/MCFG/Range.hs b/src-3.0/GF/Parsing/MCFG/Range.hs
new file mode 100644
index 000000000..91671fa00
--- /dev/null
+++ b/src-3.0/GF/Parsing/MCFG/Range.hs
@@ -0,0 +1,206 @@
+---------------------------------------------------------------------
+-- |
+-- Maintainer : PL
+-- Stability : (stable)
+-- Portability : (portable)
+--
+-- > CVS $Date: 2005/08/08 09:01:25 $
+-- > CVS $Author: peb $
+-- > CVS $Revision: 1.5 $
+--
+-- Definitions of ranges, and operations on ranges
+-----------------------------------------------------------------------------
+
+module GF.Parsing.MCFG.Range
+ ( Range(..), makeRange, concatRange, rangeEdge, edgeRange, minRange, maxRange,
+ LinRec, RangeRec,
+ makeRangeRec, rangeRestRec, rangeRestrictRule,
+ projection, unifyRec, substArgRec
+ ) where
+
+
+-- Haskell
+import Data.List
+import Control.Monad
+
+-- GF modules
+import GF.Formalism.GCFG
+import GF.Formalism.MCFG
+import GF.Formalism.Utilities
+import GF.Infra.Print
+import GF.Data.Assoc ((?))
+import GF.Data.Utilities (updateNthM)
+
+------------------------------------------------------------
+-- ranges as single pairs
+
+data Range = Range (Int, Int)
+ | EmptyRange
+ deriving (Eq, Ord, Show)
+
+makeRange :: (Int, Int) -> Range
+concatRange :: Range -> Range -> [Range]
+rangeEdge :: a -> Range -> Edge a
+edgeRange :: Edge a -> Range
+minRange :: Range -> Int
+maxRange :: Range -> Int
+
+makeRange = Range
+concatRange EmptyRange rng = return rng
+concatRange rng EmptyRange = return rng
+concatRange (Range(i,j)) (Range(j',k)) = [ Range(i,k) | j==j']
+rangeEdge a (Range(i,j)) = Edge i j a
+edgeRange (Edge i j _) = Range (i,j)
+minRange (Range rho) = fst rho
+maxRange (Range rho) = snd rho
+
+instance Print Range where
+ prt (Range (i,j)) = "(" ++ show i ++ "-" ++ show j ++ ")"
+ prt (EmptyRange) = "(?)"
+
+{-- Types --------------------------------------------------------------------
+ Linearization- and Range records implemented as lists
+-----------------------------------------------------------------------------}
+
+type LinRec c l t = [Lin c l t]
+
+type RangeRec l = [(l, Range)]
+
+
+{-- Functions ----------------------------------------------------------------
+ Concatenation : Concatenation of Ranges, Symbols and Linearizations
+ and records of Linearizations
+ Record transformation : Makes a Range record from a fully instantiated
+ Linearization record
+ Record projection : Given a label, returns the corresponding Range
+ Range restriction : Range restriction of Tokens, Symbols,
+ Linearizations and Records given a list of Tokens
+ Record replacment : Substitute a record for another in a list of Range
+ records
+ Argument substitution : Substitution of a Cat c to a Tok Range, where
+ Range is the cover of c
+ Note: The argument is still a Symbol c Range
+ Subsumation : Checks if a Range record subsumes another Range
+ record
+ Record unification : Unification of two Range records
+-----------------------------------------------------------------------------}
+
+
+--- Concatenation ------------------------------------------------------------
+
+
+concSymbols :: [Symbol c Range] -> [[Symbol c Range]]
+concSymbols (Tok rng:Tok rng':toks) = do rng'' <- concatRange rng rng'
+ concSymbols (Tok rng'':toks)
+concSymbols (sym:syms) = do syms' <- concSymbols syms
+ return (sym:syms')
+concSymbols [] = return []
+
+
+concLin :: Lin c l Range -> [Lin c l Range]
+concLin (Lin lbl syms) = do syms' <- concSymbols syms
+ return (Lin lbl syms')
+
+
+concLinRec :: LinRec c l Range -> [LinRec c l Range]
+concLinRec = mapM concLin
+
+
+--- Record transformation ----------------------------------------------------
+
+makeRangeRec :: LinRec c l Range -> RangeRec l
+makeRangeRec lins = map convLin lins
+ where convLin (Lin lbl [Tok rng]) = (lbl, rng)
+ convLin (Lin lbl []) = (lbl, EmptyRange)
+ convLin _ = error "makeRangeRec"
+
+
+--- Record projection --------------------------------------------------------
+
+projection :: Ord l => l -> RangeRec l -> [Range]
+projection l rec = maybe (fail "projection") return $ lookup l rec
+
+
+--- Range restriction --------------------------------------------------------
+
+rangeRestTok :: Ord t => Input t -> t -> [Range]
+rangeRestTok toks tok = do rng <- inputToken toks ? tok
+ return (makeRange rng)
+
+
+rangeRestSym :: Ord t => Input t -> Symbol a t -> [Symbol a Range]
+rangeRestSym toks (Tok tok) = do rng <- rangeRestTok toks tok
+ return (Tok rng)
+rangeRestSym _ (Cat c) = return (Cat c)
+
+
+rangeRestLin :: Ord t => Input t -> Lin c l t -> [Lin c l Range]
+rangeRestLin toks (Lin lbl syms) = do syms' <- mapM (rangeRestSym toks) syms
+ concLin (Lin lbl syms')
+ -- return (Lin lbl syms')
+
+
+rangeRestRec :: Ord t => Input t -> LinRec c l t -> [LinRec c l Range]
+rangeRestRec toks = mapM (rangeRestLin toks)
+
+
+rangeRestrictRule :: Ord t => Input t -> MCFRule c n l t -> [MCFRule c n l Range]
+rangeRestrictRule toks (Rule abs (Cnc l ls lins)) = liftM (Rule abs . Cnc l ls) $
+ rangeRestRec toks lins
+
+--- Argument substitution ----------------------------------------------------
+
+substArgSymbol :: Ord l => Int -> RangeRec l -> Symbol (c, l, Int) Range
+ -> Symbol (c, l, Int) Range
+substArgSymbol i rec tok@(Tok rng) = tok
+substArgSymbol i rec cat@(Cat (c, l, j))
+ | i==j = maybe err Tok $ lookup l rec
+ | otherwise = cat
+ where err = error "substArg: Label not in range-record"
+
+substArgLin :: Ord l => Int -> RangeRec l -> Lin c l Range
+ -> [Lin c l Range]
+substArgLin i rec (Lin lbl syms) =
+ concLin (Lin lbl (map (substArgSymbol i rec) syms))
+
+
+substArgRec :: Ord l => Int -> RangeRec l -> LinRec c l Range
+ -> [LinRec c l Range]
+substArgRec i rec lins = mapM (substArgLin i rec) lins
+
+
+-- Record unification & replacment ---------------------------------------------------------
+
+unifyRec :: Ord l => [RangeRec l] -> Int -> RangeRec l -> [[RangeRec l]]
+unifyRec recs i rec = updateNthM update i recs
+ where update rec' = guard (subsumes rec' rec) >> return rec
+
+-- unifyRec recs i rec = do guard $ subsumes (recs !! i) rec
+-- return $ replaceRec recs i rec
+
+replaceRec :: [RangeRec l] -> Int -> RangeRec l -> [RangeRec l]
+replaceRec recs i rec = before ++ (rec : after)
+ where (before, _ : after) = splitAt i recs
+
+subsumes :: Ord l => RangeRec l -> RangeRec l -> Bool
+subsumes rec rec' = and [r `elem` rec' | r <- rec]
+-- subsumes rec rec' = all (`elem` rec') rec
+
+
+{-
+--- Record unification -------------------------------------------------------
+unifyRangeRecs :: Ord l => [RangeRec l] -> [RangeRec l] -> [[RangeRec l]]
+unifyRangeRecs recs recs' = zipWithM unify recs recs'
+ where unify :: Ord l => RangeRec l -> RangeRec l -> [RangeRec l]
+ unify rec [] = return rec
+ unify [] rec = return rec
+ unify rec1'@(p1@(l1, r1):rec1) rec2'@(p2@(l2, r2):rec2)
+ = case compare l1 l2 of
+ LT -> do rec3 <- unify rec1 rec2'
+ return (p1:rec3)
+ GT -> do rec3 <- unify rec1' rec2
+ return (p2:rec3)
+ EQ -> do guard (r1 == r2)
+ rec3 <- unify rec1 rec2
+ return (p1:rec3)
+-}
diff --git a/src-3.0/GF/Parsing/MCFG/ViaCFG.hs b/src-3.0/GF/Parsing/MCFG/ViaCFG.hs
new file mode 100644
index 000000000..9204ea9f1
--- /dev/null
+++ b/src-3.0/GF/Parsing/MCFG/ViaCFG.hs
@@ -0,0 +1,186 @@
+----------------------------------------------------------------------
+-- |
+-- 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