packages feed

expand-0.0.1: src/Document/Grammars/Markdown.hs

{-# LANGUAGE Arrows, RecursiveDo, EmptyDataDecls, TemplateHaskell, PostfixOperators #-}

module Document.Grammars.Markdown where

import Control.Applicative
import Prelude hiding ((+),(*))
import Language.Grammars.Grammar
import Language.Grammars.Murder
import Language.Grammars.Murder.Derive
import Language.Grammars.Murder.UUParsing
import Language.Grammars.Grammar.AG

import Document.Decl
import Utils

$(csLabels  ["cs_header", "cs_atxPrefix", "cs_atxTitle"])


gMarkdown sem syms = proc () -> do
    
    rec 
        document  <-addNT-< iI (pDocument sem) blockL Ii


        blockL    <-addNT-< pMany $ iI block Ii

        block     <-addNT-< iI header Ii
                     <|>    iI paragraph Ii


        -- Block level

        paragraph <-addNT-< iI concat (textLine+) (ign blankLine) Ii

        header    <-addNT-< iI ((++) . show) atxPrefix atxTitle Ii

        atxPrefix <-addNT-< fmap length $ iI (someOf "#") Ii        
        atxTitle  <-addNT-< iI (\x xs -> value x : xs) (anyExcept "#") (manyExcept "\n") "\n" Ii



        inlineL   <-addNT-< pMany $ iI inline Ii

        -- Inline level

        inline    <-addNT-< iI bold Ii 
                     <|>    iI italics Ii 
                     <|>    iI plain Ii

        plain     <-addNT-< iI (\x xs x'-> value x : xs ++ [value x']) (anyExcept "*_") (someExcept "*_\n") (anyOf "\n") Ii

        bold      <-addNT-< iI "**" (someExcept "*\n") "**" Ii
                      <|>   iI "__" (someExcept "_\n") "__" Ii

        italics   <-addNT-< iI "*" (someExcept "*\n") "*" Ii
                     <|>    iI "_" (someExcept "_\n") "_" Ii


        -- primitives
        textLine  <-addNT-< iI (\x xs -> value x : xs) (anyExcept syms) (manyExcept "\n") "\n" Ii
        blankLine <-addNT-< iI (someOf " \n\t\r") Ii
    
    exportNTs -< exportList inlineL ( export cs_header    header
                                   . export cs_atxPrefix atxPrefix 
                                   . export cs_atxTitle      atxTitle)









lineChars = ['a'..'z'] ++ ['A' .. 'Z'] ++ ['0' .. '9'] ++ " ':;!@()\""


-- Semantics for building the AST
semLine = map value

--semNewLine :: Maybe (DTerm String) -> ()
semNewLine _ = ()

semHeaderAtx :: [DTerm String] -> String -> Block
semHeaderAtx x str = let hlevel = length x
                     in  Header hlevel [Plain str]

semHeaderSetext :: String -> (DTerm String) -> Block
semHeaderSetext str hsym = let hlevel = if (value hsym) == "=" then 1 else 2
                           in  Header hlevel [Plain str]