Get VoiceXML generation working.

This commit is contained in:
bjorn
2008-06-03 20:05:52 +00:00
parent 783f5a0aec
commit 8d4dddfada
4 changed files with 51 additions and 89 deletions

View File

@@ -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.

View File

@@ -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

View File

@@ -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
-} -}

View File

@@ -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 $