grammar-combinators-0.2: Text/GrammarCombinators/Utils/AssessSize.hs
{- Copyright 2010 Dominique Devriese
This file is part of the grammar-combinators library.
The grammar-combinators library is free software: you can
redistribute it and/or modify it under the terms of the GNU
Lesser General Public License as published by the Free
Software Foundation, either version 3 of the License, or (at
your option) any later version.
Foobar is distributed in the hope that it will be useful, but
WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with Foobar. If not, see
<http://www.gnu.org/licenses/>.
-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE ScopedTypeVariables #-}
module Text.GrammarCombinators.Utils.AssessSize (
assessSize
) where
import Text.GrammarCombinators.Base
newtype AssessSizeProductionRule (phi :: * -> *) (r :: * -> *) t v = ASPR {
assessSizeRule :: Int
}
instance ProductionRule (AssessSizeProductionRule phi r t) where
endOfInput = ASPR 1
die = ASPR 1
a ||| b = ASPR $ assessSizeRule a + assessSizeRule b
a >>> b = ASPR $ assessSizeRule a + assessSizeRule b
instance EpsProductionRule (AssessSizeProductionRule phi r t) where
epsilon _ = ASPR 1
instance LiftableProductionRule (AssessSizeProductionRule phi r t) where
epsilonL _ _ = ASPR 1
instance (Token t) => TokenProductionRule (AssessSizeProductionRule phi r t) t where
token _ = ASPR 1
anyToken = ASPR 1
instance RecProductionRule (AssessSizeProductionRule phi r t) phi r where
ref _ = ASPR 1
instance LoopProductionRule (AssessSizeProductionRule phi r t) phi r where
manyRef _ = ASPR 1
many1Ref _ = ASPR 1
-- | Assess the size of a given grammar. Primitive rules ('token', 'ref', 'manyRef', 'many1Ref', 'epsilon')
-- are counted as 1 point, combinators like '|||' or '>>>' just add the points of their left and
-- right hand sides. Proposals for better metrics are welcome.
assessSize :: forall phi r t rr . (Token t, FoldFam phi) =>
GExtendedContextFreeGrammar phi t r rr -> Int
assessSize gram =
let
f idx = assessSizeRule $ gram idx
in foldFam ((+) . f) 0