forked from GitHub/gf-core
Get VoiceXML generation working.
This commit is contained in:
@@ -10,6 +10,7 @@ import GF.Infra.Option
|
|||||||
import GF.Speech.CFG
|
import GF.Speech.CFG
|
||||||
import GF.Speech.PGFToCFG
|
import GF.Speech.PGFToCFG
|
||||||
import GF.Speech.SRGS
|
import GF.Speech.SRGS
|
||||||
|
import GF.Speech.VoiceXML
|
||||||
import GF.Text.UTF8
|
import GF.Text.UTF8
|
||||||
|
|
||||||
-- top-level access to code generation
|
-- top-level access to code generation
|
||||||
@@ -26,6 +27,8 @@ prPGF fmt gr name = case fmt of
|
|||||||
FmtHaskell_GADT -> grammar2haskellGADT gr name
|
FmtHaskell_GADT -> grammar2haskellGADT gr name
|
||||||
FmtBNF -> prCFG $ pgfToCFG gr (outputConcr gr)
|
FmtBNF -> prCFG $ pgfToCFG gr (outputConcr gr)
|
||||||
FmtSRGS_XML -> srgsXmlPrinter Nothing gr (outputConcr gr)
|
FmtSRGS_XML -> srgsXmlPrinter Nothing gr (outputConcr gr)
|
||||||
|
FmtVoiceXML -> grammar2vxml gr (outputConcr gr)
|
||||||
|
|
||||||
|
|
||||||
-- | Get the name of the concrete syntax to generate output from.
|
-- | Get the name of the concrete syntax to generate output from.
|
||||||
-- FIXME: there should be an option to change this.
|
-- FIXME: there should be an option to change this.
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ module GF.Speech.SRG (SRG(..), SRGRule(..), SRGAlt(..), SRGItem
|
|||||||
, makeSRG
|
, makeSRG
|
||||||
, makeSimpleSRG
|
, makeSimpleSRG
|
||||||
, makeNonRecursiveSRG
|
, makeNonRecursiveSRG
|
||||||
|
, getSpeechLanguage
|
||||||
, lookupFM_, prtS
|
, lookupFM_, prtS
|
||||||
) where
|
) where
|
||||||
|
|
||||||
|
|||||||
@@ -1,42 +1,22 @@
|
|||||||
----------------------------------------------------------------------
|
----------------------------------------------------------------------
|
||||||
-- |
|
-- |
|
||||||
-- Module : GrammarToVoiceXML
|
-- Module : GF.Speech.VoiceXML
|
||||||
-- Maintainer : Bjorn Bringert
|
|
||||||
-- Stability : (stable)
|
|
||||||
-- Portability : (portable)
|
|
||||||
--
|
--
|
||||||
-- Create VoiceXML dialogue system from a GF grammar.
|
-- Creates VoiceXML dialogue systems from PGF grammars.
|
||||||
-----------------------------------------------------------------------------
|
-----------------------------------------------------------------------------
|
||||||
|
module GF.Speech.VoiceXML (grammar2vxml) where
|
||||||
|
|
||||||
module GF.Speech.GrammarToVoiceXML (grammar2vxml) where
|
|
||||||
|
|
||||||
import GF.Canon.CanonToGFCC (canon2gfcc)
|
|
||||||
import qualified GF.GFCC.CId as C
|
|
||||||
import GF.GFCC.DataGFCC (GFCC(..), Abstr(..))
|
|
||||||
import GF.GFCC.Macros
|
|
||||||
import qualified GF.Canon.GFC as GFC
|
|
||||||
import GF.Canon.AbsGFC (Term)
|
|
||||||
import GF.Canon.PrintGFC (printTree)
|
|
||||||
import GF.Canon.CMacros (noMark, strsFromTerm)
|
|
||||||
import GF.Canon.Unlex (formatAsText)
|
|
||||||
import GF.Data.Utilities
|
|
||||||
import GF.CF.CFIdent (cfCat2Ident)
|
|
||||||
import GF.Compile.ShellState (StateGrammar,stateGrammarST,cncId,grammar,
|
|
||||||
startCatStateOpts,stateOptions)
|
|
||||||
import GF.Data.Str (sstrV)
|
|
||||||
import GF.Grammar.Macros hiding (assign,strsFromTerm)
|
|
||||||
import GF.Grammar.Grammar (Fun)
|
|
||||||
import GF.Grammar.Values (Tree)
|
|
||||||
import GF.Infra.Option (Options, addOptions, getOptVal, speechLanguage)
|
|
||||||
import GF.UseGrammar.GetTree (string2treeErr)
|
|
||||||
import GF.UseGrammar.Linear (linTree2strings)
|
|
||||||
|
|
||||||
import GF.Infra.Ident
|
|
||||||
import GF.Infra.Option (noOptions)
|
|
||||||
import GF.Infra.Modules
|
|
||||||
import GF.Data.Operations
|
import GF.Data.Operations
|
||||||
|
import GF.Data.Str (sstrV)
|
||||||
|
import GF.Data.Utilities
|
||||||
import GF.Data.XML
|
import GF.Data.XML
|
||||||
|
import GF.Infra.Ident
|
||||||
|
import GF.Infra.Modules
|
||||||
|
import GF.Speech.SRG (getSpeechLanguage)
|
||||||
|
import PGF.CId
|
||||||
|
import PGF.Data
|
||||||
|
import PGF.Macros
|
||||||
|
import PGF.Linearize (realize)
|
||||||
|
|
||||||
import Control.Monad (liftM)
|
import Control.Monad (liftM)
|
||||||
import Data.List (isPrefixOf, find, intersperse)
|
import Data.List (isPrefixOf, find, intersperse)
|
||||||
@@ -46,58 +26,35 @@ import Data.Maybe (fromMaybe)
|
|||||||
import Debug.Trace
|
import Debug.Trace
|
||||||
|
|
||||||
-- | the main function
|
-- | the main function
|
||||||
grammar2vxml :: Options -> StateGrammar -> String
|
grammar2vxml :: PGF -> CId -> String
|
||||||
grammar2vxml opt s = showsXMLDoc (skel2vxml name language startcat gr' qs) ""
|
grammar2vxml pgf cnc = showsXMLDoc (skel2vxml name language start skel qs) ""
|
||||||
where (_, gr') = vSkeleton (stateGrammarST s)
|
where skel = pgfSkeleton pgf
|
||||||
name = prIdent (cncId s)
|
name = prCId cnc
|
||||||
qs = catQuestions s (map fst gr')
|
qs = catQuestions pgf cnc (map fst skel)
|
||||||
opts = addOptions opt (stateOptions s)
|
language = getSpeechLanguage pgf cnc
|
||||||
language = fmap (replace '_' '-') $ getOptVal opts speechLanguage
|
start = mkCId (lookStartCat pgf)
|
||||||
startcat = C.CId $ prIdent $ cfCat2Ident $ startCatStateOpts opts s
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- * VSkeleton: a simple description of the abstract syntax.
|
-- * VSkeleton: a simple description of the abstract syntax.
|
||||||
--
|
--
|
||||||
|
|
||||||
type VSkeleton = [(VIdent, [(VIdent, [VIdent])])]
|
type Skeleton = [(CId, [(CId, [CId])])]
|
||||||
type VIdent = C.CId
|
|
||||||
|
|
||||||
prid :: VIdent -> String
|
pgfSkeleton :: PGF -> Skeleton
|
||||||
prid (C.CId x) = x
|
pgfSkeleton pgf = [(c,[(f,fst (catSkeleton (lookType pgf f))) | f <- fs])
|
||||||
|
| (c,fs) <- Map.toList (catfuns (abstract pgf))]
|
||||||
vSkeleton :: GFC.CanonGrammar -> (VIdent,VSkeleton)
|
|
||||||
vSkeleton = gfccSkeleton . canon2gfcc noOptions
|
|
||||||
|
|
||||||
gfccSkeleton :: GFCC -> (VIdent,VSkeleton)
|
|
||||||
gfccSkeleton gfcc = (absname gfcc, ts)
|
|
||||||
where a = abstract gfcc
|
|
||||||
ts = [(c,[(f,ft f) | f <- fs]) | (c,fs) <- Map.toList (catfuns a)]
|
|
||||||
ft f = case lookMap (error $ prid f) f (funs a) of
|
|
||||||
(ty,_) -> fst $ GF.GFCC.Macros.catSkeleton ty
|
|
||||||
|
|
||||||
--
|
--
|
||||||
-- * Questions to ask
|
-- * Questions to ask
|
||||||
--
|
--
|
||||||
|
|
||||||
type CatQuestions = [(VIdent,String)]
|
type CatQuestions = [(CId,String)]
|
||||||
|
|
||||||
catQuestions :: StateGrammar -> [VIdent] -> CatQuestions
|
catQuestions :: PGF -> CId -> [CId] -> CatQuestions
|
||||||
catQuestions gr cats = [(c,catQuestion gr c) | c <- cats]
|
catQuestions pgf cnc cats = [(c,catQuestion pgf cnc c) | c <- cats]
|
||||||
|
|
||||||
catQuestion :: StateGrammar -> VIdent -> String
|
catQuestion :: PGF -> CId -> CId -> String
|
||||||
catQuestion gr cat = err errHandler id (getPrintname gr cat >>= term2string)
|
catQuestion pgf cnc cat = realize (lookPrintName pgf cnc cat)
|
||||||
where -- FIXME: use some better warning facility
|
|
||||||
errHandler e = trace ("GrammarToVoiceXML: " ++ e) ("quest_"++prid cat)
|
|
||||||
term2string = liftM sstrV . strsFromTerm
|
|
||||||
|
|
||||||
getPrintname :: StateGrammar -> VIdent -> Err Term
|
|
||||||
getPrintname gr cat =
|
|
||||||
do m <- lookupModMod (grammar gr) (cncId gr)
|
|
||||||
i <- lookupInfo m (IC (prid cat))
|
|
||||||
case i of
|
|
||||||
GFC.CncCat _ _ p -> return p
|
|
||||||
_ -> fail $ "getPrintname " ++ prid cat
|
|
||||||
++ ": Expected CncCat, got " ++ show i
|
|
||||||
|
|
||||||
|
|
||||||
{-
|
{-
|
||||||
@@ -113,15 +70,15 @@ lin gr fun = do
|
|||||||
unt = formatAsText
|
unt = formatAsText
|
||||||
-}
|
-}
|
||||||
|
|
||||||
getCatQuestion :: VIdent -> CatQuestions -> String
|
getCatQuestion :: CId -> CatQuestions -> String
|
||||||
getCatQuestion c qs =
|
getCatQuestion c qs =
|
||||||
fromMaybe (error "No question for category " ++ prid c) (lookup c qs)
|
fromMaybe (error "No question for category " ++ prCId c) (lookup c qs)
|
||||||
|
|
||||||
--
|
--
|
||||||
-- * Generate VoiceXML
|
-- * Generate VoiceXML
|
||||||
--
|
--
|
||||||
|
|
||||||
skel2vxml :: String -> Maybe String -> VIdent -> VSkeleton -> CatQuestions -> XML
|
skel2vxml :: String -> Maybe String -> CId -> Skeleton -> CatQuestions -> XML
|
||||||
skel2vxml name language start skel qs =
|
skel2vxml name language start skel qs =
|
||||||
vxml language ([startForm] ++ concatMap (uncurry (catForms gr qs)) skel)
|
vxml language ([startForm] ++ concatMap (uncurry (catForms gr qs)) skel)
|
||||||
where
|
where
|
||||||
@@ -133,12 +90,12 @@ grammarURI :: String -> String
|
|||||||
grammarURI name = name ++ ".grxml"
|
grammarURI name = name ++ ".grxml"
|
||||||
|
|
||||||
|
|
||||||
catForms :: String -> CatQuestions -> VIdent -> [(VIdent, [VIdent])] -> [XML]
|
catForms :: String -> CatQuestions -> CId -> [(CId, [CId])] -> [XML]
|
||||||
catForms gr qs cat fs =
|
catForms gr qs cat fs =
|
||||||
comments [prid cat ++ " category."]
|
comments [prCId cat ++ " category."]
|
||||||
++ [cat2form gr qs cat fs]
|
++ [cat2form gr qs cat fs]
|
||||||
|
|
||||||
cat2form :: String -> CatQuestions -> VIdent -> [(VIdent, [VIdent])] -> XML
|
cat2form :: String -> CatQuestions -> CId -> [(CId, [CId])] -> XML
|
||||||
cat2form gr qs cat fs =
|
cat2form gr qs cat fs =
|
||||||
form (catFormId cat) $
|
form (catFormId cat) $
|
||||||
[var "old" Nothing,
|
[var "old" Nothing,
|
||||||
@@ -151,22 +108,22 @@ cat2form gr qs cat fs =
|
|||||||
++ concatMap (uncurry (fun2sub gr cat)) fs
|
++ concatMap (uncurry (fun2sub gr cat)) fs
|
||||||
++ [block [return_ ["term"]{-]-}]]
|
++ [block [return_ ["term"]{-]-}]]
|
||||||
|
|
||||||
fun2sub :: String -> VIdent -> VIdent -> [VIdent] -> [XML]
|
fun2sub :: String -> CId -> CId -> [CId] -> [XML]
|
||||||
fun2sub gr cat fun args =
|
fun2sub gr cat fun args =
|
||||||
comments [prid fun ++ " : ("
|
comments [prCId fun ++ " : ("
|
||||||
++ concat (intersperse ", " (map prid args))
|
++ concat (intersperse ", " (map prCId args))
|
||||||
++ ") " ++ prid cat] ++ ss
|
++ ") " ++ prCId cat] ++ ss
|
||||||
where
|
where
|
||||||
ss = zipWith mkSub [0..] args
|
ss = zipWith mkSub [0..] args
|
||||||
mkSub n t = subdialog s [("src","#"++catFormId t),
|
mkSub n t = subdialog s [("src","#"++catFormId t),
|
||||||
("cond","term.name == "++string (prid fun))]
|
("cond","term.name == "++string (prCId fun))]
|
||||||
[param "old" v,
|
[param "old" v,
|
||||||
filled [] [assign v (s++".term")]]
|
filled [] [assign v (s++".term")]]
|
||||||
where s = prid fun ++ "_" ++ show n
|
where s = prCId fun ++ "_" ++ show n
|
||||||
v = "term.args["++show n++"]"
|
v = "term.args["++show n++"]"
|
||||||
|
|
||||||
catFormId :: VIdent -> String
|
catFormId :: CId -> String
|
||||||
catFormId c = prid c ++ "_cat"
|
catFormId c = prCId c ++ "_cat"
|
||||||
|
|
||||||
|
|
||||||
--
|
--
|
||||||
@@ -267,19 +224,19 @@ string s = "'" ++ concatMap esc s ++ "'"
|
|||||||
-- * List stuff
|
-- * List stuff
|
||||||
--
|
--
|
||||||
|
|
||||||
isListCat :: (VIdent, [(VIdent, [VIdent])]) -> Bool
|
isListCat :: (CId, [(CId, [CId])]) -> Bool
|
||||||
isListCat (cat,rules) = "List" `isPrefixOf` prIdent cat && length rules == 2
|
isListCat (cat,rules) = "List" `isPrefixOf` prIdent cat && length rules == 2
|
||||||
&& ("Base"++c) `elem` fs && ("Cons"++c) `elem` fs
|
&& ("Base"++c) `elem` fs && ("Cons"++c) `elem` fs
|
||||||
where c = drop 4 (prIdent cat)
|
where c = drop 4 (prIdent cat)
|
||||||
fs = map (prIdent . fst) rules
|
fs = map (prIdent . fst) rules
|
||||||
|
|
||||||
isBaseFun :: VIdent -> Bool
|
isBaseFun :: CId -> Bool
|
||||||
isBaseFun f = "Base" `isPrefixOf` prIdent f
|
isBaseFun f = "Base" `isPrefixOf` prIdent f
|
||||||
|
|
||||||
isConsFun :: VIdent -> Bool
|
isConsFun :: CId -> Bool
|
||||||
isConsFun f = "Cons" `isPrefixOf` prIdent f
|
isConsFun f = "Cons" `isPrefixOf` prIdent f
|
||||||
|
|
||||||
baseSize :: (VIdent, [(VIdent, [VIdent])]) -> Int
|
baseSize :: (CId, [(CId, [CId])]) -> Int
|
||||||
baseSize (_,rules) = length bs
|
baseSize (_,rules) = length bs
|
||||||
where Just (_,bs) = find (isBaseFun . fst) rules
|
where Just (_,bs) = find (isBaseFun . fst) rules
|
||||||
-}
|
-}
|
||||||
|
|||||||
@@ -47,6 +47,7 @@ fmtExtension FmtHaskell = "hs"
|
|||||||
fmtExtension FmtHaskell_GADT = "hs"
|
fmtExtension FmtHaskell_GADT = "hs"
|
||||||
fmtExtension FmtBNF = "bnf"
|
fmtExtension FmtBNF = "bnf"
|
||||||
fmtExtension FmtSRGS_XML = "grxml"
|
fmtExtension FmtSRGS_XML = "grxml"
|
||||||
|
fmtExtension FmtVoiceXML = "vxml"
|
||||||
|
|
||||||
writeOutputFile :: FilePath -> String -> IOE ()
|
writeOutputFile :: FilePath -> String -> IOE ()
|
||||||
writeOutputFile outfile output = ioeIO $
|
writeOutputFile outfile output = ioeIO $
|
||||||
|
|||||||
Reference in New Issue
Block a user