{-| Module : Text.SExpression.Internal Description : Internal parser functions Copyright : (C) Richard Cook, 2019 Licence : MIT Maintainer : rcook@rcook.org Stability : stable Portability : portable This module provides internal parser functions. -} {-# OPTIONS_GHC -Wall -Werror #-} {-# LANGUAGE CPP #-} {-# LANGUAGE RecordWildCards #-} #undef MEGAPARSEC_7_OR_LATER #ifdef MIN_VERSION_GLASGOW_HASKELL -- GHC >= 7.10.1.0 #if MIN_VERSION_GLASGOW_HASKELL(8,0,0,0) -- GHC >= 8.0.0.0 #if MIN_VERSION_megaparsec(7,0,0) #define MEGAPARSEC_7_OR_LATER #endif #endif #endif module Text.SExpression.Internal ( -- * S-expression parser parseSExpr , -- * S-expression value parsers parseAtom , parseConsList , parseList , parseQuoted , parseStringDef , parseNumberDef , parseBoolDef , mkLiteralParsers , overrideBoolP , overrideNumberP , overrideStringP ) where import Control.Applicative (empty) import Control.Monad (void) import Text.Megaparsec ( (<|>) , endBy , many #ifdef MEGAPARSEC_7_OR_LATER , oneOf #endif , sepBy , try ) import Text.Megaparsec.Char ( char , digitChar , letterChar #ifndef MEGAPARSEC_7_OR_LATER , oneOf #endif , space1 ) import Text.Megaparsec.Char.Lexer ( space , skipLineComment ) import Text.SExpression.Types (Parser, SExpr(..)) import Text.SExpression.Default sc :: Parser () sc = space space1 lineComment empty where lineComment = skipLineComment ";" symbol :: Parser Char symbol = oneOf "!$%&|*+-/:<=>?@^_~#" -- | S-expression parser parseSExpr :: LiteralParsers -> Parser SExpr -- ^ parser parseSExpr lp@(LiteralParsers{..}) = try parseBool <|> parseAtom <|> parseString <|> parseNumber <|> parseQuoted lp <|> do void $ char '(' lst <- (try $ parseList lp) <|> parseConsList lp void $ char ')' >> sc pure lst -- | Parse s-expression atom parseAtom :: Parser SExpr -- ^ parser parseAtom = do h <- letterChar <|> symbol t <- many (letterChar <|> digitChar <|> symbol) return . Atom $ h : t -- | Parse s-expression list parseList :: LiteralParsers -> Parser SExpr -- ^ parser parseList lp = List <$> parseSExpr lp `sepBy` sc -- | Parse s-expression cons list parseConsList :: LiteralParsers -> Parser SExpr -- ^ parser parseConsList lp = do h <- parseSExpr lp `endBy` sc t <- char '.' >> sc >> parseSExpr lp pure $ ConsList h t -- | Parse s-expression quoted expression parseQuoted :: LiteralParsers -> Parser SExpr -- ^ parser parseQuoted lp = do void $ char '\'' e <- parseSExpr lp pure $ List [Atom "quote", e]