forked from GitHub/gf-core
Prepared for generation of finite automata in C.
This commit is contained in:
@@ -5,9 +5,9 @@
|
|||||||
-- Stability : (stable)
|
-- Stability : (stable)
|
||||||
-- Portability : (portable)
|
-- Portability : (portable)
|
||||||
--
|
--
|
||||||
-- > CVS $Date: 2005/10/26 17:13:13 $
|
-- > CVS $Date: 2005/11/10 16:43:44 $
|
||||||
-- > CVS $Author: bringert $
|
-- > CVS $Author: bringert $
|
||||||
-- > CVS $Revision: 1.5 $
|
-- > CVS $Revision: 1.6 $
|
||||||
--
|
--
|
||||||
-- Approximates CFGs with finite state networks.
|
-- Approximates CFGs with finite state networks.
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
@@ -28,7 +28,7 @@ import GF.Speech.Relation
|
|||||||
import GF.Speech.TransformCFG
|
import GF.Speech.TransformCFG
|
||||||
|
|
||||||
cfgToFA :: Ident -- ^ Grammar name
|
cfgToFA :: Ident -- ^ Grammar name
|
||||||
-> Options -> CGrammar -> NFA String
|
-> Options -> CGrammar -> DFA String
|
||||||
cfgToFA name opts = minimize . compileAutomaton start . makeSimpleRegular
|
cfgToFA name opts = minimize . compileAutomaton start . makeSimpleRegular
|
||||||
where start = getStartCat opts
|
where start = getStartCat opts
|
||||||
|
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
-- Stability : (stable)
|
-- Stability : (stable)
|
||||||
-- Portability : (portable)
|
-- Portability : (portable)
|
||||||
--
|
--
|
||||||
-- > CVS $Date: 2005/10/27 09:16:30 $
|
-- > CVS $Date: 2005/11/10 16:43:44 $
|
||||||
-- > CVS $Author: bringert $
|
-- > CVS $Author: bringert $
|
||||||
-- > CVS $Revision: 1.15 $
|
-- > CVS $Revision: 1.16 $
|
||||||
--
|
--
|
||||||
-- A simple finite state network module.
|
-- A simple finite state network module.
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
@@ -19,6 +19,7 @@ module GF.Speech.FiniteState (FA, State, NFA, DFA,
|
|||||||
newState, newTransition,
|
newState, newTransition,
|
||||||
mapStates, mapTransitions,
|
mapStates, mapTransitions,
|
||||||
moveLabelsToNodes, minimize,
|
moveLabelsToNodes, minimize,
|
||||||
|
dfa2nfa,
|
||||||
prFAGraphviz) where
|
prFAGraphviz) where
|
||||||
|
|
||||||
import Data.List
|
import Data.List
|
||||||
@@ -36,7 +37,7 @@ data FA n a b = FA (Graph n a b) n [n]
|
|||||||
|
|
||||||
type NFA a = FA State () (Maybe a)
|
type NFA a = FA State () (Maybe a)
|
||||||
|
|
||||||
type DFA a = FA [State] () a
|
type DFA a = FA State () a
|
||||||
|
|
||||||
|
|
||||||
startState :: FA n a b -> n
|
startState :: FA n a b -> n
|
||||||
@@ -72,8 +73,8 @@ mapStates f = onGraph (nmap f)
|
|||||||
mapTransitions :: (b -> c) -> FA n a b -> FA n a c
|
mapTransitions :: (b -> c) -> FA n a b -> FA n a c
|
||||||
mapTransitions f = onGraph (emap f)
|
mapTransitions f = onGraph (emap f)
|
||||||
|
|
||||||
minimize :: Ord a => NFA a -> NFA a
|
minimize :: Ord a => NFA a -> DFA a
|
||||||
minimize = dfa2nfa . determinize . reverseNFA . dfa2nfa . determinize . reverseNFA
|
minimize = determinize . reverseNFA . dfa2nfa . determinize . reverseNFA
|
||||||
|
|
||||||
onGraph :: (Graph n a b -> Graph n c d) -> FA n a b -> FA n c d
|
onGraph :: (Graph n a b -> Graph n c d) -> FA n a b -> FA n c d
|
||||||
onGraph f (FA g s ss) = FA (f g) s ss
|
onGraph f (FA g s ss) = FA (f g) s ss
|
||||||
@@ -114,11 +115,11 @@ alphabet = nub . catMaybes . map getLabel . edges
|
|||||||
determinize :: Ord a => NFA a -> DFA a
|
determinize :: Ord a => NFA a -> DFA a
|
||||||
determinize (FA g s f) = let (ns,es) = h [start] [] []
|
determinize (FA g s f) = let (ns,es) = h [start] [] []
|
||||||
final = filter (not . null . (f `intersect`)) ns
|
final = filter (not . null . (f `intersect`)) ns
|
||||||
in FA (Graph (freshDFANodes g) [(n,()) | n <- ns] es) start final
|
fa = FA (Graph undefined [(n,()) | n <- ns] es) start final
|
||||||
|
in numberStates fa
|
||||||
where out = outgoing g
|
where out = outgoing g
|
||||||
start = closure out [s]
|
start = closure out [s]
|
||||||
isDFAFinal n = not (null (f `intersect` n))
|
isDFAFinal n = not (null (f `intersect` n))
|
||||||
freshDFANodes (Graph ns _ _) = map (:[]) ns
|
|
||||||
-- Get the new DFA states and edges produced by a set of DFA states.
|
-- Get the new DFA states and edges produced by a set of DFA states.
|
||||||
new ns = unzip [ (s, (n,s,c)) | n <- ns, (c,s) <- reachable out n]
|
new ns = unzip [ (s, (n,s,c)) | n <- ns, (c,s) <- reachable out n]
|
||||||
h currentStates oldStates oldEdges
|
h currentStates oldStates oldEdges
|
||||||
@@ -128,6 +129,14 @@ determinize (FA g s f) = let (ns,es) = h [start] [] []
|
|||||||
allOldStates = currentStates ++ oldStates
|
allOldStates = currentStates ++ oldStates
|
||||||
newStates' = nub newStates \\ allOldStates
|
newStates' = nub newStates \\ allOldStates
|
||||||
|
|
||||||
|
numberStates :: (Ord x,Enum y) => FA x a b -> FA y a b
|
||||||
|
numberStates (FA g s fs) = FA (renameNodes newName rest g) s' fs'
|
||||||
|
where (ns,rest) = splitAt (length (nodes g)) $ [toEnum 0 .. ]
|
||||||
|
newNodes = zip (map fst (nodes g)) ns
|
||||||
|
newName n = lookup' n newNodes
|
||||||
|
s' = newName s
|
||||||
|
fs' = map newName fs
|
||||||
|
|
||||||
-- | Get all the nodes reachable from a set of nodes by only empty edges.
|
-- | Get all the nodes reachable from a set of nodes by only empty edges.
|
||||||
closure :: Eq n => Outgoing n a (Maybe b) -> [n] -> [n]
|
closure :: Eq n => Outgoing n a (Maybe b) -> [n] -> [n]
|
||||||
closure out = fix closure_
|
closure out = fix closure_
|
||||||
@@ -146,15 +155,7 @@ reverseNFA (FA g s fs) = FA g''' s' [s]
|
|||||||
g''' = newEdges [(s',f,Nothing) | f <- fs] g''
|
g''' = newEdges [(s',f,Nothing) | f <- fs] g''
|
||||||
|
|
||||||
dfa2nfa :: DFA a -> NFA a
|
dfa2nfa :: DFA a -> NFA a
|
||||||
dfa2nfa (FA (Graph _ ns es) s fs) = FA (Graph c ns' es') s' fs'
|
dfa2nfa = mapTransitions Just
|
||||||
where newNodes = zip (map fst ns) [0..]
|
|
||||||
newNode n = lookup' n newNodes
|
|
||||||
c = [length ns..]
|
|
||||||
ns' = [ (n,()) | (_,n) <- newNodes ]
|
|
||||||
es' = [ (newNode f, newNode t,Just l) | (f,t,l) <- es]
|
|
||||||
s' = newNode s
|
|
||||||
fs' = map newNode fs
|
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- * Visualization
|
-- * Visualization
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
-- Stability : (stable)
|
-- Stability : (stable)
|
||||||
-- Portability : (portable)
|
-- Portability : (portable)
|
||||||
--
|
--
|
||||||
-- > CVS $Date: 2005/10/26 17:13:13 $
|
-- > CVS $Date: 2005/11/10 16:43:44 $
|
||||||
-- > CVS $Author: bringert $
|
-- > CVS $Author: bringert $
|
||||||
-- > CVS $Revision: 1.1 $
|
-- > CVS $Revision: 1.2 $
|
||||||
--
|
--
|
||||||
-- A simple graph module.
|
-- A simple graph module.
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
@@ -16,7 +16,7 @@ module GF.Speech.Graph ( Graph(..), Node, Edge, Incoming, Outgoing
|
|||||||
, nmap, emap, newNode, newEdge, newEdges
|
, nmap, emap, newNode, newEdge, newEdges
|
||||||
, incoming, outgoing, getOutgoing
|
, incoming, outgoing, getOutgoing
|
||||||
, getFrom, getTo, getLabel
|
, getFrom, getTo, getLabel
|
||||||
, reverseGraph
|
, reverseGraph, renameNodes
|
||||||
) where
|
) where
|
||||||
|
|
||||||
import GF.Data.Utilities
|
import GF.Data.Utilities
|
||||||
@@ -41,9 +41,11 @@ nodes (Graph _ ns _) = ns
|
|||||||
edges :: Graph n a b -> [Edge n b]
|
edges :: Graph n a b -> [Edge n b]
|
||||||
edges (Graph _ _ es) = es
|
edges (Graph _ _ es) = es
|
||||||
|
|
||||||
|
-- | Map a function over the node label.s
|
||||||
nmap :: (a -> c) -> Graph n a b -> Graph n c b
|
nmap :: (a -> c) -> Graph n a b -> Graph n c b
|
||||||
nmap f (Graph c ns es) = Graph c [(n,f l) | (n,l) <- ns] es
|
nmap f (Graph c ns es) = Graph c [(n,f l) | (n,l) <- ns] es
|
||||||
|
|
||||||
|
-- | Map a function over the edge labels.
|
||||||
emap :: (b -> c) -> Graph n a b -> Graph n a c
|
emap :: (b -> c) -> Graph n a b -> Graph n a c
|
||||||
emap f (Graph c ns es) = Graph c ns [(x,y,f l) | (x,y,l) <- es]
|
emap f (Graph c ns es) = Graph c ns [(x,y,f l) | (x,y,l) <- es]
|
||||||
|
|
||||||
@@ -86,3 +88,12 @@ getLabel (_,_,l) = l
|
|||||||
reverseGraph :: Graph n a b -> Graph n a b
|
reverseGraph :: Graph n a b -> Graph n a b
|
||||||
reverseGraph (Graph c ns es) = Graph c ns [ (t,f,l) | (f,t,l) <- es ]
|
reverseGraph (Graph c ns es) = Graph c ns [ (t,f,l) | (f,t,l) <- es ]
|
||||||
|
|
||||||
|
|
||||||
|
-- | Re-name the nodes in the graph.
|
||||||
|
renameNodes :: (n -> m) -- ^ renaming function
|
||||||
|
-> [m] -- ^ infinite supply of fresh node names, to
|
||||||
|
-- use when adding nodes in the future.
|
||||||
|
-> Graph n a b -> Graph m a b
|
||||||
|
renameNodes newName c (Graph _ ns es) = Graph c ns' es'
|
||||||
|
where ns' = [ (newName n,x) | (n,x) <- ns ]
|
||||||
|
es' = [ (newName f, newName t, l) | (f,t,l) <- es]
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
-- Stability : (stable)
|
-- Stability : (stable)
|
||||||
-- Portability : (portable)
|
-- Portability : (portable)
|
||||||
--
|
--
|
||||||
-- > CVS $Date: 2005/11/10 14:19:33 $
|
-- > CVS $Date: 2005/11/10 16:43:44 $
|
||||||
-- > CVS $Author: bringert $
|
-- > CVS $Author: bringert $
|
||||||
-- > CVS $Revision: 1.1 $
|
-- > CVS $Revision: 1.2 $
|
||||||
--
|
--
|
||||||
-- This module prints finite automata and regular grammars
|
-- This module prints finite automata and regular grammars
|
||||||
-- for a context-free grammar.
|
-- for a context-free grammar.
|
||||||
@@ -16,7 +16,7 @@
|
|||||||
-- categories in the grammar
|
-- categories in the grammar
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
module GF.Speech.PrFA (faGraphvizPrinter,regularPrinter) where
|
module GF.Speech.PrFA (faGraphvizPrinter,regularPrinter,faCPrinter) where
|
||||||
|
|
||||||
import GF.Data.Utilities
|
import GF.Data.Utilities
|
||||||
import GF.Conversion.Types
|
import GF.Conversion.Types
|
||||||
@@ -37,7 +37,7 @@ 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 "") $ mapTransitions (fromMaybe "") $ cfgToFA name opts cfg)
|
prFAGraphviz $ mapStates (const "") $ cfgToFA name 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
|
||||||
@@ -48,3 +48,10 @@ regularPrinter = prCFRules . makeSimpleRegular
|
|||||||
prCFRules g = unlines [ c ++ " ::= " ++ join " | " (map (showRhs . ruleRhs) rs) | (c,rs) <- g]
|
prCFRules g = unlines [ c ++ " ::= " ++ join " | " (map (showRhs . ruleRhs) rs) | (c,rs) <- g]
|
||||||
join g = concat . intersperse g
|
join g = concat . intersperse g
|
||||||
showRhs = unwords . map (symbol id show)
|
showRhs = unwords . map (symbol id show)
|
||||||
|
|
||||||
|
faCPrinter :: Ident -- ^ Grammar name
|
||||||
|
-> Options -> CGrammar -> String
|
||||||
|
faCPrinter name opts cfg = fa2c $ cfgToFA name opts cfg
|
||||||
|
|
||||||
|
fa2c :: DFA String -> String
|
||||||
|
fa2c fa = undefined
|
||||||
@@ -5,9 +5,9 @@
|
|||||||
-- Stability : (stable)
|
-- Stability : (stable)
|
||||||
-- Portability : (portable)
|
-- Portability : (portable)
|
||||||
--
|
--
|
||||||
-- > CVS $Date: 2005/11/10 14:19:33 $
|
-- > CVS $Date: 2005/11/10 16:43:44 $
|
||||||
-- > CVS $Author: bringert $
|
-- > CVS $Author: bringert $
|
||||||
-- > CVS $Revision: 1.11 $
|
-- > CVS $Revision: 1.12 $
|
||||||
--
|
--
|
||||||
-- This module converts a CFG to an SLF finite-state network
|
-- This module converts a CFG to an SLF finite-state network
|
||||||
-- for use with the ATK recognizer. The SLF format is described
|
-- for use with the ATK recognizer. The SLF format is described
|
||||||
@@ -48,12 +48,12 @@ data SLFEdge = SLFEdge { eId :: Int, eStart :: Int, eEnd :: Int }
|
|||||||
|
|
||||||
slfPrinter :: Ident -- ^ Grammar name
|
slfPrinter :: Ident -- ^ Grammar name
|
||||||
-> Options -> CGrammar -> String
|
-> Options -> CGrammar -> String
|
||||||
slfPrinter name opts cfg = prSLF (automatonToSLF $ moveLabelsToNodes $ cfgToFA name opts cfg) ""
|
slfPrinter name opts cfg = prSLF (automatonToSLF $ moveLabelsToNodes $ dfa2nfa $ cfgToFA name opts cfg) ""
|
||||||
|
|
||||||
slfGraphvizPrinter :: Ident -- ^ Grammar name
|
slfGraphvizPrinter :: Ident -- ^ Grammar name
|
||||||
-> Options -> CGrammar -> String
|
-> Options -> CGrammar -> String
|
||||||
slfGraphvizPrinter name opts cfg =
|
slfGraphvizPrinter name opts cfg =
|
||||||
prFAGraphviz (mapStates (fromMaybe "") $ mapTransitions (const "") $ moveLabelsToNodes $ cfgToFA name opts cfg)
|
prFAGraphviz $ mapStates (fromMaybe "") $ mapTransitions (const "") $ moveLabelsToNodes $ dfa2nfa $ cfgToFA name opts cfg
|
||||||
|
|
||||||
automatonToSLF :: FA State (Maybe String) () -> SLF
|
automatonToSLF :: FA State (Maybe String) () -> SLF
|
||||||
automatonToSLF fa =
|
automatonToSLF fa =
|
||||||
|
|||||||
@@ -5,9 +5,9 @@
|
|||||||
-- Stability : (stable)
|
-- Stability : (stable)
|
||||||
-- Portability : (portable)
|
-- Portability : (portable)
|
||||||
--
|
--
|
||||||
-- > CVS $Date: 2005/11/10 14:19:33 $
|
-- > CVS $Date: 2005/11/10 16:43:45 $
|
||||||
-- > CVS $Author: bringert $
|
-- > CVS $Author: bringert $
|
||||||
-- > CVS $Revision: 1.83 $
|
-- > CVS $Revision: 1.84 $
|
||||||
--
|
--
|
||||||
-- A database for customizable GF shell commands.
|
-- A database for customizable GF shell commands.
|
||||||
--
|
--
|
||||||
@@ -59,7 +59,7 @@ import GF.Speech.PrGSL (gslPrinter)
|
|||||||
import GF.Speech.PrJSGF (jsgfPrinter)
|
import GF.Speech.PrJSGF (jsgfPrinter)
|
||||||
import GF.Speech.PrSRGS (srgsXmlPrinter)
|
import GF.Speech.PrSRGS (srgsXmlPrinter)
|
||||||
import GF.Speech.PrSLF (slfPrinter,slfGraphvizPrinter)
|
import GF.Speech.PrSLF (slfPrinter,slfGraphvizPrinter)
|
||||||
import GF.Speech.PrFA (faGraphvizPrinter,regularPrinter)
|
import GF.Speech.PrFA (faGraphvizPrinter,regularPrinter,faCPrinter)
|
||||||
|
|
||||||
import GF.Data.Zipper
|
import GF.Data.Zipper
|
||||||
|
|
||||||
@@ -261,6 +261,9 @@ customGrammarPrinter =
|
|||||||
,(strCI "fa_graphviz", \s -> let opts = stateOptions s
|
,(strCI "fa_graphviz", \s -> let opts = stateOptions s
|
||||||
name = cncId s
|
name = cncId s
|
||||||
in faGraphvizPrinter name opts $ stateCFG s)
|
in faGraphvizPrinter name opts $ stateCFG s)
|
||||||
|
,(strCI "fa_c", \s -> let opts = stateOptions s
|
||||||
|
name = cncId s
|
||||||
|
in faCPrinter name opts $ stateCFG s)
|
||||||
,(strCI "regular", regularPrinter . stateCFG)
|
,(strCI "regular", regularPrinter . stateCFG)
|
||||||
,(strCI "plbnf", prLBNF True)
|
,(strCI "plbnf", prLBNF True)
|
||||||
,(strCI "lbnf", prLBNF False)
|
,(strCI "lbnf", prLBNF False)
|
||||||
|
|||||||
Reference in New Issue
Block a user