Massage .cabal files.
[haskell/symantic.git] / symantic-grammar / Language / Symantic / Grammar / Regular.hs
index 20b410ab40d636472485e2801d3209334ca38d86..cd8def7c601c844cf8cbc655f728802f7e045810 100644 (file)
@@ -1,62 +1,80 @@
--- | This module defines symantics
--- for regular grammars.
+-- | Symantics for regular grammars.
 module Language.Symantic.Grammar.Regular where
 
+import Data.Semigroup (Semigroup(..))
 import Data.String (IsString(..))
 import qualified Data.Text as Text
-import Data.Semigroup (Semigroup(..))
 
+import Language.Symantic.Grammar.Meta
+import Language.Symantic.Grammar.Fixity
 import Language.Symantic.Grammar.EBNF
 import Language.Symantic.Grammar.Terminal
 
 -- * Type 'Reg'
 -- | Left or right regular grammar.
-newtype Reg (lr::LR) g a = Reg { unReg :: g a }
- deriving (IsString, Functor, Gram_Terminal)
-deriving instance Alter g => Alter (Reg lr g)
-deriving instance Try g => Try (Reg lr g)
+newtype Reg (lr::Side) g a = Reg { unReg :: g a }
+ deriving (IsString, Functor, Gram_Char, Gram_String)
+deriving instance Gram_Alt g => Gram_Alt (Reg lr g)
+deriving instance Gram_Try g => Gram_Try (Reg lr g)
 deriving instance Gram_Rule g => Gram_Rule (Reg lr g)
-deriving instance (Functor g, Alter g, Gram_RegL g) => Gram_RegL (RegL g)
-deriving instance (Functor g, Alter g, Gram_RegR g) => Gram_RegR (RegR g)
-deriving instance Gram_RegL RuleDef
-deriving instance Gram_RegR RuleDef
-deriving instance Gram_RuleDef g => Gram_RuleDef (RegR g)
-deriving instance Gram_RuleDef g => Gram_RuleDef (RegL g)
+deriving instance Gram_Reader st g => Gram_Reader st (Reg lr g)
+deriving instance Gram_State st g => Gram_State st (Reg lr g)
+deriving instance Gram_Error err g => Gram_Error err (Reg lr g)
+deriving instance (Functor g, Gram_Alt g, Gram_RegL g) => Gram_RegL (RegL g)
+deriving instance (Functor g, Gram_Alt g, Gram_RegR g) => Gram_RegR (RegR g)
+deriving instance Gram_RegL RuleEBNF
+deriving instance Gram_RegR RuleEBNF
+deriving instance Gram_RuleEBNF g => Gram_RuleEBNF (RegR g)
+deriving instance Gram_RuleEBNF g => Gram_RuleEBNF (RegL g)
 
 reg_of_Terminal :: Terminal g a -> Reg lr g a
 reg_of_Terminal (Terminal g) = Reg g
 
-type RegL = Reg 'L
-type RegR = Reg 'R
+type RegL = Reg 'SideL
+type RegR = Reg 'SideR
 
--- ** Class 'Alter'
+-- ** Class 'Gram_Alt'
 -- | Like 'Alternative' but without the 'Applicative' super-class,
 -- because a regular grammar is not closed under 'Applicative'.
--- And also because the alternative operator has to backtrack
--- when the first alternative fails.
-class Alter g where
+class Gram_Alt g where
        empty  :: g a
        (<+>)  :: g a -> g a -> g a
        infixl 3 <+>
        choice :: [g a] -> g a
        choice = foldr (<+>) empty
-deriving instance Alter p => Alter (Terminal p)
-deriving instance Alter RuleDef
-instance Alter EBNF where
+deriving instance Gram_Alt p => Gram_Alt (Terminal p)
+deriving instance Gram_Alt RuleEBNF
+instance Gram_Alt EBNF where
        empty = ebnf_const $ "empty"
-       EBNF g <+> EBNF q = EBNF $ \bo po -> infix_paren po op $
-               g bo (op, L) <> " | " <> q bo (op, R)
-               where op = infixB L 2
+       EBNF g <+> EBNF q =
+               EBNF $ \bo po -> parenInfix po op $
+               g bo (op, SideL) <> " | " <> q bo (op, SideR)
+               where op = infixB SideL 2
        choice [] = empty
        choice [g] = g
-       choice l@(_:_) = EBNF $ \bo po -> infix_paren po op $
+       choice l@(_:_) =
+               EBNF $ \bo po -> parenInfix po op $
                Text.intercalate " | " $
-               (unEBNF <$> l) <*> pure bo <*> pure (op, L)
-               where op = infixB L 2
+               (unEBNF <$> l) <*> pure bo <*> pure (op, SideL)
+               where op = infixB SideL 2
+
+-- *** Type 'Gram_Try'
+-- | Explicit backtracking.
+--
+-- To get more accurate error messages,
+-- it is helpful to backtrack (put 'try' constructors)
+-- only when the grammar actually has another alternative
+-- that could match, instead of always backtracking
+-- all previous alternatives, as in: 'try'@ a @'<+>'@ b@
+class Gram_Try g where
+       try :: g a -> g a
+instance Gram_Try EBNF where
+       try = id
+deriving instance Gram_Try RuleEBNF
 
 -- ** Class 'Gram_RegR'
 -- | Symantics for right regular grammars.
-class (Functor g, Alter g) => Gram_RegR g where
+class (Functor g, Gram_Alt g) => Gram_RegR g where
        (.*>) :: Terminal g (a -> b) -> RegR g a -> RegR g b
        infixl 4 .*>
        manyR :: Terminal g a -> RegR g [a]
@@ -65,12 +83,13 @@ class (Functor g, Alter g) => Gram_RegR g where
        someR g = (:) <$> g .*> manyR g
 instance Gram_RegR EBNF where
        Terminal f .*> Reg x = Reg $ f <*> x
-       manyR (Terminal (EBNF g)) = Reg $ EBNF $ \rm _po -> "{" <> g rm (op, L) <> "}"  where op = infixN0
-       someR (Terminal (EBNF g)) = Reg $ EBNF $ \rm _po -> "{" <> g rm (op, L) <> "}-" where op = infixN0
+       manyR (Terminal (EBNF g)) = Reg $ EBNF $ \rm _po -> "{" <> g rm (op, SideL) <> "}"  where op = infixN0
+       someR (Terminal (EBNF g)) = Reg $ EBNF $ \rm _po -> "{" <> g rm (op, SideL) <> "}-" where op = infixN0
+        -- NOTE: the suffix "-" symbolizes "minus the empty string".
 
 -- ** Class 'Gram_RegL'
 -- | Symantics for left regular grammars.
-class (Functor g, Alter g) => Gram_RegL g where
+class (Functor g, Gram_Alt g) => Gram_RegL g where
        (<*.) :: RegL g (a -> b) -> Terminal g a -> RegL g b
        infixl 4 <*.
        manyL :: Terminal g a -> RegL g [a]
@@ -80,5 +99,5 @@ class (Functor g, Alter g) => Gram_RegL g where
        someL g = (\cs c -> cs ++ [c]) <$> manyL g <*. g
 instance Gram_RegL EBNF where
        Reg f <*. Terminal x = Reg $ f <*> x
-       manyL (Terminal (EBNF g)) = Reg $ EBNF $ \rm _po -> "{" <> g rm (op, L) <> "}"  where op = infixN0
-       someL (Terminal (EBNF g)) = Reg $ EBNF $ \rm _po -> "{" <> g rm (op, L) <> "}-" where op = infixN0
+       manyL (Terminal (EBNF g)) = Reg $ EBNF $ \rm _po -> "{" <> g rm (op, SideL) <> "}"  where op = infixN0
+       someL (Terminal (EBNF g)) = Reg $ EBNF $ \rm _po -> "{" <> g rm (op, SideL) <> "}-" where op = infixN0