1
0
forked from GitHub/gf-core

Some tracing and formatting stuff looking for the the stack overflow problem in the FA generation.

This commit is contained in:
bringert
2005-12-22 18:04:05 +00:00
parent ff1194c1d6
commit cb9769788e
2 changed files with 71 additions and 62 deletions

View File

@@ -27,9 +27,13 @@ import GF.Speech.FiniteState
import GF.Speech.Relation import GF.Speech.Relation
import GF.Speech.TransformCFG import GF.Speech.TransformCFG
import Debug.Trace
cfgToFA :: Options -> CGrammar -> DFA String cfgToFA :: Options -> CGrammar -> DFA String
cfgToFA opts = minimize . compileAutomaton start . makeSimpleRegular cfgToFA opts = minimize . compileAutomaton start . makeSimpleRegular
--cfgToFA opts = trfa "minimal" . minimize . trfa "initial" . compileAutomaton start . makeSimpleRegular
where start = getStartCat opts where start = getStartCat opts
trfa s fa = trace (s ++ ", states: " ++ show (length (states fa)) ++ ", transitions: " ++ show (length (transitions fa))) fa
makeSimpleRegular :: CGrammar -> CFRules makeSimpleRegular :: CGrammar -> CFRules
makeSimpleRegular = makeRegular . removeIdenticalRules . removeEmptyCats . cfgToCFRules makeSimpleRegular = makeRegular . removeIdenticalRules . removeEmptyCats . cfgToCFRules
@@ -41,74 +45,76 @@ makeSimpleRegular = makeRegular . removeIdenticalRules . removeEmptyCats . cfgTo
makeRegular :: CFRules -> CFRules makeRegular :: CFRules -> CFRules
makeRegular g = groupProds $ concatMap trSet (mutRecCats True g) makeRegular g = groupProds $ concatMap trSet (mutRecCats True g)
where trSet cs | allXLinear cs rs = rs where trSet cs | allXLinear cs rs = rs
| otherwise = concatMap handleCat cs | otherwise = concatMap handleCat cs
where rs = catSetRules g cs where rs = catSetRules g cs
handleCat c = [CFRule c' [] (mkName (c++"-empty"))] -- introduce A' -> e handleCat c = [CFRule c' [] (mkName (c++"-empty"))] -- introduce A' -> e
++ concatMap (makeRightLinearRules c) (catRules g c) ++ concatMap (makeRightLinearRules c) (catRules g c)
where c' = newCat c where c' = newCat c
makeRightLinearRules b' (CFRule c ss n) = makeRightLinearRules b' (CFRule c ss n) =
case ys of case ys of
[] -> [CFRule b' (xs ++ [Cat (newCat c)]) n] -- no non-terminals left [] -> [CFRule b' (xs ++ [Cat (newCat c)]) n] -- no non-terminals left
(Cat b:zs) -> CFRule b' (xs ++ [Cat b]) n (Cat b:zs) -> CFRule b' (xs ++ [Cat b]) n
: makeRightLinearRules (newCat b) (CFRule c zs n) : makeRightLinearRules (newCat b) (CFRule c zs n)
where (xs,ys) = break (`catElem` cs) ss where (xs,ys) = break (`catElem` cs) ss
newCat c = c ++ "$" newCat c = c ++ "$"
-- | Get the sets of mutually recursive non-terminals for a grammar. -- | Get the sets of mutually recursive non-terminals for a grammar.
mutRecCats :: Bool -- ^ If true, all categories will be in some set. mutRecCats :: Bool -- ^ If true, all categories will be in some set.
-- If false, only recursive categories will be included. -- If false, only recursive categories will be included.
-> CFRules -> [[Cat_]] -> CFRules -> [[Cat_]]
mutRecCats incAll g = equivalenceClasses $ refl $ symmetricSubrelation $ transitiveClosure r mutRecCats incAll g = equivalenceClasses $ refl $ symmetricSubrelation $ transitiveClosure r
where r = mkRel [(c,c') | (_,rs) <- g, CFRule c ss _ <- rs, Cat c' <- ss] where r = mkRel [(c,c') | (_,rs) <- g, CFRule c ss _ <- rs, Cat c' <- ss]
allCats = map fst g allCats = map fst g
refl = if incAll then reflexiveClosure_ allCats else reflexiveSubrelation refl = if incAll then reflexiveClosure_ allCats else reflexiveSubrelation
-- Convert a strongly regular grammar to a finite automaton. -- Convert a strongly regular grammar to a finite automaton.
compileAutomaton :: Cat_ -- ^ Start category compileAutomaton :: Cat_ -- ^ Start category
-> CFRules -> CFRules
-> NFA Token -> NFA Token
compileAutomaton start g = make_fa s [Cat start] f fa'' compileAutomaton start g = make_fa s [Cat start] f fa''
where fa = newFA () where
s = startState fa fa = newFA ()
(fa',f) = newState () fa s = startState fa
fa'' = addFinalState f fa' (fa',f) = newState () fa
ns = mutRecCats False g fa'' = addFinalState f fa'
-- | The make_fa algorithm from \"Regular approximation of CFLs: a grammatical view\", ns = mutRecCats False g
-- Mark-Jan Nederhof. International Workshop on Parsing Technologies, 1997. -- | The make_fa algorithm from \"Regular approximation of CFLs: a grammatical view\",
make_fa :: State -> [Symbol Cat_ Token] -> State -- Mark-Jan Nederhof. International Workshop on Parsing Technologies, 1997.
-> NFA Token -> NFA Token make_fa :: State -> [Symbol Cat_ Token] -> State
make_fa q0 alpha q1 fa = -> NFA Token -> NFA Token
case alpha of make_fa q0 alpha q1 fa =
[] -> newTransition q0 q1 Nothing fa case alpha of
[Tok t] -> newTransition q0 q1 (Just t) fa [] -> newTransition q0 q1 Nothing fa
[Cat a] -> case findSet a ns of [Tok t] -> newTransition q0 q1 (Just t) fa
-- a is recursive [Cat a] -> case findSet a ns of
Just ni -> let (fa',ss) = addStatesForCats ni fa -- a is recursive
getState x = lookup' x ss Just ni -> let (fa',ss) = addStatesForCats ni fa
niRules = catSetRules g ni getState x = lookup' x ss
(nrs,rs) = partition (ruleIsNonRecursive ni) niRules niRules = catSetRules g ni
in if all (isRightLinear ni) niRules then (nrs,rs) = partition (ruleIsNonRecursive ni) niRules
-- the set Ni is right-recursive or cyclic in if all (isRightLinear ni) niRules
let fa'' = foldFuns [make_fa (getState c) xs q1 | CFRule c xs _ <- nrs] fa' then
fa''' = foldFuns [make_fa (getState c) xs (getState d) | CFRule c ss _ <- rs, -- the set Ni is right-recursive or cyclic
let (xs,Cat d) = (init ss,last ss)] fa'' let fa'' = foldFuns [make_fa (getState c) xs q1 | CFRule c xs _ <- nrs] fa'
in newTransition q0 (getState a) Nothing fa''' fa''' = foldFuns [make_fa (getState c) xs (getState d) | CFRule c ss _ <- rs,
else let (xs,Cat d) = (init ss,last ss)] fa''
-- the set Ni is left-recursive in newTransition q0 (getState a) Nothing fa'''
let fa'' = foldFuns [make_fa q0 xs (getState c) | CFRule c xs _ <- nrs] fa' else
fa''' = foldFuns [make_fa (getState d) xs (getState c) | CFRule c (Cat d:xs) _ <- rs] fa'' -- the set Ni is left-recursive
in newTransition (getState a) q1 Nothing fa''' let fa'' = foldFuns [make_fa q0 xs (getState c) | CFRule c xs _ <- nrs] fa'
-- a is not recursive fa''' = foldFuns [make_fa (getState d) xs (getState c) | CFRule c (Cat d:xs) _ <- rs] fa''
Nothing -> let rs = catRules g a in newTransition (getState a) q1 Nothing fa'''
in foldl (\fa -> \ (CFRule _ b _) -> make_fa q0 b q1 fa) fa rs -- a is not recursive
(x:beta) -> let (fa',q) = newState () fa Nothing -> let rs = catRules g a
in make_fa q beta q1 $ make_fa q0 [x] q fa' in foldl (\fa -> \ (CFRule _ b _) -> make_fa q0 b q1 fa) fa rs
addStatesForCats [] fa = (fa,[]) (x:beta) -> let (fa',q) = newState () fa
addStatesForCats (c:cs) fa = let (fa',s) = newState () fa in make_fa q beta q1 $ make_fa q0 [x] q fa'
(fa'',ss) = addStatesForCats cs fa' addStatesForCats [] fa = (fa,[])
in (fa'',(c,s):ss) addStatesForCats (c:cs) fa = let (fa',s) = newState () fa
ruleIsNonRecursive cs = noCatsInSet cs . ruleRhs (fa'',ss) = addStatesForCats cs fa'
in (fa'',(c,s):ss)
ruleIsNonRecursive cs = noCatsInSet cs . ruleRhs
noCatsInSet :: Eq c => [c] -> [Symbol c t] -> Bool noCatsInSet :: Eq c => [c] -> [Symbol c t] -> Bool
@@ -121,12 +127,12 @@ allXLinear cs rs = all (isRightLinear cs) rs || all (isLeftLinear cs) rs
-- | Checks if a context-free rule is right-linear. -- | Checks if a context-free rule is right-linear.
isRightLinear :: Eq c => [c] -- ^ The categories to consider isRightLinear :: Eq c => [c] -- ^ The categories to consider
-> CFRule c n t -- ^ The rule to check for right-linearity -> CFRule c n t -- ^ The rule to check for right-linearity
-> Bool -> Bool
isRightLinear cs = noCatsInSet cs . safeInit . ruleRhs isRightLinear cs = noCatsInSet cs . safeInit . ruleRhs
-- | Checks if a context-free rule is left-linear. -- | Checks if a context-free rule is left-linear.
isLeftLinear :: Eq c => [c] -- ^ The categories to consider isLeftLinear :: Eq c => [c] -- ^ The categories to consider
-> CFRule c n t -- ^ The rule to check for right-linearity -> CFRule c n t -- ^ The rule to check for right-linearity
-> Bool -> Bool
isLeftLinear cs = noCatsInSet cs . drop 1 . ruleRhs isLeftLinear cs = noCatsInSet cs . drop 1 . ruleRhs

View File

@@ -34,10 +34,13 @@ import Data.Char (toUpper,toLower)
import Data.List import Data.List
import Data.Maybe (fromMaybe) import Data.Maybe (fromMaybe)
faGraphvizPrinter :: Ident -- ^ Grammar name faGraphvizPrinter :: Ident -- ^ Grammar name
-> Options -> CGrammar -> String -> Options -> CGrammar -> String
faGraphvizPrinter name opts cfg = faGraphvizPrinter name opts cfg =
prFAGraphviz $ mapStates (const "") $ cfgToFA opts cfg prFAGraphviz $ mapStates (const "") fa
where fa = cfgToFA opts cfg
-- | Convert the grammar to a regular grammar and print it in BNF -- | Convert the grammar to a regular grammar and print it in BNF