packages feed

Grempa-0.1.0: examples/Ex1SimpleExprParser.hs

-- | Generate parsers for the simple expression grammar.

-- Needed for generating parsers at compile-time.
{-# LANGUAGE TemplateHaskell #-}
module Ex1SimpleExprParser where

-- Normally you would only import one of these depending on whether you want
-- to generate parsers at compile-time or runtime, but here we will show both.
import Data.Parser.Grempa.Static
import Data.Parser.Grempa.Dynamic

-- Import the grammar
import Ex1SimpleExpr

-- | The type of this function tells us that it is a parser for a
--   language operating on lists of 'Char's returning an 'E' if the parsing
--   is successful.
parseExprStatic :: Parser Char E
-- For making static parsers, Grempa needs both the "representation" of the
-- grammar, which in this case is achieved by [|expr|], and the grammar itself,
-- which is the reason for the repetition of arguments to the function.
parseExprStatic = $(mkStaticParser expr [|expr|])

-- | @'Parser' t a@ is a synynom to @[t] -> 'Either' ('ParseError' t) a@.
--   Often the desired functionality is @[t] -> a@ where the parser will throw
--   an exception if something goes wrong. The 'parse' function does just that
--   transformation to the parser.
parseExprStaticResult :: String -> E
parseExprStaticResult = parse parseExprStatic

-- | For making dynamic parsers, no Template Haskell magic is needed.
--   A parser will be created at runtime, which can take some time for big
--   grammars, but it makes it possible to create grammars that for example
--   depend on some input.
--
--   The function mkDynamicParser takes as a first argument a tuple consisting
--   of a wrap and an unwrap function to be run on all input tokens before and
--   after parsing respectively. This can sometimes be useful when the Eq and
--   Ord instances of the token type are not what is desired in the parser, as
--   we will see in later examples.
--
--   For this grammar, we will use the idWrapper (=(id, id)) which does not wrap
--   the tokens.
parseExprDynamic :: Parser Char E
parseExprDynamic = mkDynamicParser idWrapper expr

-- | You can do the same transformation as before to the dynamically generated
--   parsers.
parseExprDynamicResult :: String -> E
parseExprDynamicResult = parse parseExprDynamic

-- | Try a parser out on some input strings.
--   Run it using for example @test 'parseExprStaticResult'.
--   Notice that the precedence levels are what we are normally used to
--   and that the parentheses are included in the result not by a separate
--   constructor, but just by the structure.
test :: (String -> E) -> [E]
test p = map p inputStrings
  where
    inputStrings =
      [ "x+x"
      , "x*x+x*x"
      , "x*(x+x)*x"
      , "x*((((x))))"
      ]