packages feed

typed-peg-0.3.0.0: examples/Layout.hs

{-# LANGUAGE DataKinds        #-}
{-# LANGUAGE QuasiQuotes      #-}
{-# LANGUAGE TemplateHaskell  #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE TypeOperators    #-}

module Layout
  ( DoStmt (..)
  , DoEnv
  , doExp
  , layoutOpts
  ) where

import PEG
import PEG.QQ (pegGrammar)

data DoStmt
  = Atom   String
  | Nested [DoStmt]
  deriving (Eq, Show)

-- | @name@ is a character class, so its result is a chunk of the input rather
-- than a 'String' — which is why its annotation is @s@ and why the generated
-- environment takes the stream as a parameter.
--
-- @ws@ has neither a label nor an action, so it returns @()@: that is the
-- DSL's rule for a rule body, and the annotation has to agree with it.  A
-- start expression is different — @%start ws d:doexp ws !.@ returns what its
-- one labelled item returns.
[pegGrammar|
  %name  doExp
  %env   DoEnv
  %start ws d:doexp ws !.

  doexp  :: [DoStmt] <- "do" b:(i:istmts / j:stmts)

  istmts :: [DoStmt] <- ss:(ws st:|s:stmt|)+^>

  stmts  :: [DoStmt] <- r:(ws '{' ws s:stmt ss:(ws ';' ws t:stmt)* ws '}' { s : ss })^~

  stmt   :: DoStmt   <- d:doexp { Nested d } / n:name { Atom (chunkToString n) }

  name   :: s        <- cs:[a-z]+

  ws     :: ()       <- [ \t\r\n]*_~
|]

layoutOpts :: Opts
layoutOpts = defaultOpts { optTokenMode = relD geR }