mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-09 04:59:31 -06:00
added syntax to api translation module
This commit is contained in:
2
gf.cabal
2
gf.cabal
@@ -46,6 +46,8 @@ library
|
||||
PGF.Probabilistic
|
||||
PGF.Forest
|
||||
PGF.Optimize
|
||||
PGF.Signature
|
||||
PGF.ToAPI
|
||||
GF.Data.TrieMap
|
||||
GF.Data.Utilities
|
||||
GF.Data.SortedList
|
||||
|
||||
@@ -126,7 +126,10 @@ module PGF(
|
||||
readProbabilitiesFromFile,
|
||||
|
||||
-- * Browsing
|
||||
browse
|
||||
browse,
|
||||
-- * ToAPI
|
||||
exprToAPI,
|
||||
stringToAPI
|
||||
) where
|
||||
|
||||
import PGF.CId
|
||||
@@ -141,6 +144,7 @@ import PGF.Expr (Tree)
|
||||
import PGF.Morphology
|
||||
import PGF.Data
|
||||
import PGF.Binary
|
||||
import PGF.ToAPI
|
||||
import qualified PGF.Forest as Forest
|
||||
import qualified PGF.Parse as Parse
|
||||
|
||||
|
||||
11
src/runtime/haskell/PGF/Signature.hs
Normal file
11
src/runtime/haskell/PGF/Signature.hs
Normal file
File diff suppressed because one or more lines are too long
208
src/runtime/haskell/PGF/ToApi.hs
Normal file
208
src/runtime/haskell/PGF/ToApi.hs
Normal file
@@ -0,0 +1,208 @@
|
||||
module PGF.ToAPI
|
||||
(stringToAPI,exprToAPI)
|
||||
where
|
||||
|
||||
import PGF.Expr
|
||||
import PGF.CId
|
||||
import Data.Maybe
|
||||
import System.IO
|
||||
import Control.Monad
|
||||
import Data.Set as Set (fromList,toList)
|
||||
import Data.List
|
||||
import Data.Map(Map)
|
||||
import qualified Data.Map as Map
|
||||
import PGF.Signature
|
||||
|
||||
|
||||
|
||||
-- intermediate structure for representing the translated expression
|
||||
data APIfunc = BasicFunc String | AppFunc String [APIfunc] | NoAPI
|
||||
deriving (Show,Eq)
|
||||
|
||||
|
||||
|
||||
|
||||
-- translates a GF expression/tree into an equivalent one which uses functions from the GF
|
||||
-- API instead of the syntactic modules
|
||||
exprToAPI :: Expr -> IO String
|
||||
exprToAPI expr =
|
||||
do ffs <- exprToFunc expr
|
||||
return $ printAPIfunc ffs
|
||||
|
||||
|
||||
|
||||
|
||||
-- translates a GF expression/tree written as a string to its correspondent which uses API functions
|
||||
-- the string is parsed into a GF expression/tree first
|
||||
stringToAPI :: String -> IO String
|
||||
stringToAPI expressionToRead =
|
||||
case readExpr expressionToRead of
|
||||
Just ex -> exprToAPI ex
|
||||
_ -> fail "incorrect expression given as input "
|
||||
|
||||
|
||||
|
||||
|
||||
-- function for translating an expression into APIFunc with type inference for
|
||||
-- the type of the expression
|
||||
exprToFunc :: Expr -> IO APIfunc
|
||||
exprToFunc expr =
|
||||
case unApp expr of
|
||||
Just (cid,l) ->
|
||||
case Map.lookup (showCId cid) syntaxFuncs of
|
||||
Just sig -> mkAPI True (fst sig,expr)
|
||||
_ -> case l of
|
||||
[] -> return $ BasicFunc (showCId cid)
|
||||
_ -> do es <- mapM exprToFunc l
|
||||
return $ AppFunc (showCId cid) es
|
||||
_ -> return $ BasicFunc (showExpr [] expr)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
-- main function for translating an expression along with its type into an APIFunc
|
||||
-- the boolean controls the need to optimize the result
|
||||
mkAPI :: Bool -> (String, Expr) -> IO APIfunc
|
||||
mkAPI opt (ty,expr) =
|
||||
if elem ty rephraseable then rephraseSentence ty expr
|
||||
else if opt then if elem ty optimizable then optimize expr else computeAPI (ty,expr)
|
||||
else computeAPI (ty,expr)
|
||||
where
|
||||
rephraseSentence ty expr =
|
||||
case unApp expr of
|
||||
Just (cid,es) -> if isPrefixOf "Use" (showCId cid) then
|
||||
do let newCat = drop 3 (showCId cid)
|
||||
afClause <- mkAPI True (newCat, es !! 2)
|
||||
afPol <- mkAPI True ("Pol",es !! 1)
|
||||
lTense <- mkAPI True ("Temp", head es)
|
||||
case lTense of
|
||||
AppFunc _ [BasicFunc s1, BasicFunc s2] ->
|
||||
let (r1,r2) = getTemporalParam s1 s2 in
|
||||
return $ AppFunc ("mk"++newCat) [r1,r2,afPol,afClause]
|
||||
_ -> fail $ "erroneous tense"
|
||||
else (mkAPI False) (ty,expr)
|
||||
_ -> fail $ "incorrect for for expression "++ showExpr [] expr
|
||||
|
||||
getTemporalParam s1 s2 =
|
||||
let r1 = case s1 of
|
||||
"TPres" -> NoAPI
|
||||
"TPast" -> BasicFunc "pastTense"
|
||||
"TFut" -> BasicFunc "futureTense"
|
||||
"TCond" -> BasicFunc "conditionalTense"
|
||||
r2 = case s2 of
|
||||
"ASimul" -> NoAPI
|
||||
"AAnter" -> BasicFunc "anteriorAnt"
|
||||
in (r1,r2)
|
||||
|
||||
|
||||
|
||||
computeAPI :: (String,Expr) -> IO APIfunc
|
||||
computeAPI (ty,expr) =
|
||||
case (unApp expr) of
|
||||
Just (cid,[]) -> getSimpCat (showCId cid) ty
|
||||
Just (cid,es) ->
|
||||
do p <- specFunction (showCId cid) es
|
||||
if isJust p then return $ fromJust p
|
||||
else case Map.lookup (show cid) syntaxFuncs of
|
||||
Nothing -> exprToFunc expr
|
||||
Just (nameCat,typesExps) ->
|
||||
|
||||
if elem nameCat hiddenCats && length es == 1 then (mkAPI True) (head typesExps,head es)
|
||||
else if elem nameCat hiddenCats then fail $ "incorrect coercion "++nameCat++" - "++show es
|
||||
else do afs <- mapM (mkAPI True) (zip typesExps es)
|
||||
return $ AppFunc ("mk" ++ nameCat) afs
|
||||
_ -> fail "error"
|
||||
where
|
||||
getSimpCat "IdRP" _ = return $ BasicFunc "which_RP"
|
||||
getSimpCat "DefArt" _ = return $ BasicFunc "the_Art"
|
||||
getSimpCat "IndefArt" _ = return $ BasicFunc "a_Art"
|
||||
getSimpCat "NumSg" _ = return $ NoAPI
|
||||
getSimpCat "NumPl" _ = return $ BasicFunc "plNum"
|
||||
getSimpCat "PPos" _ = return $ NoAPI
|
||||
getSimpCat "PNeg" _ = return $ BasicFunc "negativePol"
|
||||
getSimpCat cid ty = if elem ty ["PConj","Voc"] && isInfixOf "No" cid
|
||||
then return NoAPI
|
||||
else return $ BasicFunc cid
|
||||
|
||||
specFunction "PassV2" es = rephraseUnary "passiveVP" "V2" es
|
||||
specFunction "ReflA2" es = rephraseUnary "reflAP" "A2" es
|
||||
specFunction "UseComparA" es = rephraseUnary "comparAP" "A" es
|
||||
specFunction "TFullStop" es = rephraseText "fullStopPunct" es
|
||||
specFunction "TExclMark" es = rephraseText "exclMarkPunct" es
|
||||
specFunction "TQuestMark" es = rephraseText "questMarkPunct" es
|
||||
specFunction _ _ = return Nothing
|
||||
|
||||
rephraseUnary ss ty es =
|
||||
do afs <- mkAPI True (ty,head es)
|
||||
return $ Just (AppFunc ss [afs])
|
||||
|
||||
rephraseText ss es =
|
||||
do afs <- mapM (mkAPI True) (zip ["Phr","Text"] es)
|
||||
if afs !! 1 == BasicFunc "TEmpty" then return $ Just (AppFunc "mkText" [head afs,BasicFunc ss])
|
||||
else return $ Just (AppFunc "mkText" [head afs, BasicFunc ss, last afs])
|
||||
|
||||
|
||||
|
||||
-- optimizations for the translation of some categories
|
||||
optimize expr = optimizeNP expr
|
||||
|
||||
optimizeNP expr =
|
||||
case unApp expr of
|
||||
Just (cid,es) ->
|
||||
if showCId cid == "MassNP" then do afs <- nounAsCN (head es)
|
||||
return $ AppFunc "mkNP" [afs]
|
||||
else if showCId cid == "DetCN" then do quants <- quantAsDet (head es)
|
||||
ns <- nounAsCN (head $ tail es)
|
||||
return $ AppFunc "mkNP" (quants ++ [ns])
|
||||
else mkAPI False ("NP",expr)
|
||||
_ -> fail $ "incorrect expression " ++ (showExpr [] expr)
|
||||
where
|
||||
nounAsCN expr =
|
||||
case unApp expr of
|
||||
Just (cid,es) -> if showCId cid == "UseN" then (mkAPI False) ("N",head es)
|
||||
else (mkAPI False) ("CN",expr)
|
||||
_ -> fail $ "incorrect expression "++ (showExpr [] expr)
|
||||
|
||||
quantAsDet expr =
|
||||
case unApp expr of
|
||||
Just (cid,es) -> if showCId cid == "DetQuant" then mapM (mkAPI False) [("Quant", head es),("Num",head $ tail es)]
|
||||
else do l <- (mkAPI False) ("Det",expr)
|
||||
return [l]
|
||||
_ -> fail $ "incorrect expression "++ (showExpr [] expr)
|
||||
|
||||
|
||||
|
||||
-- categories not present in the API - rephrasing needed
|
||||
hiddenCats :: [String]
|
||||
hiddenCats = ["N2","V2","Comp","SC"]
|
||||
|
||||
|
||||
|
||||
-- categories for which optimization of the translation is provided at the moment
|
||||
optimizable :: [String]
|
||||
optimizable = ["NP"]
|
||||
|
||||
|
||||
|
||||
-- categories for which the compositional translation needs to be rephrased
|
||||
rephraseable :: [String]
|
||||
rephraseable = ["S","QS","RS"]
|
||||
|
||||
|
||||
|
||||
-- converts the intermediate structure APIFunc to plain string
|
||||
printAPIfunc :: APIfunc -> String
|
||||
printAPIfunc (BasicFunc f) = f
|
||||
printAPIfunc NoAPI = ""
|
||||
printAPIfunc (AppFunc f es) = unwords (f : map (\x -> printAPIArgfunc x ) es)
|
||||
where
|
||||
printAPIArgfunc (BasicFunc f) = f
|
||||
printAPIArgfunc NoAPI = ""
|
||||
printAPIArgfunc f = "(" ++ printAPIfunc f ++ ")"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user