egison-4.1.0: hs-src/Language/Egison/Parser/SExpr.hs
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE ViewPatterns #-}
{-# OPTIONS_GHC -Wno-all #-} -- Since we will soon deprecate this parser
{- |
Module : Language.Egison.Parser.SExpr
Licence : MIT
This module implements the parser for the old S-expression syntax.
-}
module Language.Egison.Parser.SExpr
(
-- * Parse a string
parseTopExprs
, parseTopExpr
, parseExprs
, parseExpr
) where
import Control.Applicative (pure, (*>), (<$>), (<*), (<*>))
import Control.Monad.Except (throwError)
import Control.Monad.Identity (Identity)
import Data.Char (isLower, isUpper, toUpper)
import Data.Either
import Data.Functor (($>))
import Data.List.Split (splitOn)
import Data.Ratio
import qualified Data.Set as Set
import qualified Data.Text as T
import Text.Parsec
import Text.Parsec.String
import qualified Text.Parsec.Token as P
import Language.Egison.AST
parseTopExprs :: String -> Either String [TopExpr]
parseTopExprs = doParse $ do
ret <- whiteSpace >> endBy topExpr whiteSpace
eof
return ret
parseTopExpr :: String -> Either String TopExpr
parseTopExpr = doParse $ do
ret <- whiteSpace >> topExpr
whiteSpace >> eof
return ret
parseExprs :: String -> Either String [Expr]
parseExprs = doParse $ do
ret <- whiteSpace >> endBy expr whiteSpace
eof
return ret
parseExpr :: String -> Either String Expr
parseExpr = doParse $ do
ret <- whiteSpace >> expr
whiteSpace >> eof
return ret
--
-- Parser
--
doParse :: Parser a -> String -> Either String a
doParse p input = either (throwError . show) return $ parse p "egison" input
doParse' :: Parser a -> String -> a
doParse' p input = case doParse p input of
Right x -> x
--
-- Expressions
--
topExpr :: Parser TopExpr
topExpr = try (Test <$> expr)
<|> try defineExpr
<|> try (parens (testExpr
<|> executeExpr
<|> loadFileExpr
<|> loadExpr))
<?> "top-level expression"
defineExpr :: Parser TopExpr
defineExpr = parens (keywordDefine >> Define <$> (char '$' >> identVarWithIndices) <*> expr)
testExpr :: Parser TopExpr
testExpr = keywordTest >> Test <$> expr
executeExpr :: Parser TopExpr
executeExpr = keywordExecute >> Execute <$> expr
loadFileExpr :: Parser TopExpr
loadFileExpr = keywordLoadFile >> LoadFile <$> stringLiteral
loadExpr :: Parser TopExpr
loadExpr = keywordLoad >> Load <$> stringLiteral
expr :: Parser Expr
expr = P.lexeme lexer (do expr0 <- expr' <|> quoteExpr
expr1 <- option expr0 $ try (string "..." >> IndexedExpr False expr0 <$> parseindex)
<|> IndexedExpr True expr0 <$> parseindex
option expr1 $ (\x -> makeApply "**" [expr1, x]) <$> try (char '^' >> expr'))
where parseindex :: Parser [IndexExpr Expr]
parseindex = many1 (try (MultiSubscript <$> (char '_' >> expr') <*> (string "..._" >> expr'))
<|> try (MultiSuperscript <$> (char '~' >> expr') <*> (string "...~" >> expr'))
<|> try (Subscript <$> (char '_' >> expr'))
<|> try (Superscript <$> (char '~' >> expr'))
<|> try (SupSubscript <$> (string "~_" >> expr'))
<|> try (Userscript <$> (char '|' >> expr')))
quoteExpr :: Parser Expr
quoteExpr = char '\'' >> QuoteExpr <$> expr'
expr' :: Parser Expr
expr' = try anonParamFuncExpr
<|> try (ConstantExpr <$> constantExpr)
<|> try anonParamExpr
<|> try freshVarExpr
<|> try varExpr
<|> inductiveDataExpr
<|> try vectorExpr
<|> try tupleExpr
<|> try hashExpr
<|> collectionExpr
<|> quoteSymbolExpr
<|> wedgeExpr
<|> parens (ifExpr
<|> lambdaExpr
<|> memoizedLambdaExpr
<|> cambdaExpr
<|> patternFunctionExpr
<|> letRecExpr
<|> letExpr
<|> letStarExpr
<|> withSymbolsExpr
<|> doExpr
<|> matchAllExpr
<|> matchAllDFSExpr
<|> matchExpr
<|> matchDFSExpr
<|> matchAllLambdaExpr
<|> matchLambdaExpr
<|> matcherExpr
<|> seqExpr
<|> applyExpr
<|> cApplyExpr
<|> algebraicDataMatcherExpr
<|> generateTensorExpr
<|> tensorExpr
<|> tensorContractExpr
<|> tensorMapExpr
<|> tensorMap2Expr
<|> transposeExpr
<|> subrefsExpr
<|> suprefsExpr
<|> userrefsExpr
<|> functionWithArgExpr
)
<?> "expression"
varExpr :: Parser Expr
varExpr = VarExpr <$> ident
freshVarExpr :: Parser Expr
freshVarExpr = char '#' >> return FreshVarExpr
inductiveDataExpr :: Parser Expr
inductiveDataExpr = angles $ do
name <- upperName
args <- sepEndBy expr whiteSpace
return $ makeApply name args
tupleExpr :: Parser Expr
tupleExpr = brackets $ TupleExpr <$> sepEndBy expr whiteSpace
data InnerExpr
= ElementExpr Expr
| SubCollectionExpr Expr
collectionExpr :: Parser Expr
collectionExpr = do
inners <- braces $ sepEndBy innerExpr whiteSpace
return $ f [] inners
where
innerExpr :: Parser InnerExpr
innerExpr = (char '@' >> SubCollectionExpr <$> expr)
<|> ElementExpr <$> expr
isElementExpr :: InnerExpr -> Bool
isElementExpr ElementExpr{} = True
isElementExpr _ = False
f :: [Expr] -> [InnerExpr] -> Expr
f xs [] = CollectionExpr xs
f xs [ElementExpr y] = CollectionExpr (xs ++ [y])
f [] [SubCollectionExpr y] = y
f [x] [SubCollectionExpr y] = ConsExpr x y
f xs [SubCollectionExpr y] = JoinExpr (CollectionExpr xs) y
f xs (ElementExpr y : ys) = f (xs ++ [y]) ys
f [] (SubCollectionExpr y : ys) = JoinExpr y (f [] ys)
f [x] (SubCollectionExpr y : ys) = ConsExpr x (JoinExpr y (f [] ys))
f xs (SubCollectionExpr y : ys) = JoinExpr (CollectionExpr xs) (JoinExpr y (f [] ys))
vectorExpr :: Parser Expr
vectorExpr = between lp rp $ VectorExpr <$> sepEndBy expr whiteSpace
where
lp = P.lexeme lexer (string "[|")
rp = string "|]"
hashExpr :: Parser Expr
hashExpr = between lp rp $ HashExpr <$> sepEndBy pairExpr whiteSpace
where
lp = P.lexeme lexer (string "{|")
rp = string "|}"
pairExpr :: Parser (Expr, Expr)
pairExpr = brackets $ (,) <$> expr <*> expr
wedgeExpr :: Parser Expr
wedgeExpr = do
e <- char '!' >> expr
case e of
ApplyExpr e1 e2 -> return $ WedgeApplyExpr e1 e2
functionWithArgExpr :: Parser Expr
functionWithArgExpr = keywordFunction >> FunctionExpr <$> between lp rp (sepEndBy ident whiteSpace)
where
lp = P.lexeme lexer (char '[')
rp = char ']'
quoteSymbolExpr :: Parser Expr
quoteSymbolExpr = char '`' >> QuoteSymbolExpr <$> expr
matchAllExpr :: Parser Expr
matchAllExpr = keywordMatchAll >> MatchAllExpr BFSMode <$> expr <*> expr <*> (((:[]) <$> matchClause) <|> matchClauses)
matchAllDFSExpr :: Parser Expr
matchAllDFSExpr = keywordMatchAllDFS >> MatchAllExpr DFSMode <$> expr <*> expr <*> (((:[]) <$> matchClause) <|> matchClauses)
matchExpr :: Parser Expr
matchExpr = keywordMatch >> MatchExpr BFSMode <$> expr <*> expr <*> matchClauses
matchDFSExpr :: Parser Expr
matchDFSExpr = keywordMatchDFS >> MatchExpr DFSMode <$> expr <*> expr <*> matchClauses
matchAllLambdaExpr :: Parser Expr
matchAllLambdaExpr = keywordMatchAllLambda >> MatchAllLambdaExpr <$> expr <*> (((:[]) <$> matchClause) <|> matchClauses)
matchLambdaExpr :: Parser Expr
matchLambdaExpr = keywordMatchLambda >> MatchLambdaExpr <$> expr <*> matchClauses
matchClauses :: Parser [MatchClause]
matchClauses = braces $ sepEndBy matchClause whiteSpace
matchClause :: Parser MatchClause
matchClause = brackets $ (,) <$> pattern <*> expr
matcherExpr :: Parser Expr
matcherExpr = keywordMatcher >> MatcherExpr <$> ppMatchClauses
ppMatchClauses :: Parser [PatternDef]
ppMatchClauses = braces $ sepEndBy ppMatchClause whiteSpace
ppMatchClause :: Parser PatternDef
ppMatchClause = brackets $ (,,) <$> ppPattern <*> expr <*> pdMatchClauses
pdMatchClauses :: Parser [(PrimitiveDataPattern, Expr)]
pdMatchClauses = braces $ sepEndBy pdMatchClause whiteSpace
pdMatchClause :: Parser (PrimitiveDataPattern, Expr)
pdMatchClause = brackets $ (,) <$> pdPattern <*> expr
ppPattern :: Parser PrimitivePatPattern
ppPattern = P.lexeme lexer (ppWildCard
<|> ppPatVar
<|> ppValuePat
<|> ppInductivePat
<|> ppTuplePat
<?> "primitive-pattren-pattern")
ppWildCard :: Parser PrimitivePatPattern
ppWildCard = reservedOp "_" $> PPWildCard
ppPatVar :: Parser PrimitivePatPattern
ppPatVar = reservedOp "$" $> PPPatVar
ppValuePat :: Parser PrimitivePatPattern
ppValuePat = reservedOp ",$" >> PPValuePat <$> ident
ppInductivePat :: Parser PrimitivePatPattern
ppInductivePat = angles (PPInductivePat <$> lowerName <*> sepEndBy ppPattern whiteSpace)
ppTuplePat :: Parser PrimitivePatPattern
ppTuplePat = brackets $ PPTuplePat <$> sepEndBy ppPattern whiteSpace
pdPattern :: Parser PrimitiveDataPattern
pdPattern = P.lexeme lexer pdPattern'
pdPattern' :: Parser PrimitiveDataPattern
pdPattern' = reservedOp "_" $> PDWildCard
<|> (char '$' >> PDPatVar <$> ident)
<|> braces ((PDConsPat <$> pdPattern <*> (char '@' *> pdPattern))
<|> (PDSnocPat <$> (char '@' *> pdPattern) <*> pdPattern)
<|> pure PDEmptyPat)
<|> angles (PDInductivePat <$> upperName <*> sepEndBy pdPattern whiteSpace)
<|> brackets (PDTuplePat <$> sepEndBy pdPattern whiteSpace)
<|> PDConstantPat <$> constantExpr
<?> "primitive-data-pattern"
ifExpr :: Parser Expr
ifExpr = keywordIf >> IfExpr <$> expr <*> expr <*> expr
lambdaExpr :: Parser Expr
lambdaExpr = keywordLambda >> LambdaExpr <$> argNames <*> expr
memoizedLambdaExpr :: Parser Expr
memoizedLambdaExpr = keywordMemoizedLambda >> MemoizedLambdaExpr <$> varNames <*> expr
memoizeFrame :: Parser [(Expr, Expr, Expr)]
memoizeFrame = braces $ sepEndBy memoizeBinding whiteSpace
memoizeBinding :: Parser (Expr, Expr, Expr)
memoizeBinding = brackets $ (,,) <$> expr <*> expr <*> expr
cambdaExpr :: Parser Expr
cambdaExpr = keywordCambda >> char '$' >> CambdaExpr <$> ident <*> expr
patternFunctionExpr :: Parser Expr
patternFunctionExpr = keywordPatternFunction >> PatternFunctionExpr <$> varNames <*> pattern
letRecExpr :: Parser Expr
letRecExpr = keywordLetRec >> LetRecExpr <$> bindings <*> expr
letExpr :: Parser Expr
letExpr = keywordLet >> LetRecExpr <$> bindings <*> expr
letStarExpr :: Parser Expr
letStarExpr = keywordLetStar >> LetRecExpr <$> bindings <*> expr
withSymbolsExpr :: Parser Expr
withSymbolsExpr = keywordWithSymbols >> WithSymbolsExpr <$> braces (sepEndBy ident whiteSpace) <*> expr
doExpr :: Parser Expr
doExpr = keywordDo >> DoExpr <$> statements <*> option (makeApply "return" []) expr
statements :: Parser [BindingExpr]
statements = braces $ sepEndBy statement whiteSpace
statement :: Parser BindingExpr
statement = try binding
<|> try (brackets (Bind (PDTuplePat []) <$> expr))
<|> (Bind (PDTuplePat []) <$> expr)
bindings' :: Parser [(PrimitiveDataPattern, Expr)]
bindings' = braces $ sepEndBy binding' whiteSpace
binding' :: Parser (PrimitiveDataPattern, Expr)
binding' = brackets $ (,) <$> varNames' <*> expr
bindings :: Parser [BindingExpr]
bindings = braces $ sepEndBy binding whiteSpace
binding :: Parser BindingExpr
binding = brackets $ Bind <$> varNames' <*> expr
varNames :: Parser [String]
varNames = return <$> (char '$' >> ident)
<|> brackets (sepEndBy (char '$' >> ident) whiteSpace)
varNames' :: Parser PrimitiveDataPattern
varNames' = PDPatVar <$> (char '$' >> ident)
<|> PDTuplePat <$> brackets (sepEndBy (PDPatVar <$> (char '$' >> ident)) whiteSpace)
argNames :: Parser [Arg ArgPattern]
argNames = return <$> argName
<|> brackets (sepEndBy argName whiteSpace)
argName :: Parser (Arg ArgPattern)
argName = try (ScalarArg <$> (char '$' >> argPattern))
<|> try (InvertedScalarArg <$> (string "*$" >> argPattern))
<|> try (TensorArg <$> (char '%' >> argPattern))
argPattern :: Parser ArgPattern
argPattern = APPatVar <$> ident
seqExpr :: Parser Expr
seqExpr = keywordSeq >> SeqExpr <$> expr <*> expr
cApplyExpr :: Parser Expr
cApplyExpr = keywordCApply >> CApplyExpr <$> expr <*> expr
applyExpr :: Parser Expr
applyExpr = do
func <- expr
args <- sepEndBy arg whiteSpace
let vars = lefts args
case vars of
[] -> return $ ApplyExpr func (rights args)
_ | all null vars ->
let n = toInteger (length vars)
args' = f args 1
in return $ AnonParamFuncExpr n $ ApplyExpr func args'
| all (not . null) vars ->
let ns = Set.fromList $ map read vars
n = Set.size ns
in if Set.findMin ns == 1 && Set.findMax ns == n
then
let args' = map g args
in return $ AnonParamFuncExpr (toInteger n) $ ApplyExpr func args'
else fail "invalid anonymous parameter function"
| otherwise -> fail "invalid anonymous parameter function"
where
arg = try (Right <$> expr)
<|> char '$' *> (Left <$> option "" index)
index = (:) <$> satisfy (\c -> '1' <= c && c <= '9') <*> many digit
f [] _ = []
f (Left _ : args) n = AnonParamExpr n : f args (n + 1)
f (Right expr : args) n = expr : f args n
g (Left arg) = AnonParamExpr (read arg)
g (Right expr) = expr
anonParamFuncExpr :: Parser Expr
anonParamFuncExpr = (AnonParamFuncExpr . read <$> index) <*> (char '#' >> expr)
where
index = (:) <$> satisfy (\c -> '1' <= c && c <= '9') <*> many digit
anonParamExpr :: Parser Expr
anonParamExpr = char '%' >> AnonParamExpr <$> integerLiteral
algebraicDataMatcherExpr :: Parser Expr
algebraicDataMatcherExpr = keywordAlgebraicDataMatcher
>> braces (AlgebraicDataMatcherExpr <$> sepEndBy1 inductivePat' whiteSpace)
where
inductivePat' :: Parser (String, [Expr])
inductivePat' = angles $ (,) <$> lowerName <*> sepEndBy expr whiteSpace
generateTensorExpr :: Parser Expr
generateTensorExpr = keywordGenerateTensor >> GenerateTensorExpr <$> expr <*> expr
tensorExpr :: Parser Expr
tensorExpr = keywordTensor >> TensorExpr <$> expr <*> expr
tensorContractExpr :: Parser Expr
tensorContractExpr = keywordTensorContract >> TensorContractExpr <$> expr
tensorMapExpr :: Parser Expr
tensorMapExpr = keywordTensorMap >> TensorMapExpr <$> expr <*> expr
tensorMap2Expr :: Parser Expr
tensorMap2Expr = keywordTensorMap2 >> TensorMap2Expr <$> expr <*> expr <*> expr
transposeExpr :: Parser Expr
transposeExpr = keywordTranspose >> TransposeExpr <$> expr <*> expr
subrefsExpr :: Parser Expr
subrefsExpr = (keywordSubrefs >> SubrefsExpr False <$> expr <*> expr)
<|> (keywordSubrefsNew >> SubrefsExpr True <$> expr <*> expr)
suprefsExpr :: Parser Expr
suprefsExpr = (keywordSuprefs >> SuprefsExpr False <$> expr <*> expr)
<|> (keywordSuprefsNew >> SuprefsExpr True <$> expr <*> expr)
userrefsExpr :: Parser Expr
userrefsExpr = (keywordUserrefs >> UserrefsExpr False <$> expr <*> expr)
<|> (keywordUserrefsNew >> UserrefsExpr True <$> expr <*> expr)
-- Patterns
pattern :: Parser Pattern
pattern = P.lexeme lexer (do pattern <- pattern'
option pattern $ IndexedPat pattern <$> many1 (try $ char '_' >> expr'))
pattern' :: Parser Pattern
pattern' = wildCard
<|> contPat
<|> patVar
<|> varPat
<|> valuePat
<|> predPat
<|> notPat
<|> tuplePat
<|> inductivePat
<|> laterPatVar
<|> try seqNilPat
<|> try seqConsPat
<|> try seqPat
<|> parens (andPat
<|> notPat'
<|> orPat
<|> loopPat
<|> letPat
<|> try dApplyPat
<|> try pApplyPat
)
pattern'' :: Parser Pattern
pattern'' = wildCard
<|> patVar
<|> valuePat
wildCard :: Parser Pattern
wildCard = reservedOp "_" >> pure WildCard
patVar :: Parser Pattern
patVar = char '$' >> PatVar <$> ident
varPat :: Parser Pattern
varPat = VarPat <$> ident
valuePat :: Parser Pattern
valuePat = char ',' >> ValuePat <$> expr
predPat :: Parser Pattern
predPat = char '?' >> PredPat <$> expr
letPat :: Parser Pattern
letPat = keywordLet >> LetPat <$> bindings <*> pattern
notPat :: Parser Pattern
notPat = char '!' >> NotPat <$> pattern
notPat' :: Parser Pattern
notPat' = keywordNot >> NotPat <$> pattern
tuplePat :: Parser Pattern
tuplePat = brackets $ TuplePat <$> sepEndBy pattern whiteSpace
inductivePat :: Parser Pattern
inductivePat = angles $ InductivePat <$> lowerName <*> sepEndBy pattern whiteSpace
contPat :: Parser Pattern
contPat = keywordCont >> pure ContPat
andPat :: Parser Pattern
andPat = do
pats <- (reservedOp "&" <|> keywordAnd) >> sepEndBy pattern whiteSpace
case pats of
[] -> return WildCard
_ -> return $ foldr1 AndPat pats
orPat :: Parser Pattern
orPat = do
pats <- (reservedOp "|" <|> keywordOr) >> sepEndBy pattern whiteSpace
case pats of
[] -> return (NotPat WildCard)
_ -> return $ foldr1 OrPat pats
pApplyPat :: Parser Pattern
pApplyPat = PApplyPat <$> expr <*> sepEndBy pattern whiteSpace
dApplyPat :: Parser Pattern
dApplyPat = DApplyPat <$> pattern'' <*> sepEndBy pattern whiteSpace
loopPat :: Parser Pattern
loopPat = keywordLoop >> char '$' >> LoopPat <$> ident <*> loopRange <*> pattern <*> option (NotPat WildCard) pattern
loopRange :: Parser LoopRange
loopRange = brackets (try (LoopRange <$> expr <*> expr <*> option WildCard pattern)
<|> (do s <- expr
ep <- option WildCard pattern
return (LoopRange s (makeApply "from" [makeApply "-'" [s, ConstantExpr (IntegerExpr 1)]]) ep)))
seqNilPat :: Parser Pattern
seqNilPat = braces $ pure SeqNilPat
seqConsPat :: Parser Pattern
seqConsPat = braces $ SeqConsPat <$> pattern <*> (char '@' >> pattern)
seqPat :: Parser Pattern
seqPat = braces $ do
pats <- sepEndBy pattern whiteSpace
tailPat <- option SeqNilPat (char '@' >> pattern)
return $ foldr SeqConsPat tailPat pats
laterPatVar :: Parser Pattern
laterPatVar = char '#' >> pure LaterPatVar
-- Constants
constantExpr :: Parser ConstantExpr
constantExpr = StringExpr . T.pack <$> stringLiteral
<|> BoolExpr <$> boolLiteral
<|> try (CharExpr <$> oneChar)
<|> try (FloatExpr <$> positiveFloatLiteral)
<|> try (IntegerExpr <$> integerLiteral)
<|> (keywordSomething $> SomethingExpr)
<|> (keywordUndefined $> UndefinedExpr)
<?> "constant"
positiveFloatLiteral :: Parser Double
positiveFloatLiteral = do
n <- integerLiteral
char '.'
mStr <- many1 digit
let m = read mStr
let l = m % (10 ^ fromIntegral (length mStr))
if n < 0 then return (fromRational (fromIntegral n - l) :: Double)
else return (fromRational (fromIntegral n + l) :: Double)
--
-- Tokens
--
egisonDef :: P.GenLanguageDef String () Identity
egisonDef =
P.LanguageDef { P.commentStart = "#|"
, P.commentEnd = "|#"
, P.commentLine = ";"
, P.identStart = letter <|> symbol1 <|> symbol0
, P.identLetter = letter <|> digit <|> symbol2
, P.opStart = symbol1
, P.opLetter = symbol1
, P.reservedNames = reservedKeywords
, P.reservedOpNames = reservedOperators
, P.nestedComments = True
, P.caseSensitive = True }
symbol0 = char '^'
-- Don't allow three consecutive dots to be a part of identifier
symbol1 = oneOf "+-*/=∂∇" <|> try (char '.' <* notFollowedBy (string ".."))
symbol2 = symbol1 <|> oneOf "'!?₀₁₂₃₄₅₆₇₈₉"
lexer :: P.GenTokenParser String () Identity
lexer = P.makeTokenParser egisonDef
reservedKeywords :: [String]
reservedKeywords =
[ "define"
, "set!"
, "test"
, "execute"
, "load-file"
, "load"
, "if"
, "seq"
, "capply"
, "lambda"
, "memoized-lambda"
, "memoize"
, "cambda"
, "pattern-function"
, "letrec"
, "let"
, "let*"
, "with-symbols"
-- , "not"
-- , "and"
-- , "or"
, "loop"
, "match-all"
, "match"
, "match-all-dfs"
, "match-dfs"
, "match-all-lambda"
, "match-lambda"
, "matcher"
, "do"
, "algebraic-data-matcher"
, "generate-tensor"
, "tensor"
, "contract"
, "tensor-map"
, "tensor-map2"
, "transpose"
, "subrefs"
, "subrefs!"
, "suprefs"
, "suprefs!"
, "user-refs"
, "user-refs!"
, "function"
, "something"
, "undefined"]
reservedOperators :: [String]
reservedOperators =
[ "$"
, ",$"
, "_"
, "^"
, "&"
, "|*"
-- , "'"
-- , "~"
-- , "!"
-- , ","
-- , "@"
, "..."]
reserved :: String -> Parser ()
reserved = P.reserved lexer
reservedOp :: String -> Parser ()
reservedOp = P.reservedOp lexer
keywordDefine = reserved "define"
keywordSet = reserved "set!"
keywordTest = reserved "test"
keywordExecute = reserved "execute"
keywordLoadFile = reserved "load-file"
keywordLoad = reserved "load"
keywordIf = reserved "if"
keywordNot = reserved "not"
keywordAnd = reserved "and"
keywordOr = reserved "or"
keywordSeq = reserved "seq"
keywordCApply = reserved "capply"
keywordLambda = reserved "lambda"
keywordMemoizedLambda = reserved "memoized-lambda"
keywordMemoize = reserved "memoize"
keywordCambda = reserved "cambda"
keywordPatternFunction = reserved "pattern-function"
keywordLetRec = reserved "letrec"
keywordLet = reserved "let"
keywordLetStar = reserved "let*"
keywordWithSymbols = reserved "with-symbols"
keywordLoop = reserved "loop"
keywordCont = reserved "..."
keywordMatchAll = reserved "match-all"
keywordMatchAllDFS = reserved "match-all-dfs"
keywordMatchAllLambda = reserved "match-all-lambda"
keywordMatch = reserved "match"
keywordMatchDFS = reserved "match-dfs"
keywordMatchLambda = reserved "match-lambda"
keywordMatcher = reserved "matcher"
keywordDo = reserved "do"
keywordIo = reserved "io"
keywordSomething = reserved "something"
keywordUndefined = reserved "undefined"
keywordAlgebraicDataMatcher = reserved "algebraic-data-matcher"
keywordGenerateTensor = reserved "generate-tensor"
keywordTensor = reserved "tensor"
keywordTensorContract = reserved "contract"
keywordTensorMap = reserved "tensor-map"
keywordTensorMap2 = reserved "tensor-map2"
keywordTranspose = reserved "transpose"
keywordSubrefs = reserved "subrefs"
keywordSubrefsNew = reserved "subrefs!"
keywordSuprefs = reserved "suprefs"
keywordSuprefsNew = reserved "suprefs!"
keywordUserrefs = reserved "user-refs"
keywordUserrefsNew = reserved "user-refs!"
keywordFunction = reserved "function"
sign :: Num a => Parser (a -> a)
sign = (char '-' >> return negate)
<|> (char '+' >> return id)
<|> return id
integerLiteral :: Parser Integer
integerLiteral = sign <*> P.natural lexer
stringLiteral :: Parser String
stringLiteral = P.stringLiteral lexer
charLiteral :: Parser Char
charLiteral = P.charLiteral lexer
oneChar :: Parser Char
oneChar = do
string "c#"
x <- (char '\\' >> anyChar >>= (\x -> return ['\\', x])) <|> (anyChar >>= (\x -> return [x]))
return $ doParse' charLiteral $ "'" ++ x ++ "'"
boolLiteral :: Parser Bool
boolLiteral = char '#' >> (char 't' $> True <|> char 'f' $> False)
whiteSpace :: Parser ()
whiteSpace = P.whiteSpace lexer
parens :: Parser a -> Parser a
parens = P.parens lexer
brackets :: Parser a -> Parser a
brackets = P.brackets lexer
braces :: Parser a -> Parser a
braces = P.braces lexer
angles :: Parser a -> Parser a
angles = P.angles lexer
ident :: Parser String
ident = toCamelCase <$> P.identifier lexer
identVarWithIndices :: Parser VarWithIndices
identVarWithIndices = P.lexeme lexer (do
name <- ident
is <- many indexForVar
return $ VarWithIndices name is)
indexForVar :: Parser VarIndex
indexForVar = try (char '~' >> VSuperscript <$> ident)
<|> try (char '_' >> VSubscript <$> ident)
indexType :: Parser (IndexExpr ())
indexType = try (char '~' >> return (Superscript ()))
<|> try (char '_' >> return (Subscript ()))
upperName :: Parser String
upperName = P.lexeme lexer upperName'
upperName' :: Parser String
upperName' = (:) <$> upper <*> option "" ident
where
upper :: Parser Char
upper = satisfy isUpper
lowerName :: Parser String
lowerName = P.lexeme lexer lowerName'
lowerName' :: Parser String
lowerName' = (:) <$> lower <*> option "" ident
where
lower :: Parser Char
lower = satisfy isLower
renamedFunctions :: [(String, String)]
renamedFunctions =
[ ("empty?", "isEmpty")
, ("S.empty?", "S.isEmpty")
, ("bool?", "isBool")
, ("integer?", "isInteger")
, ("rational?", "isRational")
, ("scalar?", "isScalar")
, ("float?", "isFloat")
, ("char?", "isChar")
, ("string?", "isString")
, ("collection?", "isCollection")
, ("hash?", "isHash")
, ("tensor?", "isTensor")
, ("even?", "isEven")
, ("odd?", "isOdd")
, ("prime?", "isPrime")
, ("eof?", "isEof")
, ("eof-port?", "isEofPort")
, ("alphabet?", "isAlphabet")
, ("C.between?", "C.isBetween")
, ("alphabets?", "isAlphabetString")
, ("include?", "include")
, ("include/m?", "includeAs")
, ("member?", "member")
, ("member/m?", "memberAs")
, ("divisor?", "divisor")
, ("tree-member?","treeMember")
, ("eq/m?", "eqAs")
, ("eq?", "equal")
, ("lt?", "lt")
, ("lte?", "lte")
, ("gt?", "gt")
, ("gte?", "gte")
, ("car", "head")
, ("cdr", "tail")
, ("rac", "last")
, ("rdc", "init")
]
-- Translate identifiers for Non-S syntax
toCamelCase :: String -> String
toCamelCase "-'" = "-'"
toCamelCase "f.-'" = "f.-'"
toCamelCase "b.." = "b."
toCamelCase "b..'" = "b.'"
toCamelCase (flip lookup renamedFunctions -> Just name') =
name'
toCamelCase (reverse -> 'm':'/':xs) =
toCamelCase (reverse xs ++ "-as")
toCamelCase x =
let heads:tails = splitOn "-" x
in concat $ heads : map capitalize tails
where
capitalize [] = "-"
capitalize (x:xs) = toUpper x : xs