-- | A DSL for building BNF grammars

module Hydra.Dsl.Grammars where

import qualified Hydra.Grammar as G

import Data.String(IsString(..))


instance IsString G.Pattern where fromString :: String -> Pattern
fromString = String -> Pattern
symbol

infixr 0 >:
(>:) :: String -> G.Pattern -> G.Pattern
String
l >: :: String -> Pattern -> Pattern
>: Pattern
p = LabeledPattern -> Pattern
G.PatternLabeled (LabeledPattern -> Pattern) -> LabeledPattern -> Pattern
forall a b. (a -> b) -> a -> b
$ Label -> Pattern -> LabeledPattern
G.LabeledPattern (String -> Label
G.Label String
l) Pattern
p

alts :: [G.Pattern] -> G.Pattern
alts :: [Pattern] -> Pattern
alts = [Pattern] -> Pattern
G.PatternAlternatives

define :: String -> [G.Pattern] -> G.Production
define :: String -> [Pattern] -> Production
define String
s [Pattern]
pats = Symbol -> Pattern -> Production
G.Production (String -> Symbol
G.Symbol String
s) Pattern
pat
  where
    pat :: Pattern
pat = case [Pattern]
pats of
      [Pattern
p] -> Pattern
p
      [Pattern]
_ -> [Pattern] -> Pattern
alts [Pattern]
pats

ignored :: G.Pattern -> G.Pattern
ignored :: Pattern -> Pattern
ignored = Pattern -> Pattern
G.PatternIgnored

list :: [G.Pattern] -> G.Pattern
list :: [Pattern] -> Pattern
list = [Pattern] -> Pattern
G.PatternSequence

nil :: G.Pattern
nil :: Pattern
nil = Pattern
G.PatternNil

opt :: G.Pattern -> G.Pattern
opt :: Pattern -> Pattern
opt = Pattern -> Pattern
G.PatternOption

plus :: G.Pattern -> G.Pattern
plus :: Pattern -> Pattern
plus = Pattern -> Pattern
G.PatternPlus

regex :: String -> G.Pattern
regex :: String -> Pattern
regex = Regex -> Pattern
G.PatternRegex (Regex -> Pattern) -> (String -> Regex) -> String -> Pattern
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Regex
G.Regex

-- | A helper which matches patterns like "foo.bar.quux" or "one; two; three; four"
sep :: G.Pattern -> G.Pattern -> G.Pattern
sep :: Pattern -> Pattern -> Pattern
sep Pattern
separator Pattern
pat = [Pattern] -> Pattern
list[Pattern
pat, Pattern -> Pattern
star([Pattern] -> Pattern
list[Pattern
separator, Pattern
pat])]

-- | A helper which matches patterns like "foo.bar.quux" or "foo.bar.quux." (i.e. trailing separators are allowed)
sepp :: G.Pattern -> G.Pattern -> G.Pattern
sepp :: Pattern -> Pattern -> Pattern
sepp Pattern
separator Pattern
pat = [Pattern] -> Pattern
list[Pattern
pat, Pattern -> Pattern
star([Pattern] -> Pattern
list[Pattern
separator, Pattern
pat]), Pattern -> Pattern
opt(Pattern
separator)]

star :: G.Pattern -> G.Pattern
star :: Pattern -> Pattern
star = Pattern -> Pattern
G.PatternStar

symbol :: String -> G.Pattern
symbol :: String -> Pattern
symbol = Symbol -> Pattern
G.PatternNonterminal (Symbol -> Pattern) -> (String -> Symbol) -> String -> Pattern
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Symbol
G.Symbol

terminal :: String -> G.Pattern
terminal :: String -> Pattern
terminal = Constant -> Pattern
G.PatternConstant (Constant -> Pattern) -> (String -> Constant) -> String -> Pattern
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Constant
G.Constant