packages feed

anatomy-0.4: src/Anatomy/Parser.hs

module Anatomy.Parser (parseFile, parseDefinition) where

import Control.Monad.Error
import Text.Parsec hiding (parse)
import Atomo.Parser (continue)
import Atomo.Lexer.Base (TaggedToken)
import Atomo.Parser.Expand
import Atomo.Parser.Expr hiding (parser)
import qualified Atomo.Types as AT
import qualified Atomo.Parser.Base as AP

import Anatomy.Lexer (lexer, defLexer, tagged)
import Anatomy.Parser.Base
import Anatomy.Types


pNested :: Parser Segment
pNested = do
    pos <- getPosition
    s <- getState
    ts <- nested
    case runParser p s (show pos) ts of
        Left e -> fail ("nested: " ++ show e)
        Right (r, s') -> do
            putState s'
            return (Nested r)
  where
    p = do
        r <- parser
        s <- getState
        return (r, s)

subParse :: [TaggedAToken] -> Parser [Segment]
subParse ts = do
    pos <- getPosition
    s <- getState
    case runParser p s (show pos) ts of
        Left e -> fail ("sub: " ++ show e)
        Right (r, s') -> do
            putState s'
            return r
  where
    p = do
        r <- parser
        s <- getState
        return (r, s)

pChunk :: Parser Segment
pChunk = do
    c <- chunk
    return (Chunk c)

pKeyword :: Parser Segment
pKeyword = do
    (ns, ts) <- keyword
    ss <- subParse ts
    return (KeywordDispatch ns ss)

pSingle :: Parser Segment
pSingle = fmap SingleDispatch single

pAtomo :: Parser Segment
pAtomo = do
    ts <- atomo
    fmap Atomo (subAtomo pExpr ts)

subAtomo :: AP.Parser a -> [TaggedToken] -> Parser a
subAtomo p ts = do
    pos <- getPosition
    s <- getState
    case runParser p s (show pos) ts of
        Left e -> fail ("atomo: " ++ show e)
        Right ok -> return ok

pDefinition :: Parser Definition
pDefinition = do
    (t, cs, r) <- definition
    nt <- subAtomo pDispatch t
    ncs <- mapM (subAtomo pDispatch) cs
    nr <- subAtomo pDispatch r
    return (Definition nt ncs nr)

parser :: Parser [Segment]
parser = do
    ss <- many $ choice
        [ pKeyword
        , pSingle
        , pAtomo
        , pNested
        , pChunk
        ]
    eof
    return ss

expandSegment :: Segment -> AT.VM Segment
expandSegment (Atomo e) = liftM Atomo (macroExpand e)
expandSegment (Nested ss) =
  liftM Nested (mapM expandSegment ss)
expandSegment (InlineDefinition d (Just s)) =
  liftM (InlineDefinition d . Just) (expandSegment s)
expandSegment s = return s

parseFile :: String -> AT.VM [Segment]
parseFile fn = liftIO (readFile fn) >>= continue lexer parser fn >>= mapM expandSegment

parseDefinition :: String -> AT.VM Definition
parseDefinition = continue
    (fmap (:[]) $ tagged defLexer)
    (do { r <- pDefinition; eof; return r })
    "<definition>"