{-# LANGUAGE OverloadedStrings #-}

-- | Provides parser that produces [AST]("Parser.Ast").
module Parser.Parser where

import Control.Monad (liftM2, void)
import Control.Monad.Combinators.Expr (Operator (..), makeExprParser)
import Data.Either (lefts, rights)
import Data.Function ((&))
import Data.Functor (($>))
import Data.Maybe (catMaybes)
import Data.Text (Text)
import MaybeVoid (MaybeVoid, maybeToMaybeVoid)
import qualified Parser.Ast as Ast
import Parser.Lexer
import Text.Megaparsec (MonadParsec (..), choice, eitherP, many, optional, parseMaybe, some, (<|>))

---------------------------------------------------------Parser---------------------------------------------------------

-- * Parser

-- | Parser entry point.
parse :: Text -> Maybe Ast.Program
parse :: Text -> Maybe Program
parse = forall e s a. (Ord e, Stream s) => Parsec e s a -> s -> Maybe a
parseMaybe forall a b. (a -> b) -> a -> b
$ Parser ()
sc forall (f :: * -> *) a b. Applicative f => f a -> f b -> f b
*> ParsecT Void Text Identity Program
programP forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* forall e s (m :: * -> *). MonadParsec e s m => m ()
eof

--------------------------------------------------------Program---------------------------------------------------------

-- * Program (top-level) parsers

-- | Program parser.
programP :: Parser Ast.Program
programP :: ParsecT Void Text Identity Program
programP = do
  [Either VarDecl FunctionDef]
decls <- forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many Parser (Either VarDecl FunctionDef)
topLevelDeclP
  forall (m :: * -> *) a. Monad m => a -> m a
return Ast.Program {topLevelVarDecls :: [VarDecl]
Ast.topLevelVarDecls = forall a b. [Either a b] -> [a]
lefts [Either VarDecl FunctionDef]
decls, topLevelFunctionDefs :: [FunctionDef]
Ast.topLevelFunctionDefs = forall a b. [Either a b] -> [b]
rights [Either VarDecl FunctionDef]
decls}

-- | Top-level declaration parser, it parses either var declaration or function definition.
topLevelDeclP :: Parser (Either Ast.VarDecl Ast.FunctionDef)
topLevelDeclP :: Parser (Either VarDecl FunctionDef)
topLevelDeclP = forall e s (m :: * -> *) a b.
MonadParsec e s m =>
m a -> m b -> m (Either a b)
eitherP' (ParsecT Void Text Identity VarDecl
varDeclP forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text
semicolon) Parser FunctionDef
functionDefP

-- | Function definition parser.
functionDefP :: Parser Ast.FunctionDef
functionDefP :: Parser FunctionDef
functionDefP = Text -> Function -> FunctionDef
Ast.FunctionDef forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
kwFunc forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text
identifierP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Function
functionP

------------------------------------------------------Expressions-------------------------------------------------------

-- * Expressions parsers

-- | Expression parser.
expressionP :: Parser Ast.Expression
expressionP :: Parser Expression
expressionP = forall (m :: * -> *) a.
MonadPlus m =>
m a -> [[Operator m a]] -> m a
makeExprParser (forall (m :: * -> *) a1 a2 r.
Monad m =>
(a1 -> a2 -> r) -> m a1 -> m a2 -> m r
liftM2 (forall (t :: * -> *) b a.
Foldable t =>
(b -> a -> b) -> b -> t a -> b
foldl forall a b. a -> (a -> b) -> b
(&)) Parser Expression
termExpressionP (forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many (ParsecT Void Text Identity (Expression -> Expression)
funcCallOp forall (f :: * -> *) a. Alternative f => f a -> f a -> f a
<|> ParsecT Void Text Identity (Expression -> Expression)
arrayAccessByIndexOp))) [[Operator (ParsecT Void Text Identity) Expression]]
opsTable

-- | Terminal expression parser, it's terminal in terms of 'makeExprParser' parser.
termExpressionP :: Parser Ast.Expression
termExpressionP :: Parser Expression
termExpressionP =
  forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice'
    [ forall a. Parser a -> Parser a
parens Parser Expression
expressionP,
      Value -> Expression
Ast.ExprValue forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Value
valueP,
      Text -> Expression
Ast.ExprIdentifier forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text
identifierP,
      Expression -> Expression
Ast.ExprLenFuncCall forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
idLenFunc forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Parser a -> Parser a
parens Parser Expression
expressionP,
      [Expression] -> Expression
Ast.ExprPrintFuncCall forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
idPrintFunc forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Parser a -> Parser [a]
listedInPar Parser Expression
expressionP,
      [Expression] -> Expression
Ast.ExprPrintlnFuncCall forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
idPrintlnFunc forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Parser a -> Parser [a]
listedInPar Parser Expression
expressionP,
      Expression -> Expression
Ast.ExprPanicFuncCall forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
idPanicFunc forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Parser a -> Parser a
parens Parser Expression
expressionP
    ]

-- | Operators table, contains all operator parsers and their fixity.
opsTable :: [[Operator Parser Ast.Expression]]
opsTable :: [[Operator (ParsecT Void Text Identity) Expression]]
opsTable =
  [ [ Text -> UnaryOp -> Operator (ParsecT Void Text Identity) Expression
unaryOp Text
"+" UnaryOp
Ast.UnaryPlusOp,
      Text -> UnaryOp -> Operator (ParsecT Void Text Identity) Expression
unaryOp Text
"-" UnaryOp
Ast.UnaryMinusOp,
      Text -> UnaryOp -> Operator (ParsecT Void Text Identity) Expression
unaryOp Text
"!" UnaryOp
Ast.NotOp
    ],
    [ Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"*" BinaryOp
Ast.MultOp,
      Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"/" BinaryOp
Ast.DivOp,
      Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"%" BinaryOp
Ast.ModOp
    ],
    [ Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"+" BinaryOp
Ast.PlusOp,
      Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"-" BinaryOp
Ast.MinusOp
    ],
    [ Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"==" BinaryOp
Ast.EqOp,
      Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"!=" BinaryOp
Ast.NeOp,
      Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"<=" BinaryOp
Ast.LeOp,
      Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"<" BinaryOp
Ast.LtOp,
      Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
">=" BinaryOp
Ast.MeOp,
      Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
">" BinaryOp
Ast.MtOp
    ],
    [Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"&&" BinaryOp
Ast.AndOp],
    [Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
"||" BinaryOp
Ast.OrOp]
  ]

-- ** Operators

-- | Utility function, that takes operator symbol, binary operator constructor and gives new binary operator in return.
binaryOp :: Text -> Ast.BinaryOp -> Operator Parser Ast.Expression
binaryOp :: Text
-> BinaryOp -> Operator (ParsecT Void Text Identity) Expression
binaryOp Text
opSym BinaryOp
op = forall (m :: * -> *) a. m (a -> a -> a) -> Operator m a
InfixL forall a b. (a -> b) -> a -> b
$ BinaryOp -> Expression -> Expression -> Expression
Ast.ExprBinaryOp BinaryOp
op forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Text -> Parser Text
symbol Text
opSym

-- | Utility function, that takes operator symbol, unary operator constructor and gives new unary operator in return.
unaryOp :: Text -> Ast.UnaryOp -> Operator Parser Ast.Expression
unaryOp :: Text -> UnaryOp -> Operator (ParsecT Void Text Identity) Expression
unaryOp Text
opSym UnaryOp
op = forall (m :: * -> *) a. m (a -> a) -> Operator m a
Prefix forall a b. (a -> b) -> a -> b
$ UnaryOp -> Expression -> Expression
Ast.ExprUnaryOp UnaryOp
op forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Text -> Parser Text
symbol Text
opSym

-- | Function call operator.
funcCallOp :: Parser (Ast.Expression -> Ast.Expression)
funcCallOp :: ParsecT Void Text Identity (Expression -> Expression)
funcCallOp = forall a b c. (a -> b -> c) -> b -> a -> c
flip Expression -> [Expression] -> Expression
Ast.ExprFuncCall forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Parser a -> Parser [a]
listedInPar Parser Expression
expressionP

-- | Array access by index operator.
arrayAccessByIndexOp :: Parser (Ast.Expression -> Ast.Expression)
arrayAccessByIndexOp :: ParsecT Void Text Identity (Expression -> Expression)
arrayAccessByIndexOp = forall a b c. (a -> b -> c) -> b -> a -> c
flip Expression -> Expression -> Expression
Ast.ExprArrayAccessByIndex forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Parser a -> Parser a
brackets Parser Expression
expressionP

---------------------------------------------------------Types----------------------------------------------------------

-- * Types parsers

-- | Type parser.
typeP :: Parser Ast.Type
typeP :: Parser Type
typeP =
  forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice'
    [ Type
Ast.TInt forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
idInt,
      Type
Ast.TBool forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
idBool,
      Type
Ast.TString forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
idString,
      ArrayType -> Type
Ast.TArray forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ArrayType
arrayTypeP,
      FunctionType -> Type
Ast.TFunction forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser FunctionType
functionTypeP,
      forall a. Parser a -> Parser a
parens Parser Type
typeP
    ]

-- | Array type parser.
arrayTypeP :: Parser Ast.ArrayType
arrayTypeP :: Parser ArrayType
arrayTypeP = forall a b c. (a -> b -> c) -> b -> a -> c
flip Type -> Expression -> ArrayType
Ast.ArrayType forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall a. Parser a -> Parser a
brackets Parser Expression
expressionP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Type
typeP

-- | Function type parser.
functionTypeP :: Parser Ast.FunctionType
functionTypeP :: Parser FunctionType
functionTypeP = [Type] -> MaybeVoid Type -> FunctionType
Ast.FunctionType forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
kwFunc forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Parser a -> Parser [a]
listedInPar Parser Type
typeP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> m (MaybeVoid a)
maybeVoid Parser Type
typeP

-------------------------------------------------------Statements-------------------------------------------------------

-- * Statements parsers

-- | Statement parser.
statementP :: Parser Ast.Statement
statementP :: Parser Statement
statementP =
  forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice'
    [ Parser Statement
stmtReturnP,
      Parser Statement
stmtForGoToP,
      Parser Statement
stmtForP,
      VarDecl -> Statement
Ast.StmtVarDecl forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ParsecT Void Text Identity VarDecl
varDeclP,
      IfElse -> Statement
Ast.StmtIfElse forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser IfElse
ifElseP,
      Block -> Statement
Ast.StmtBlock forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Block
blockP,
      SimpleStmt -> Statement
Ast.StmtSimple forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser SimpleStmt
simpleStmtP
    ]

-- | Return statement parser.
stmtReturnP :: Parser Ast.Statement
stmtReturnP :: Parser Statement
stmtReturnP = MaybeVoid Expression -> Statement
Ast.StmtReturn forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
kwReturn forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> m (MaybeVoid a)
maybeVoid Parser Expression
expressionP

-- | For goto statement parser.
stmtForGoToP :: Parser Ast.Statement
stmtForGoToP :: Parser Statement
stmtForGoToP = ForGoTo -> Statement
Ast.StmtForGoTo forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice' [ForGoTo
Ast.Break forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
kwBreak, ForGoTo
Ast.Continue forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
kwContinue]

-- | For statement parser.
stmtForP :: Parser Ast.Statement
stmtForP :: Parser Statement
stmtForP = For -> Statement
Ast.StmtFor forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (ForHead -> Block -> For
Ast.For forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ forall (f :: * -> *) a. Functor f => f a -> f ()
void Parser Text
kwFor forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT Void Text Identity ForHead
forHead forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Block
blockP)
  where
    forHead :: ParsecT Void Text Identity ForHead
forHead =
      forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice'
        [ Maybe SimpleStmt -> Maybe Expression -> Maybe SimpleStmt -> ForHead
Ast.ForHead
            forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m (Maybe a)
optional' Parser SimpleStmt
simpleStmtP
            forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text
semicolon
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m (Maybe a)
optional' Parser Expression
expressionP
            forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text
semicolon
            forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m (Maybe a)
optional' Parser SimpleStmt
simpleStmtP,
          Maybe SimpleStmt -> Maybe Expression -> Maybe SimpleStmt -> ForHead
Ast.ForHead forall a. Maybe a
Nothing forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m (Maybe a)
optional' Parser Expression
expressionP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) a. Applicative f => a -> f a
pure forall a. Maybe a
Nothing
        ]

-- | Var declaration parser.
varDeclP :: Parser Ast.VarDecl
varDeclP :: ParsecT Void Text Identity VarDecl
varDeclP = Parser Text
kwVar forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Text -> VarValue -> VarDecl
Ast.VarDecl forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Text
identifierP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT Void Text Identity VarValue
varValueP
  where
    varValueP :: ParsecT Void Text Identity VarValue
varValueP =
      forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice'
        [ Maybe Type -> Expression -> VarValue
Ast.VarValue forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m (Maybe a)
optional' Parser Type
typeP forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Text -> Parser Text
symbol Text
"=" forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Expression
expressionP,
          Type -> VarValue
Ast.DefaultedVarValue forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Type
typeP
        ]

-- | If-else parser.
ifElseP :: Parser Ast.IfElse
ifElseP :: Parser IfElse
ifElseP = Parser Text
kwIf forall (f :: * -> *) a b. Functor f => f a -> b -> f b
$> Maybe SimpleStmt -> Expression -> Block -> Else -> IfElse
Ast.IfElse forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m (Maybe a)
optional' (Parser SimpleStmt
simpleStmtP forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text
semicolon) forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Expression
expressionP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Block
blockP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT Void Text Identity Else
elseP
  where
    elseP :: ParsecT Void Text Identity Else
elseP =
      forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice'
        [ IfElse -> Else
Ast.Elif forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
kwElse forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser IfElse
ifElseP,
          Block -> Else
Ast.Else forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
kwElse forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Block
blockP,
          forall (m :: * -> *) a. Monad m => a -> m a
return Else
Ast.NoElse
        ]

-- | Block parser.
blockP :: Parser Ast.Block
blockP :: Parser Block
blockP = forall a. Parser a -> Parser a
braces forall a b. (a -> b) -> a -> b
$ forall a. [Maybe a] -> [a]
catMaybes forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
many (forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m (Maybe a)
optional' Parser Statement
statementP forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Parser Text
semicolon)

-- | Simple statement parser.
simpleStmtP :: Parser Ast.SimpleStmt
simpleStmtP :: Parser SimpleStmt
simpleStmtP = forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice' [Parser SimpleStmt
stmtAssignmentP, Parser SimpleStmt
stmtIncDecP, Parser SimpleStmt
stmtShortVarDeclP, Parser SimpleStmt
stmtExpressionP]

-- | Assignment statement parser.
stmtAssignmentP :: Parser Ast.SimpleStmt
stmtAssignmentP :: Parser SimpleStmt
stmtAssignmentP = Lvalue -> Expression -> SimpleStmt
Ast.StmtAssignment forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Lvalue
lvalueP forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Text -> Parser Text
symbol Text
"=" forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Expression
expressionP

-- | Increment or decrement statement parser.
stmtIncDecP :: Parser Ast.SimpleStmt
stmtIncDecP :: Parser SimpleStmt
stmtIncDecP = Lvalue -> IncDec -> SimpleStmt
Ast.StmtIncDec forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Lvalue
lvalueP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice' [IncDec
Ast.Inc forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Text -> Parser Text
symbol Text
"++", IncDec
Ast.Dec forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Text -> Parser Text
symbol Text
"--"]

-- | Short var declaration statement parser.
stmtShortVarDeclP :: Parser Ast.SimpleStmt
stmtShortVarDeclP :: Parser SimpleStmt
stmtShortVarDeclP = Text -> Expression -> SimpleStmt
Ast.StmtShortVarDecl forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text
identifierP forall (f :: * -> *) a b. Applicative f => f a -> f b -> f a
<* Text -> Parser Text
symbol Text
":=" forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Expression
expressionP

-- | Expression statement parser.
stmtExpressionP :: Parser Ast.SimpleStmt
stmtExpressionP :: Parser SimpleStmt
stmtExpressionP = Expression -> SimpleStmt
Ast.StmtExpression forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Expression
expressionP

-- | Lvalue parser.
lvalueP :: Parser Ast.Lvalue
lvalueP :: Parser Lvalue
lvalueP =
  forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice'
    [ Text -> [Expression] -> Lvalue
Ast.LvalArrEl forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text
identifierP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall (m :: * -> *) a. MonadPlus m => m a -> m [a]
some (forall a. Parser a -> Parser a
brackets Parser Expression
expressionP),
      Text -> Lvalue
Ast.LvalVar forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text
identifierP
    ]

---------------------------------------------------------Values---------------------------------------------------------

-- * Values parsers

-- | Value parser.
valueP :: Parser Ast.Value
valueP :: Parser Value
valueP =
  forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice'
    [ Integer -> Value
Ast.ValInt forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Integer
intLitP,
      Bool -> Value
Ast.ValBool forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Bool
boolLitP,
      Text -> Value
Ast.ValString forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text
stringLitP,
      ArrayValue -> Value
Ast.ValArray forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ArrayValue
arrayValP,
      FunctionValue -> Value
Ast.ValFunction forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser FunctionValue
functionValP
    ]

-- | Array value parser.
arrayValP :: Parser Ast.ArrayValue
arrayValP :: Parser ArrayValue
arrayValP = ArrayType -> [Expression] -> ArrayValue
Ast.ArrayValue forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser ArrayType
arrayTypeP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> forall a. Parser a -> Parser a
braces (forall a. Parser a -> Parser [a]
listed Parser Expression
expressionP)

-- | Function value parser.
functionValP :: Parser Ast.FunctionValue
functionValP :: Parser FunctionValue
functionValP = forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice' [FunctionValue
Ast.Nil forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
idNil, Function -> FunctionValue
Ast.AnonymousFunction forall (f :: * -> *) a b. Functor f => a -> f b -> f a
<$ Parser Text
kwFunc forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Function
functionP]

-- | Nameless function parser.
functionP :: Parser Ast.Function
functionP :: Parser Function
functionP = [(Text, Type)] -> MaybeVoid Type -> Block -> Function
Ast.Function forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser [(Text, Type)]
params forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> ParsecT Void Text Identity (MaybeVoid Type)
result forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Block
blockP
  where
    params :: Parser [(Text, Type)]
params = forall a. Parser a -> Parser [a]
listedInPar ((,) forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Parser Text
identifierP forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
<*> Parser Type
typeP)
    result :: ParsecT Void Text Identity (MaybeVoid Type)
result = forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> m (MaybeVoid a)
maybeVoid Parser Type
typeP

---------------------------------------------------------Utils----------------------------------------------------------

-- * Utils

-- | Choice between elements parser with built-in backtracking support.
choice' :: (Foldable f, MonadParsec e s m, Functor f) => f (m a) -> m a
choice' :: forall (f :: * -> *) e s (m :: * -> *) a.
(Foldable f, MonadParsec e s m, Functor f) =>
f (m a) -> m a
choice' f (m a)
ps = forall (f :: * -> *) (m :: * -> *) a.
(Foldable f, Alternative m) =>
f (m a) -> m a
choice forall a b. (a -> b) -> a -> b
$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> f (m a)
ps

-- | Combine two alternatives with built-in backtracking support.
eitherP' :: MonadParsec e s m => m a -> m b -> m (Either a b)
eitherP' :: forall e s (m :: * -> *) a b.
MonadParsec e s m =>
m a -> m b -> m (Either a b)
eitherP' m a
leftP = forall (m :: * -> *) a b.
Alternative m =>
m a -> m b -> m (Either a b)
eitherP forall a b. (a -> b) -> a -> b
$ forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try m a
leftP

-- | Optional element parser with built-in backtracking support.
optional' :: (MonadParsec e s m) => m a -> m (Maybe a)
optional' :: forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m (Maybe a)
optional' = forall (f :: * -> *) a. Alternative f => f a -> f (Maybe a)
optional forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m a
try

maybeVoid :: (MonadParsec e s m) => m a -> m (MaybeVoid a)
maybeVoid :: forall e s (m :: * -> *) a.
MonadParsec e s m =>
m a -> m (MaybeVoid a)
maybeVoid = forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap forall a. Maybe a -> MaybeVoid a
maybeToMaybeVoid forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall e s (m :: * -> *) a. MonadParsec e s m => m a -> m (Maybe a)
optional'