caml-parser-0.1.0.0: src/CamlParser/Parser/Combinators.hs
{-# LANGUAGE OverloadedStrings #-}
module CamlParser.Parser.Combinators where
import Control.Monad (void)
import Data.Set (Set)
import qualified Data.Set as Set
import Data.Void (Void)
import Text.Megaparsec hiding (Token)
import Text.Megaparsec.Char
import CamlParser.Lexer.Token
import CamlParser.Syntax.Location
import CamlParser.Syntax.Expr
import CamlParser.Syntax.Pattern
type Parser = Parsec Void [Located Token]
tok :: Token -> Parser Token
tok t = token testTok Set.empty
where
testTok (Located t' _)
| t == t' = Just t'
| otherwise = Nothing
matchTok :: (Token -> Maybe a) -> Parser a
matchTok f = token (\(Located t' _) -> f t') Set.empty
identP :: Parser String
identP = matchTok isIdentToken <?> "identifier"
where
isIdentToken (TokIdent s) = Just s
isIdentToken (TokKeywordExt _ s) = Just s
isIdentToken _ = Nothing
intP :: Parser Integer
intP = matchTok isInt <?> "integer"
where
isInt (TokInt n) = Just n
isInt _ = Nothing
floatP :: Parser Double
floatP = matchTok isFloat <?> "float"
where
isFloat (TokFloat f) = Just f
isFloat _ = Nothing
stringP :: Parser String
stringP = matchTok isStr <?> "string"
where
isStr (TokString s) = Just s
isStr _ = Nothing
charP :: Parser Char
charP = matchTok isCh <?> "char"
where
isCh (TokChar c) = Just c
isCh _ = Nothing
keyword :: String -> Parser String
keyword kw = matchTok test <?> ("keyword " ++ kw)
where
test (TokKeywordExt _ s) | s == kw = Just s
test _ = Nothing
located :: Parser a -> Parser (Located a)
located p = do
Located _ loc1 <- lookAhead anySingle
v <- p
Located _ loc2 <- lookAhead anySingle
return $ Located v (loc1 <> loc2)
parens :: Parser a -> Parser a
parens = between (tok TokLParen) (tok TokRParen)
brackets :: Parser a -> Parser a
brackets = between (tok TokLBracket) (tok TokRBracket)
braces :: Parser a -> Parser a
braces = between (tok TokLBrace) (tok TokRBrace)
semi, comma, dot, colon, equal, minusGreater :: Parser ()
semi = void (tok TokSemi)
comma = void (tok TokComma)
dot = void (tok TokDot)
colon = void (tok TokColon)
equal = void (tok TokEqual)
minusGreater = void (tok TokMinusGreater)
bar :: Parser ()
bar = void (tok TokBar)
andP :: Parser ()
andP = void (tok TokAnd)
infixOpP :: Int -> Parser String
infixOpP level = matchTok test <?> ("infix operator level " ++ show level)
where
test (TokInfix l s) | l == level = Just s
test (TokStar) | level == 3 = Just "*"
test (TokSubtractive s) | level == 2 = Just s
test TokEqual | level == 0 = Just "="
test TokEqualEqual | level == 0 = Just "=="
test _ = Nothing
prefixOpP :: Parser String
prefixOpP = matchTok test <?> "prefix operator"
where
test (TokPrefix s) = Just s
test _ = Nothing
subtractiveP :: Parser String
subtractiveP = matchTok test <?> "subtractive operator"
where
test (TokSubtractive s) = Just s
test _ = Nothing
consP :: Parser ()
consP = void (tok TokColonColon)
assignP :: Parser ()
assignP = void (tok TokColonEqual)
lessMinusP :: Parser ()
lessMinusP = void (tok TokLessMinus)
optionalBar :: Parser ()
optionalBar = optional (tok TokBar) >> return ()