{- 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 . -} {-# LANGUAGE EmptyDataDecls #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE TypeFamilies #-} module Text.GrammarCombinators.Library.Numeric ( DecimalInteger, NumericDomain (DecimalInteger), NumericValue (NVI), numericGrammar, procNumericGrammar ) where import Text.GrammarCombinators.Base data DecimalDigit data DecimalNonZeroDigit data DecimalInteger -- | This domain is intended to be reused in grammars where decimal integers are used. -- You can refer to the DecimalInteger non-terminal using the 'lib' primitive from the 'ProductionRuleWithLibrary' type class -- and then obtain the combined grammar by combining your grammar with 'procNumericGrammar' using the -- 'Text.GrammarCombinators.Transform.CombineGrammars.combineGrammars' function data NumericDomain ix where DecimalDigit :: NumericDomain DecimalDigit DecimalNonZeroDigit :: NumericDomain DecimalNonZeroDigit DecimalInteger :: NumericDomain DecimalInteger instance ShowFam NumericDomain where showIdx DecimalDigit = "DecimalDigit" showIdx DecimalNonZeroDigit = "DecimalNonZeroDigit" showIdx DecimalInteger = "DecimalInteger" instance FoldFam NumericDomain where foldFam f n = f DecimalDigit $ f DecimalNonZeroDigit $ f DecimalInteger n instance MemoFam NumericDomain where data Memo NumericDomain v = MND (v DecimalDigit) (v DecimalNonZeroDigit) (v DecimalInteger) toMemo f = MND (f DecimalDigit) (f DecimalNonZeroDigit) (f DecimalInteger) fromMemo (MND v _ _) DecimalDigit = v fromMemo (MND _ v _) DecimalNonZeroDigit = v fromMemo (MND _ _ v) DecimalInteger = v instance EqFam NumericDomain where overrideIdx _ DecimalDigit v DecimalDigit = v overrideIdx _ DecimalNonZeroDigit v DecimalNonZeroDigit = v overrideIdx _ DecimalInteger v DecimalInteger = v overrideIdx f _ _ idx = f idx instance Domain NumericDomain data PFNum r ix where DecimalDigitF :: Char -> PFNum r DecimalDigit DecimalNonZeroDigitF :: Char -> PFNum r DecimalNonZeroDigit DecimalIntegerF :: r DecimalNonZeroDigit -> [r DecimalDigit] -> PFNum r DecimalInteger type instance PF NumericDomain = PFNum numericGrammar :: ExtendedContextFreeGrammar NumericDomain Char numericGrammar DecimalInteger = DecimalIntegerF $>> ref DecimalNonZeroDigit >>> manyRef DecimalDigit numericGrammar DecimalDigit = DecimalDigitF $>> tokenRange ['0'..'9'] numericGrammar DecimalNonZeroDigit = DecimalNonZeroDigitF $>> tokenRange ['1'..'9'] data family NumericValue n ix data instance NumericValue n DecimalInteger = NVI n data instance NumericValue n DecimalDigit = NVD { unNVD :: Char } data instance NumericValue n DecimalNonZeroDigit = NVND Char processNumerics :: (Read n) => Processor NumericDomain (NumericValue n) processNumerics DecimalDigit (DecimalDigitF c) = NVD c processNumerics DecimalNonZeroDigit (DecimalNonZeroDigitF c) = NVND c processNumerics DecimalInteger (DecimalIntegerF (NVND c) wcs) = NVI num where num = read $ c : cs cs = map unNVD wcs -- | The standard processing grammar for domain 'NumericDomain', intended to be combined with other grammars using -- the 'Text.GrammarCombinators.Transform.CombineGrammars.combineGrammars' function. procNumericGrammar :: (Read n) => ProcessingExtendedContextFreeGrammar NumericDomain Char (NumericValue n) procNumericGrammar = applyProcessorE numericGrammar processNumerics