mirror of
https://github.com/GrammaticalFramework/gf-core.git
synced 2026-04-09 04:59:31 -06:00
152 lines
4.5 KiB
Haskell
152 lines
4.5 KiB
Haskell
----------------------------------------------------------------------
|
|
-- |
|
|
-- Module : GetGrammar
|
|
-- Maintainer : AR
|
|
-- Stability : (stable)
|
|
-- Portability : (portable)
|
|
--
|
|
-- > CVS $Date: 2005/11/15 17:56:13 $
|
|
-- > CVS $Author: aarne $
|
|
-- > CVS $Revision: 1.16 $
|
|
--
|
|
-- this module builds the internal GF grammar that is sent to the type checker
|
|
-----------------------------------------------------------------------------
|
|
|
|
module GF.Compile.GetGrammar (
|
|
getSourceModule, getSourceGrammar,
|
|
getOldGrammar, getCFGrammar, getEBNFGrammar,
|
|
err2err
|
|
) where
|
|
|
|
import GF.Data.Operations
|
|
import qualified GF.Source.ErrM as E
|
|
|
|
import GF.Infra.UseIO
|
|
import GF.Grammar.Grammar
|
|
import GF.Infra.Modules
|
|
import GF.Grammar.PrGrammar
|
|
import qualified GF.Source.AbsGF as A
|
|
import GF.Source.SourceToGrammar
|
|
---- import Macros
|
|
---- import Rename
|
|
import GF.Text.UTF8 ----
|
|
import GF.Infra.Option
|
|
--- import Custom
|
|
import GF.Source.ParGF
|
|
import qualified GF.Source.LexGF as L
|
|
|
|
import GF.CF.CF (rules2CF)
|
|
import GF.CF.PPrCF
|
|
import GF.CF.CFtoGrammar
|
|
import GF.CF.EBNF
|
|
|
|
import GF.Infra.ReadFiles ----
|
|
|
|
import Data.Char (toUpper)
|
|
import Data.List (nub)
|
|
import Control.Monad (foldM)
|
|
import System (system)
|
|
|
|
getSourceModule :: Options -> FilePath -> IOE SourceModule
|
|
getSourceModule opts file0 = do
|
|
file <- case getOptVal opts usePreprocessor of
|
|
Just p -> do
|
|
let tmp = "_gf_preproc.tmp"
|
|
cmd = p +++ file0 ++ ">" ++ tmp
|
|
ioeIO $ system cmd
|
|
-- ioeIO $ putStrLn $ "preproc" +++ cmd
|
|
return tmp
|
|
_ -> return file0
|
|
string0 <- readFileIOE file
|
|
let string = case getOptVal opts uniCoding of
|
|
Just "utf8" -> decodeUTF8 string0
|
|
_ -> string0
|
|
let tokens = myLexer string
|
|
mo1 <- ioeErr $ err2err $ pModDef tokens
|
|
ioeErr $ transModDef mo1
|
|
|
|
getSourceGrammar :: Options -> FilePath -> IOE SourceGrammar
|
|
getSourceGrammar opts file = do
|
|
string <- readFileIOE file
|
|
let tokens = myLexer string
|
|
gr1 <- ioeErr $ err2err $ pGrammar tokens
|
|
ioeErr $ transGrammar gr1
|
|
|
|
|
|
-- for old GF format with includes
|
|
|
|
getOldGrammar :: Options -> FilePath -> IOE SourceGrammar
|
|
getOldGrammar opts file = do
|
|
defs <- parseOldGrammarFiles file
|
|
let g = A.OldGr A.NoIncl defs
|
|
let name = justFileName file
|
|
ioeErr $ transOldGrammar opts name g
|
|
|
|
parseOldGrammarFiles :: FilePath -> IOE [A.TopDef]
|
|
parseOldGrammarFiles file = do
|
|
putStrLnE $ "reading grammar of old format" +++ file
|
|
(_, g) <- getImports "" ([],[]) file
|
|
return g -- now we can throw away includes
|
|
where
|
|
getImports oldInitPath (oldImps, oldG) f = do
|
|
(path,s) <- readFileLibraryIOE oldInitPath f
|
|
if not (elem path oldImps)
|
|
then do
|
|
(imps,g) <- parseOldGrammar path
|
|
foldM (getImports (initFilePath path)) (path : oldImps, g ++ oldG) imps
|
|
else
|
|
return (oldImps, oldG)
|
|
|
|
parseOldGrammar :: FilePath -> IOE ([FilePath],[A.TopDef])
|
|
parseOldGrammar file = do
|
|
putStrLnE $ "reading old file" +++ file
|
|
s <- ioeIO $ readFileIf file
|
|
A.OldGr incl topdefs <- ioeErr $ err2err $ pOldGrammar $ oldLexer $ fixNewlines s
|
|
includes <- ioeErr $ transInclude incl
|
|
return (includes, topdefs)
|
|
|
|
----
|
|
|
|
err2err :: E.Err a -> Err a
|
|
err2err (E.Ok v) = Ok v
|
|
err2err (E.Bad s) = Bad s
|
|
|
|
ioeEErr = ioeErr . err2err
|
|
|
|
-- | To resolve the new reserved words:
|
|
-- change them by turning the final letter to upper case.
|
|
--- There is a risk of clash.
|
|
oldLexer :: String -> [L.Token]
|
|
oldLexer = map change . L.tokens where
|
|
change t = case t of
|
|
(L.PT p (L.TS s)) | elem s newReservedWords ->
|
|
(L.PT p (L.TV (init s ++ [toUpper (last s)])))
|
|
_ -> t
|
|
|
|
getCFGrammar :: Options -> FilePath -> IOE SourceGrammar
|
|
getCFGrammar opts file = do
|
|
let mo = takeWhile (/='.') file
|
|
s <- ioeIO $ readFileIf file
|
|
let files = case words (concat (take 1 (lines s))) of
|
|
"--":"include":fs -> fs
|
|
_ -> []
|
|
ss <- ioeIO $ mapM readFileIf files
|
|
cfs <- ioeErr $ mapM (pCF mo) $ s:ss
|
|
defs <- return $ cf2grammar $ rules2CF $ concat cfs
|
|
let g = A.OldGr A.NoIncl defs
|
|
--- let ma = justModuleName file
|
|
--- let mc = 'C':ma ---
|
|
--- let opts' = addOptions (options [useAbsName ma, useCncName mc]) opts
|
|
ioeErr $ transOldGrammar opts file g
|
|
|
|
getEBNFGrammar :: Options -> FilePath -> IOE SourceGrammar
|
|
getEBNFGrammar opts file = do
|
|
let mo = takeWhile (/='.') file
|
|
s <- ioeIO $ readFileIf file
|
|
defs <- ioeErr $ pEBNFasGrammar s
|
|
let g = A.OldGr A.NoIncl defs
|
|
--- let ma = justModuleName file
|
|
--- let mc = 'C':ma ---
|
|
--- let opts' = addOptions (options [useAbsName ma, useCncName mc]) opts
|
|
ioeErr $ transOldGrammar opts file g
|