build parsers on demand if they aren't in the PGF file

This commit is contained in:
krasimir
2008-09-16 15:35:15 +00:00
parent a0fb2a0b0b
commit 9827f433fb
2 changed files with 31 additions and 14 deletions

View File

@@ -584,7 +584,10 @@ library
GF.Data.Assoc GF.Data.Assoc
GF.Data.ErrM GF.Data.ErrM
GF.Text.UTF8 GF.Text.UTF8
-- needed only for the on demand generation of PMCFG
GF.Data.BacktrackM
GF.Compile.GenerateFCFG
GF.Compile.GeneratePMCFG
executable gf executable gf
build-depends: base, build-depends: base,

View File

@@ -5,6 +5,8 @@ import PGF.Data
import PGF.Raw.Abstract import PGF.Raw.Abstract
import PGF.BuildParser (buildParserInfo) import PGF.BuildParser (buildParserInfo)
import PGF.Parsing.FCFG.Utilities import PGF.Parsing.FCFG.Utilities
import qualified GF.Compile.GenerateFCFG as FCFG
import qualified GF.Compile.GeneratePMCFG as PMCFG
import qualified Data.Array as Array import qualified Data.Array as Array
import qualified Data.Map as Map import qualified Data.Map as Map
@@ -24,7 +26,7 @@ toPGF (Grm [
App "cat" cts App "cat" cts
]), ]),
App "concrete" ccs App "concrete" ccs
]) = PGF { ]) = let pgf = PGF {
absname = mkCId a, absname = mkCId a,
cncnames = [mkCId c | App c [] <- cs], cncnames = [mkCId c | App c [] <- cs],
gflags = Map.fromAscList [(mkCId f,v) | App f [AStr v] <- gfs], gflags = Map.fromAscList [(mkCId f,v) | App f [AStr v] <- gfs],
@@ -38,21 +40,27 @@ toPGF (Grm [
catfuns = Map.fromAscList catfuns = Map.fromAscList
[(cat,[f | (f, (DTyp _ c _,_)) <- lfuns, c==cat]) | (cat,_) <- lcats] [(cat,[f | (f, (DTyp _ c _,_)) <- lfuns, c==cat]) | (cat,_) <- lcats]
in Abstr aflags funs cats catfuns, in Abstr aflags funs cats catfuns,
concretes = Map.fromAscList [(mkCId lang, toConcr ts) | App lang ts <- ccs] concretes = Map.fromAscList [(mkCId lang, toConcr pgf ts) | App lang ts <- ccs]
} }
in pgf
where where
toConcr :: [RExp] -> Concr toConcr :: PGF -> [RExp] -> Concr
toConcr = foldl add (Concr { toConcr pgf rexp =
cflags = Map.empty, let cnc = foldl add (Concr {cflags = Map.empty,
lins = Map.empty, lins = Map.empty,
opers = Map.empty, opers = Map.empty,
lincats = Map.empty, lincats = Map.empty,
lindefs = Map.empty, lindefs = Map.empty,
printnames = Map.empty, printnames = Map.empty,
paramlincats = Map.empty, paramlincats = Map.empty,
parser = Nothing parser = Just (buildParserOnDemand cnc) -- This thunk will be overwritten if there is a parser
}) -- compiled in the PGF file. We use lazy evaluation here
-- to make sure that buildParserOnDemand is called only
-- if it is needed.
}) rexp
in cnc
where where
add :: Concr -> RExp -> Concr add :: Concr -> RExp -> Concr
add cnc (App "flags" ts) = cnc { cflags = Map.fromAscList [(mkCId f,v) | App f [AStr v] <- ts] } add cnc (App "flags" ts) = cnc { cflags = Map.fromAscList [(mkCId f,v) | App f [AStr v] <- ts] }
@@ -64,6 +72,12 @@ toConcr = foldl add (Concr {
add cnc (App "param" ts) = cnc { paramlincats = mkTermMap ts } add cnc (App "param" ts) = cnc { paramlincats = mkTermMap ts }
add cnc (App "parser" ts) = cnc { parser = Just (toPInfo ts) } add cnc (App "parser" ts) = cnc { parser = Just (toPInfo ts) }
buildParserOnDemand cnc = buildParserInfo fcfg
where
fcfg
| Map.lookup (mkCId "erasing") (cflags cnc) == Just "on" = PMCFG.convertConcrete (abstract pgf) cnc
| otherwise = FCFG.convertConcrete (abstract pgf) cnc
toPInfo :: [RExp] -> ParserInfo toPInfo :: [RExp] -> ParserInfo
toPInfo [App "rules" rs, App "startupcats" cs] = buildParserInfo (rules, cats) toPInfo [App "rules" rs, App "startupcats" cs] = buildParserInfo (rules, cats)
where where