52 lines
1.7 KiB
Haskell
52 lines
1.7 KiB
Haskell
module Parse.Parser (parseProgram, preParse) where
|
|
|
|
import Ast
|
|
import Control.Applicative ((<$>), (<*>))
|
|
import Control.Monad
|
|
import Data.Char (isSymbol, isDigit)
|
|
import Data.List (foldl',intercalate)
|
|
import Text.Parsec hiding (newline,spaces)
|
|
|
|
import Parse.Library
|
|
import Parse.Expr
|
|
import Parse.Types
|
|
import Parse.Modules
|
|
import Parse.Foreign
|
|
|
|
|
|
statement = choice (typeAlias:defs) <|> def <?> "datatype or variable definition"
|
|
where defs = map ((:[]) <$>) [ foreignDef, datatype, typeAnnotation ]
|
|
|
|
freshDef = commitIf (freshLine >> (letter <|> char '_')) $ do
|
|
freshLine
|
|
statement <?> "another datatype or variable definition"
|
|
|
|
defs1 = do d <- statement <?> "at least one datatype or variable definition"
|
|
concat <$> (d:) <$> many freshDef
|
|
|
|
program = do
|
|
optional freshLine
|
|
(names,exports) <- option (["Main"],[]) (moduleDef `followedBy` freshLine)
|
|
is <- (do try (lookAhead $ reserved "import")
|
|
imports `followedBy` freshLine) <|> return []
|
|
statements <- defs1
|
|
optional freshLine ; optional spaces ; eof
|
|
return $ Module names exports is statements
|
|
|
|
parseProgram = setupParser program
|
|
|
|
preParse :: String -> Either String (String, [String])
|
|
preParse = setupParser $ do
|
|
optional skip
|
|
(,) <$> option "Main" moduleName <*> option [] imprts
|
|
where
|
|
skip = try (manyTill anyChar (try (string "/**")))
|
|
imprts = fmap (map fst) imports `followedBy` freshLine
|
|
getName = intercalate "." . fst
|
|
moduleName = do optional freshLine
|
|
getName <$> moduleDef `followedBy` freshLine
|
|
|
|
setupParser p source =
|
|
case iParse p "" source of
|
|
Right result -> Right result
|
|
Left err -> Left $ "Parse error at " ++ show err
|