generate unique new category names when removing left recursion from cfgs.

This commit is contained in:
bringert
2006-04-13 14:29:27 +00:00
parent 3d7c4e80d7
commit 26b61d82ee

View File

@@ -31,9 +31,9 @@ import GF.Formalism.Utilities (Symbol(..), mapSymbol, filterCats, symbol,
import GF.Infra.Ident import GF.Infra.Ident
import GF.Infra.Option import GF.Infra.Option
import GF.Infra.Print import GF.Infra.Print
import GF.Speech.FiniteState
import Control.Monad import Control.Monad
import Control.Monad.State (State, get, put, evalState)
import Data.Map (Map) import Data.Map (Map)
import qualified Data.Map as Map import qualified Data.Map as Map
import Data.List import Data.List
@@ -88,7 +88,7 @@ removeIdenticalRules g = [(c,sortNubBy cmpRules rs) | (c,rs) <- g]
mconcat [c1 `compare` c2, ss1 `compare` ss2] mconcat [c1 `compare` c2, ss1 `compare` ss2]
removeLeftRecursion :: CFRules -> CFRules removeLeftRecursion :: CFRules -> CFRules
removeLeftRecursion rs = concatMap removeDirectLeftRecursion $ map handleProds rs removeLeftRecursion rs = removeDirectLeftRecursions $ map handleProds rs
where where
handleProds (c, r) = (c, concatMap handleProd r) handleProds (c, r) = (c, concatMap handleProd r)
handleProd (CFRule ai (Cat aj:alpha) n) | aj < ai = handleProd (CFRule ai (Cat aj:alpha) n) | aj < ai =
@@ -100,17 +100,25 @@ removeLeftRecursion rs = concatMap removeDirectLeftRecursion $ map handleProds r
[CFRule ai (beta ++ alpha) n | CFRule _ beta _ <- lookup' aj rs] [CFRule ai (beta ++ alpha) n | CFRule _ beta _ <- lookup' aj rs]
handleProd r = [r] handleProd r = [r]
removeDirectLeftRecursion :: (Cat_,[CFRule_]) -- ^ All productions for a category removeDirectLeftRecursions :: [(Cat_,[CFRule_])] -- ^ All productions for a category
-> CFRules -> CFRules
removeDirectLeftRecursion (a,rs) | null dr = [(a,rs)] removeDirectLeftRecursions = concat . flip evalState 0 . mapM removeDirectLeftRecursion
| otherwise = [(a, as), (a', a's)]
removeDirectLeftRecursion :: (Cat_,[CFRule_]) -- ^ All productions for a category
-> State Int CFRules
removeDirectLeftRecursion (a,rs)
| null dr = return [(a,rs)]
| otherwise =
do
a' <- fresh a
let as = maybeEndWithA' nr
is = [CFRule a' (tail r) n | CFRule _ r n <- dr]
a's = maybeEndWithA' is
maybeEndWithA' xs = xs ++ [CFRule c (r++[Cat a']) n | CFRule c r n <- xs]
return [(a, as), (a', a's)]
where where
a' = a ++ "'" -- FIXME: this might not be unique
(dr,nr) = partition isDirectLeftRecursive rs (dr,nr) = partition isDirectLeftRecursive rs
as = maybeEndWithA' nr fresh x = do { n <- get; put (n+1); return $ x ++ "'" ++ show n }
is = [CFRule a' (tail r) n | CFRule _ r n <- dr]
a's = maybeEndWithA' is
maybeEndWithA' xs = xs ++ [CFRule c (r++[Cat a']) n | CFRule c r n <- xs]
isDirectLeftRecursive :: CFRule_ -> Bool isDirectLeftRecursive :: CFRule_ -> Bool
isDirectLeftRecursive (CFRule c (Cat c':_) _) = c == c' isDirectLeftRecursive (CFRule c (Cat c':_) _) = c == c'