summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPéter Diviánszky <divipp@gmail.com>2016-09-16 14:21:13 +0200
committerPéter Diviánszky <divipp@gmail.com>2016-09-16 14:21:13 +0200
commit6cfd368e594aaca8579acbb700f7c1a4302f280a (patch)
treecc002e0327ff5a5eca34a8aa428415147794fb55
parente3bf90b0ba18b5dcaa7e166efb5d270301608aeb (diff)
use megaparsec 5.0
-rw-r--r--lambdacube-compiler.cabal8
-rw-r--r--src/LambdaCube/Compiler/Lexer.hs35
-rw-r--r--src/LambdaCube/Compiler/Parser.hs1
-rw-r--r--src/LambdaCube/Compiler/Utils.hs8
-rw-r--r--test/UnitTests.hs8
5 files changed, 40 insertions, 20 deletions
diff --git a/lambdacube-compiler.cabal b/lambdacube-compiler.cabal
index c0de68a1..0eb3868c 100644
--- a/lambdacube-compiler.cabal
+++ b/lambdacube-compiler.cabal
@@ -83,7 +83,7 @@ library
83 exceptions >= 0.8 && <0.9, 83 exceptions >= 0.8 && <0.9,
84 filepath >=1.4 && <1.5, 84 filepath >=1.4 && <1.5,
85 mtl >=2.2 && <2.3, 85 mtl >=2.2 && <2.3,
86 megaparsec >= 4.4.0 && <4.5, 86 megaparsec >=5.0 && <5.1,
87 ansi-wl-pprint >=0.6 && <0.7, 87 ansi-wl-pprint >=0.6 && <0.7,
88 pretty-show >= 1.6.9, 88 pretty-show >= 1.6.9,
89 text >= 1.2 && <1.3, 89 text >= 1.2 && <1.3,
@@ -107,7 +107,7 @@ executable lambdacube-compiler-unit-tests
107 base < 4.10, 107 base < 4.10,
108 containers >=0.5 && <0.6, 108 containers >=0.5 && <0.6,
109 lambdacube-compiler, 109 lambdacube-compiler,
110 megaparsec >= 4.3.0 && <4.5, 110 megaparsec >=5.0 && <5.1,
111 QuickCheck >= 2.8.2 && <2.10, 111 QuickCheck >= 2.8.2 && <2.10,
112 tasty >= 0.11 && <0.12, 112 tasty >= 0.11 && <0.12,
113 tasty-quickcheck >=0.8 && <0.9 113 tasty-quickcheck >=0.8 && <0.9
@@ -136,7 +136,7 @@ executable lambdacube-compiler-test-suite
136 mtl >=2.2 && <2.3, 136 mtl >=2.2 && <2.3,
137 monad-control >= 1.0 && <1.1, 137 monad-control >= 1.0 && <1.1,
138 optparse-applicative >=0.12 && <0.14, 138 optparse-applicative >=0.12 && <0.14,
139 megaparsec >= 4.3.0 && <4.5, 139 megaparsec >=5.0 && <5.1,
140 ansi-wl-pprint >=0.6 && <0.7, 140 ansi-wl-pprint >=0.6 && <0.7,
141 patience >= 0.1 && < 0.2, 141 patience >= 0.1 && < 0.2,
142 text >= 1.2 && <1.3, 142 text >= 1.2 && <1.3,
@@ -244,7 +244,7 @@ executable lambdacube-compiler-coverage-test-suite
244 mtl >=2.2 && <2.3, 244 mtl >=2.2 && <2.3,
245 monad-control >= 1.0 && <1.1, 245 monad-control >= 1.0 && <1.1,
246 optparse-applicative >=0.12 && <0.14, 246 optparse-applicative >=0.12 && <0.14,
247 megaparsec >= 4.3.0 && <4.5, 247 megaparsec >=5.0 && <5.1,
248 ansi-wl-pprint >=0.6 && <0.7, 248 ansi-wl-pprint >=0.6 && <0.7,
249 pretty-show >= 1.6.9, 249 pretty-show >= 1.6.9,
250 patience >= 0.1 && < 0.2, 250 patience >= 0.1 && < 0.2,
diff --git a/src/LambdaCube/Compiler/Lexer.hs b/src/LambdaCube/Compiler/Lexer.hs
index 2b7f8cda..66179853 100644
--- a/src/LambdaCube/Compiler/Lexer.hs
+++ b/src/LambdaCube/Compiler/Lexer.hs
@@ -6,22 +6,25 @@
6{-# LANGUAGE UndecidableInstances #-} 6{-# LANGUAGE UndecidableInstances #-}
7{-# LANGUAGE MultiParamTypeClasses #-} 7{-# LANGUAGE MultiParamTypeClasses #-}
8{-# LANGUAGE NoMonomorphismRestriction #-} 8{-# LANGUAGE NoMonomorphismRestriction #-}
9{-# LANGUAGE OverloadedStrings #-} 9{-# LANGUAGE TypeFamilies #-}
10{-# LANGUAGE RankNTypes #-}
10module LambdaCube.Compiler.Lexer 11module LambdaCube.Compiler.Lexer
11 ( module LambdaCube.Compiler.Lexer 12 ( module LambdaCube.Compiler.Lexer
12 , module ParseUtils 13 , module ParseUtils
13 ) where 14 ) where
14 15
15import Data.List 16import Data.List
17import Data.List.NonEmpty (fromList)
16import Data.Char 18import Data.Char
17import qualified Data.Set as Set 19import qualified Data.Set as Set
18import Control.Monad.Except 20import Control.Monad.Except
19import Control.Monad.RWS 21import Control.Monad.RWS
20import Control.Applicative 22import Control.Applicative
23import Control.Arrow
21 24
22import Text.Megaparsec hiding (State) 25import Text.Megaparsec hiding (State, ParseError)
23import qualified Text.Megaparsec as P 26import qualified Text.Megaparsec as P
24import Text.Megaparsec as ParseUtils hiding (try, Message, State) 27import Text.Megaparsec as ParseUtils hiding (try, Message, State, ParseError)
25import Text.Megaparsec.Lexer hiding (lexeme, symbol, negate) 28import Text.Megaparsec.Lexer hiding (lexeme, symbol, negate)
26 29
27import LambdaCube.Compiler.Pretty hiding (parens) 30import LambdaCube.Compiler.Pretty hiding (parens)
@@ -34,19 +37,21 @@ import LambdaCube.Compiler.DesugaredSource
34try_ s m = try m <?> s 37try_ s m = try m <?> s
35 38
36toSPos :: SourcePos -> SPos 39toSPos :: SourcePos -> SPos
37toSPos p = SPos (sourceLine p) (sourceColumn p) 40toSPos p = SPos (fromIntegral $ unPos $ sourceLine p) (fromIntegral $ unPos $ sourceColumn p)
38 41
39getSPos = toSPos <$> getPosition 42getSPos = toSPos <$> getPosition
40 43
41-------------------------------------------------------------------------------- literals 44-------------------------------------------------------------------------------- literals
42 45
43parseLit :: Parse r w Lit 46parseLit :: forall r w . Parse r w Lit
44parseLit = lexeme (LChar <$> charLiteral <|> LString <$> stringLiteral <|> natFloat) <?> "literal" 47parseLit = lexeme (LChar <$> charLiteral <|> LString <$> stringLiteral <|> natFloat) <?> "literal"
45 where 48 where
49 charLiteral :: Parse r w Char
46 charLiteral = between (char '\'') 50 charLiteral = between (char '\'')
47 (char '\'' <?> "end of character") 51 (char '\'' <?> "end of character")
48 (char '\\' *> escapeCode <|> satisfy ((&&) <$> (> '\026') <*> (/= '\'')) <?> "character") 52 (char '\\' *> escapeCode <|> satisfy ((&&) <$> (> '\026') <*> (/= '\'')) <?> "character")
49 53
54 stringLiteral :: Parse r w String
50 stringLiteral = between (char '"') 55 stringLiteral = between (char '"')
51 (char '"' <?> "end of string") 56 (char '"' <?> "end of string")
52 (concat <$> many stringChar) 57 (concat <$> many stringChar)
@@ -57,6 +62,7 @@ parseLit = lexeme (LChar <$> charLiteral <|> LString <$> stringLiteral <|> natFl
57 <|> [] <$ char '&' 62 <|> [] <$ char '&'
58 <|> (:[]) <$> escapeCode 63 <|> (:[]) <$> escapeCode
59 64
65 escapeCode :: Parse r w Char
60 escapeCode = choice (charEsc ++ charNum: (char '^' *> charControl): charAscii) <?> "escape code" 66 escapeCode = choice (charEsc ++ charNum: (char '^' *> charControl): charAscii) <?> "escape code"
61 where 67 where
62 charControl = toEnum . (+ (-64)) . fromEnum <$> satisfy ((&&) <$> (>= 'A') <*> (<= '_')) <?> "control char" 68 charControl = toEnum . (+ (-64)) . fromEnum <$> satisfy ((&&) <$> (>= 'A') <*> (<= '_')) <?> "control char"
@@ -73,6 +79,7 @@ parseLit = lexeme (LChar <$> charLiteral <|> LString <$> stringLiteral <|> natFl
73 -- \a \b \t \n \v \f \r ' ' 79 -- \a \b \t \n \v \f \r ' '
74 y = toEnum <$> ([0..32] ++ [127]) 80 y = toEnum <$> ([0..32] ++ [127])
75 81
82 natFloat :: Parse r w Lit
76 natFloat = char '0' *> zeroNumFloat <|> decimalFloat 83 natFloat = char '0' *> zeroNumFloat <|> decimalFloat
77 where 84 where
78 zeroNumFloat = LInt <$> (oneOf "xX" *> hexadecimal <|> oneOf "oO" *> octal) 85 zeroNumFloat = LInt <$> (oneOf "xX" *> hexadecimal <|> oneOf "oO" *> octal)
@@ -105,13 +112,18 @@ data ParseEnv r = ParseEnv
105type ParseState r = (ParseEnv r, P.State String) 112type ParseState r = (ParseEnv r, P.State String)
106 113
107parseState :: FileInfo -> r -> ParseState r 114parseState :: FileInfo -> r -> ParseState r
108parseState fi di = (ParseEnv fi di ExpNS (SPos 0 0), either (error "impossible") id $ runParser getParserState (filePath fi) (fileContent fi)) 115parseState fi di = (ParseEnv fi di ExpNS (SPos 0 0), either (error "impossible") id $ runParser (getParserState :: Parsec Dec String (P.State String)) (filePath fi) (fileContent fi))
109 116
110--type Parse r w = ReaderT (ParseEnv r) (WriterT [w] (StateT SPos (Parsec String))) 117--type Parse r w = ReaderT (ParseEnv r) (WriterT [w] (StateT SPos (Parsec String)))
111type Parse r w = RWST (ParseEnv r) [w] SPos (Parsec String) 118type Parse r w = RWST (ParseEnv r) [w] SPos (Parsec Dec String)
119
120newtype ParseError = ParseErr (P.ParseError (Token String) Dec)
121
122instance Show ParseError where
123 show (ParseErr e) = parseErrorPretty e
112 124
113runParse :: Parse r w a -> ParseState r -> Either ParseError (a, [w]) 125runParse :: Parse r w a -> ParseState r -> Either ParseError (a, [w])
114runParse p (env, st) = snd . flip runParser' st $ evalRWST p env (error "spos") 126runParse p (env, st) = left ParseErr . snd . flip runParser' st $ evalRWST p env (error "spos")
115 127
116getParseState :: Parse r w (ParseState r) 128getParseState :: Parse r w (ParseState r)
117getParseState = (,) <$> ask <*> getParserState 129getParseState = (,) <$> ask <*> getParserState
@@ -154,6 +166,7 @@ noSpaceBefore p = try $ do
154 166
155lexeme_ p = lexemeWithoutSpace p <* whiteSpace 167lexeme_ p = lexemeWithoutSpace p <* whiteSpace
156 168
169lexeme :: Parse r w a -> Parse r w a
157lexeme p = snd <$> lexeme_ p 170lexeme p = snd <$> lexeme_ p
158 171
159lexemeName p = uncurry SIName <$> lexeme_ p 172lexemeName p = uncurry SIName <$> lexeme_ p
@@ -214,6 +227,7 @@ opLetter = lowercaseOpLetter <|> char ':'
214 227
215maybeStartWith p i = i <|> (:) <$> satisfy p <*> i 228maybeStartWith p i = i <|> (:) <$> satisfy p <*> i
216 229
230upperCase, upperCase_, lowerCase :: Parse r w SIName
217upperCase = identifier (tick =<< (:) <$> upperLetter <*> many identLetter) <?> "uppercase ident" 231upperCase = identifier (tick =<< (:) <$> upperLetter <*> many identLetter) <?> "uppercase ident"
218upperCase_ = identifier (tick =<< maybeStartWith (=='\'') ((:) <$> upperLetter <*> many identLetter)) <?> "uppercase ident" 232upperCase_ = identifier (tick =<< maybeStartWith (=='\'') ((:) <$> upperLetter <*> many identLetter)) <?> "uppercase ident"
219lowerCase = identifier ((:) <$> lowerLetter <*> many identLetter) <?> "lowercase ident" 233lowerCase = identifier ((:) <$> lowerLetter <*> many identLetter) <?> "lowercase ident"
@@ -237,10 +251,13 @@ reservedOp name = fst <$> lexeme_ (try $ string name *> notFollowedBy opLetter)
237 251
238reserved name = fst <$> lexeme_ (try $ string name *> notFollowedBy identLetter) 252reserved name = fst <$> lexeme_ (try $ string name *> notFollowedBy identLetter)
239 253
240expect msg p i = i >>= \n -> if p n then unexpected (msg ++ " " ++ show n) else return n 254expect :: String -> (String -> Bool) -> Parse r w String -> Parse r w String
255expect msg p i = i >>= \n -> if p n then unexpected (Tokens $ fromList n) else return n
241 256
257identifier :: Parse r w String -> Parse r w SIName
242identifier name = lexemeName $ try $ expect "reserved word" (`Set.member` theReservedNames) name 258identifier name = lexemeName $ try $ expect "reserved word" (`Set.member` theReservedNames) name
243 259
260operator :: Parse r w String -> Parse r w SIName
244operator name = lexemeName $ try $ expect "reserved operator" (`Set.member` theReservedOpNames) name 261operator name = lexemeName $ try $ expect "reserved operator" (`Set.member` theReservedOpNames) name
245 262
246theReservedOpNames = Set.fromList ["::","..","=","\\","|","<-","->","@","~","=>"] 263theReservedOpNames = Set.fromList ["::","..","=","\\","|","<-","->","@","~","=>"]
diff --git a/src/LambdaCube/Compiler/Parser.hs b/src/LambdaCube/Compiler/Parser.hs
index db059fcb..8db4b855 100644
--- a/src/LambdaCube/Compiler/Parser.hs
+++ b/src/LambdaCube/Compiler/Parser.hs
@@ -7,6 +7,7 @@
7{-# LANGUAGE OverloadedStrings #-} 7{-# LANGUAGE OverloadedStrings #-}
8{-# LANGUAGE DeriveFunctor #-} 8{-# LANGUAGE DeriveFunctor #-}
9{-# LANGUAGE ScopedTypeVariables #-} 9{-# LANGUAGE ScopedTypeVariables #-}
10{-# LANGUAGE TypeFamilies #-}
10module LambdaCube.Compiler.Parser 11module LambdaCube.Compiler.Parser
11 ( parseLC 12 ( parseLC
12 , runDefParser 13 , runDefParser
diff --git a/src/LambdaCube/Compiler/Utils.hs b/src/LambdaCube/Compiler/Utils.hs
index 5ec3815c..2834497b 100644
--- a/src/LambdaCube/Compiler/Utils.hs
+++ b/src/LambdaCube/Compiler/Utils.hs
@@ -115,8 +115,9 @@ instance MonadMask m => MonadMask (ExceptT e m) where
115 mask f = ExceptT $ mask $ \u -> runExceptT $ f (mapExceptT u) 115 mask f = ExceptT $ mask $ \u -> runExceptT $ f (mapExceptT u)
116 uninterruptibleMask = error "not implemented: uninterruptibleMask for ExcpetT" 116 uninterruptibleMask = error "not implemented: uninterruptibleMask for ExcpetT"
117-} 117-}
118instance (Monoid w, P.MonadParsec st m t) => P.MonadParsec st (RWST r w s m) t where 118
119 failure = lift . P.failure 119instance (Monoid w, P.MonadParsec e s m) => P.MonadParsec e s (RWST r w st m) where
120 failure a b = lift . P.failure a b
120 label = mapRWST . P.label 121 label = mapRWST . P.label
121 try = mapRWST P.try 122 try = mapRWST P.try
122 lookAhead (RWST m) = RWST $ \r s -> (\(a, _, _) -> (a, s, mempty)) <$> P.lookAhead (m r s) 123 lookAhead (RWST m) = RWST $ \r s -> (\(a, _, _) -> (a, s, mempty)) <$> P.lookAhead (m r s)
@@ -124,8 +125,7 @@ instance (Monoid w, P.MonadParsec st m t) => P.MonadParsec st (RWST r w s m) t w
124 withRecovery rec (RWST m) = RWST $ \r s -> P.withRecovery (\e -> runRWST (rec e) r s) (m r s) 125 withRecovery rec (RWST m) = RWST $ \r s -> P.withRecovery (\e -> runRWST (rec e) r s) (m r s)
125 eof = lift P.eof 126 eof = lift P.eof
126 token f e = lift $ P.token f e 127 token f e = lift $ P.token f e
127 tokens f e ts = lift $ P.tokens f e ts 128 tokens f e = lift $ P.tokens f e
128 getParserState = lift P.getParserState 129 getParserState = lift P.getParserState
129 updateParserState f = lift $ P.updateParserState f 130 updateParserState f = lift $ P.updateParserState f
130 131
131
diff --git a/test/UnitTests.hs b/test/UnitTests.hs
index 56b7f3b1..52569f48 100644
--- a/test/UnitTests.hs
+++ b/test/UnitTests.hs
@@ -2,7 +2,7 @@
2module Main where 2module Main where
3 3
4import Data.Monoid 4import Data.Monoid
5import Text.Megaparsec.Pos (SourcePos(..), newPos, sourceName, sourceLine, sourceColumn) 5import Text.Megaparsec.Pos (Pos, unsafePos, SourcePos(..), sourceName, sourceLine, sourceColumn)
6import qualified Data.Map as Map 6import qualified Data.Map as Map
7import qualified Data.Set as Set 7import qualified Data.Set as Set
8 8
@@ -28,12 +28,14 @@ main = defaultMain $ testGroup "Compiler"
28----------------------------------------------------------------- Arbitraries 28----------------------------------------------------------------- Arbitraries
29 29
30-- SourcePos 30-- SourcePos
31instance Arbitrary Pos where
32 arbitrary = unsafePos . getPositive <$> arbitrary
31 33
32instance Arbitrary SourcePos where 34instance Arbitrary SourcePos where
33 arbitrary = newPos <$> arbitrary <*> (getPositive <$> arbitrary) <*> (getPositive <$> arbitrary) 35 arbitrary = SourcePos <$> arbitrary <*> arbitrary <*> arbitrary
34 shrink pos 36 shrink pos
35 | n <- sourceName pos, l <- sourceLine pos, c <- sourceColumn pos 37 | n <- sourceName pos, l <- sourceLine pos, c <- sourceColumn pos
36 = [newPos n' l' c' | n' <- shrink n, l' <- shrink l, c' <- shrink c] 38 = [SourcePos n' l' c' | n' <- shrink n, l' <- shrink l, c' <- shrink c]
37 -- TODO: Diagonalize shrink 39 -- TODO: Diagonalize shrink
38 40
39-- TODO: generate only valid positions 41-- TODO: generate only valid positions