diff options
author | Péter Diviánszky <divipp@gmail.com> | 2016-09-16 14:21:13 +0200 |
---|---|---|
committer | Péter Diviánszky <divipp@gmail.com> | 2016-09-16 14:21:13 +0200 |
commit | 6cfd368e594aaca8579acbb700f7c1a4302f280a (patch) | |
tree | cc002e0327ff5a5eca34a8aa428415147794fb55 | |
parent | e3bf90b0ba18b5dcaa7e166efb5d270301608aeb (diff) |
use megaparsec 5.0
-rw-r--r-- | lambdacube-compiler.cabal | 8 | ||||
-rw-r--r-- | src/LambdaCube/Compiler/Lexer.hs | 35 | ||||
-rw-r--r-- | src/LambdaCube/Compiler/Parser.hs | 1 | ||||
-rw-r--r-- | src/LambdaCube/Compiler/Utils.hs | 8 | ||||
-rw-r--r-- | test/UnitTests.hs | 8 |
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 #-} | ||
10 | module LambdaCube.Compiler.Lexer | 11 | module 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 | ||
15 | import Data.List | 16 | import Data.List |
17 | import Data.List.NonEmpty (fromList) | ||
16 | import Data.Char | 18 | import Data.Char |
17 | import qualified Data.Set as Set | 19 | import qualified Data.Set as Set |
18 | import Control.Monad.Except | 20 | import Control.Monad.Except |
19 | import Control.Monad.RWS | 21 | import Control.Monad.RWS |
20 | import Control.Applicative | 22 | import Control.Applicative |
23 | import Control.Arrow | ||
21 | 24 | ||
22 | import Text.Megaparsec hiding (State) | 25 | import Text.Megaparsec hiding (State, ParseError) |
23 | import qualified Text.Megaparsec as P | 26 | import qualified Text.Megaparsec as P |
24 | import Text.Megaparsec as ParseUtils hiding (try, Message, State) | 27 | import Text.Megaparsec as ParseUtils hiding (try, Message, State, ParseError) |
25 | import Text.Megaparsec.Lexer hiding (lexeme, symbol, negate) | 28 | import Text.Megaparsec.Lexer hiding (lexeme, symbol, negate) |
26 | 29 | ||
27 | import LambdaCube.Compiler.Pretty hiding (parens) | 30 | import LambdaCube.Compiler.Pretty hiding (parens) |
@@ -34,19 +37,21 @@ import LambdaCube.Compiler.DesugaredSource | |||
34 | try_ s m = try m <?> s | 37 | try_ s m = try m <?> s |
35 | 38 | ||
36 | toSPos :: SourcePos -> SPos | 39 | toSPos :: SourcePos -> SPos |
37 | toSPos p = SPos (sourceLine p) (sourceColumn p) | 40 | toSPos p = SPos (fromIntegral $ unPos $ sourceLine p) (fromIntegral $ unPos $ sourceColumn p) |
38 | 41 | ||
39 | getSPos = toSPos <$> getPosition | 42 | getSPos = toSPos <$> getPosition |
40 | 43 | ||
41 | -------------------------------------------------------------------------------- literals | 44 | -------------------------------------------------------------------------------- literals |
42 | 45 | ||
43 | parseLit :: Parse r w Lit | 46 | parseLit :: forall r w . Parse r w Lit |
44 | parseLit = lexeme (LChar <$> charLiteral <|> LString <$> stringLiteral <|> natFloat) <?> "literal" | 47 | parseLit = 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 | |||
105 | type ParseState r = (ParseEnv r, P.State String) | 112 | type ParseState r = (ParseEnv r, P.State String) |
106 | 113 | ||
107 | parseState :: FileInfo -> r -> ParseState r | 114 | parseState :: FileInfo -> r -> ParseState r |
108 | parseState fi di = (ParseEnv fi di ExpNS (SPos 0 0), either (error "impossible") id $ runParser getParserState (filePath fi) (fileContent fi)) | 115 | parseState 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))) |
111 | type Parse r w = RWST (ParseEnv r) [w] SPos (Parsec String) | 118 | type Parse r w = RWST (ParseEnv r) [w] SPos (Parsec Dec String) |
119 | |||
120 | newtype ParseError = ParseErr (P.ParseError (Token String) Dec) | ||
121 | |||
122 | instance Show ParseError where | ||
123 | show (ParseErr e) = parseErrorPretty e | ||
112 | 124 | ||
113 | runParse :: Parse r w a -> ParseState r -> Either ParseError (a, [w]) | 125 | runParse :: Parse r w a -> ParseState r -> Either ParseError (a, [w]) |
114 | runParse p (env, st) = snd . flip runParser' st $ evalRWST p env (error "spos") | 126 | runParse p (env, st) = left ParseErr . snd . flip runParser' st $ evalRWST p env (error "spos") |
115 | 127 | ||
116 | getParseState :: Parse r w (ParseState r) | 128 | getParseState :: Parse r w (ParseState r) |
117 | getParseState = (,) <$> ask <*> getParserState | 129 | getParseState = (,) <$> ask <*> getParserState |
@@ -154,6 +166,7 @@ noSpaceBefore p = try $ do | |||
154 | 166 | ||
155 | lexeme_ p = lexemeWithoutSpace p <* whiteSpace | 167 | lexeme_ p = lexemeWithoutSpace p <* whiteSpace |
156 | 168 | ||
169 | lexeme :: Parse r w a -> Parse r w a | ||
157 | lexeme p = snd <$> lexeme_ p | 170 | lexeme p = snd <$> lexeme_ p |
158 | 171 | ||
159 | lexemeName p = uncurry SIName <$> lexeme_ p | 172 | lexemeName p = uncurry SIName <$> lexeme_ p |
@@ -214,6 +227,7 @@ opLetter = lowercaseOpLetter <|> char ':' | |||
214 | 227 | ||
215 | maybeStartWith p i = i <|> (:) <$> satisfy p <*> i | 228 | maybeStartWith p i = i <|> (:) <$> satisfy p <*> i |
216 | 229 | ||
230 | upperCase, upperCase_, lowerCase :: Parse r w SIName | ||
217 | upperCase = identifier (tick =<< (:) <$> upperLetter <*> many identLetter) <?> "uppercase ident" | 231 | upperCase = identifier (tick =<< (:) <$> upperLetter <*> many identLetter) <?> "uppercase ident" |
218 | upperCase_ = identifier (tick =<< maybeStartWith (=='\'') ((:) <$> upperLetter <*> many identLetter)) <?> "uppercase ident" | 232 | upperCase_ = identifier (tick =<< maybeStartWith (=='\'') ((:) <$> upperLetter <*> many identLetter)) <?> "uppercase ident" |
219 | lowerCase = identifier ((:) <$> lowerLetter <*> many identLetter) <?> "lowercase ident" | 233 | lowerCase = identifier ((:) <$> lowerLetter <*> many identLetter) <?> "lowercase ident" |
@@ -237,10 +251,13 @@ reservedOp name = fst <$> lexeme_ (try $ string name *> notFollowedBy opLetter) | |||
237 | 251 | ||
238 | reserved name = fst <$> lexeme_ (try $ string name *> notFollowedBy identLetter) | 252 | reserved name = fst <$> lexeme_ (try $ string name *> notFollowedBy identLetter) |
239 | 253 | ||
240 | expect msg p i = i >>= \n -> if p n then unexpected (msg ++ " " ++ show n) else return n | 254 | expect :: String -> (String -> Bool) -> Parse r w String -> Parse r w String |
255 | expect msg p i = i >>= \n -> if p n then unexpected (Tokens $ fromList n) else return n | ||
241 | 256 | ||
257 | identifier :: Parse r w String -> Parse r w SIName | ||
242 | identifier name = lexemeName $ try $ expect "reserved word" (`Set.member` theReservedNames) name | 258 | identifier name = lexemeName $ try $ expect "reserved word" (`Set.member` theReservedNames) name |
243 | 259 | ||
260 | operator :: Parse r w String -> Parse r w SIName | ||
244 | operator name = lexemeName $ try $ expect "reserved operator" (`Set.member` theReservedOpNames) name | 261 | operator name = lexemeName $ try $ expect "reserved operator" (`Set.member` theReservedOpNames) name |
245 | 262 | ||
246 | theReservedOpNames = Set.fromList ["::","..","=","\\","|","<-","->","@","~","=>"] | 263 | theReservedOpNames = 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 #-} | ||
10 | module LambdaCube.Compiler.Parser | 11 | module 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 | -} |
118 | instance (Monoid w, P.MonadParsec st m t) => P.MonadParsec st (RWST r w s m) t where | 118 | |
119 | failure = lift . P.failure | 119 | instance (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 @@ | |||
2 | module Main where | 2 | module Main where |
3 | 3 | ||
4 | import Data.Monoid | 4 | import Data.Monoid |
5 | import Text.Megaparsec.Pos (SourcePos(..), newPos, sourceName, sourceLine, sourceColumn) | 5 | import Text.Megaparsec.Pos (Pos, unsafePos, SourcePos(..), sourceName, sourceLine, sourceColumn) |
6 | import qualified Data.Map as Map | 6 | import qualified Data.Map as Map |
7 | import qualified Data.Set as Set | 7 | import 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 |
31 | instance Arbitrary Pos where | ||
32 | arbitrary = unsafePos . getPositive <$> arbitrary | ||
31 | 33 | ||
32 | instance Arbitrary SourcePos where | 34 | instance 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 |