@@ -4,11 +4,13 @@ import Control.Applicative ((<$>), (<*>))
4import Control.Monad
4import Control.Monad
5import Data.Char (isSymbol, isDigit)
5import Data.Char (isSymbol, isDigit)
6import Data.List (foldl',intercalate)
6import Data.List (foldl',intercalate)
7+import qualified Data.Map as Map
7import Text.Parsec hiding (newline,spaces)
8import Text.Parsec hiding (newline,spaces)
8import qualified Text.PrettyPrint as P
9import qualified Text.PrettyPrint as P
10import qualified SourceSyntax.Module as S
11import qualified SourceSyntax.Module as S
11import Parse.Helpers
12import Parse.Helpers
13+import Parse.Binop (infixStmt, OpTable)
12import Parse.Expression
14import Parse.Expression
13import Parse.Type
15import Parse.Type
14import Parse.Module
16import Parse.Module
@@ -21,8 +23,8 @@ freshDef = commitIf (freshLine >> (letter <|> char '_')) $ do
21decls = do d <- Decl.declaration <?> "at least one datatype or variable definition"
23decls = do d <- Decl.declaration <?> "at least one datatype or variable definition"
22 (d:) <$> many freshDef
24 (d:) <$> many freshDef
24−program :: String -> Either [P.Doc] (S.Module t v)
26+program :: OpTable -> String -> Either [P.Doc] (S.Module t v)
25−program = setupParser $ do
27+program table = setupParserWithTable table $ do
26 optional freshLine
28 optional freshLine
27 (names,exports) <- option (["Main"],[]) (moduleDef `followedBy` freshLine)
29 (names,exports) <- option (["Main"],[]) (moduleDef `followedBy` freshLine)
28 is <- (do try (lookAhead $ reserved "import")
30 is <- (do try (lookAhead $ reserved "import")
@@ -39,6 +41,40 @@ dependencies =
39 (,) <$> option "Main" (getName <$> moduleDef `followedBy` freshLine)
41 (,) <$> option "Main" (getName <$> moduleDef `followedBy` freshLine)
40 <*> option [] (map fst <$> imports `followedBy` freshLine)
42 <*> option [] (map fst <$> imports `followedBy` freshLine)
44+setupParserWithTable :: OpTable -> IParser a -> String -> Either [P.Doc] a
45+setupParserWithTable table p source =
46+ do localTable <- setupParser parseFixities source
47+ case Map.intersection table localTable of
48+ overlap | not (Map.null overlap) -> Left [ msg overlap ]
50+ flip setupParser source $ do
51+ putState (Map.union table localTable)
55+ P.vcat [ P.text "Parse error:"
56+ , P.text $ "Overlapping definitions for infix operators: " ++
57+ intercalate " " (Map.keys overlap)
60+parseFixities = infixes []
62+ nil p = const () <$> p
63+ manyTil p end = end <|> (p >> manyTil p end)
65+ eatLine = manyTil (nil multiComment <|> nil anyChar)
66+ (const False <$> simpleNewline <|> const True <$> eof)
69+ next <- Left <$> infixStmt <|> Right <$> eatLine
71+ Left stmt -> infixes (stmt:stmts)
72+ Right True -> return $ format stmts
73+ Right False -> infixes stmts
75+ format = Map.fromList . map (\(lvl,assoc,op) -> (op, (lvl,assoc)))
42setupParser :: IParser a -> String -> Either [P.Doc] a
78setupParser :: IParser a -> String -> Either [P.Doc] a
43setupParser p source =
79setupParser p source =
44 case iParse p source of
80 case iParse p source of