1 {-# LANGUAGE FlexibleContexts #-}
2 {-# LANGUAGE NoImplicitPrelude #-}
3 {-# LANGUAGE OverloadedStrings #-}
4 {-# LANGUAGE Rank2Types #-}
5 {-# LANGUAGE TupleSections #-}
6 {-# OPTIONS_GHC -fno-warn-tabs #-}
7 module Calculus.Lambda.Omega.Explicit.Read where
9 import Control.Applicative (Alternative(..), Applicative(..), (<$>), (<$))
10 import qualified Control.Applicative as Applicative
13 import Data.Char (Char)
14 import qualified Data.Char as Char
15 import Data.Either (Either(..))
16 import Data.Eq (Eq(..))
17 import Data.Foldable (Foldable(..))
18 import Data.Function (($), (.), flip)
19 import qualified Data.List as List
20 import Data.Maybe (Maybe(..))
21 import Data.Maybe (catMaybes)
22 import Data.Text (Text)
23 import Data.String (String)
24 import qualified Data.Text as Text
25 import Text.Parsec ((<?>))
26 import qualified Text.Parsec as R
27 import Text.Show (Show(..))
31 import Calculus.Abstraction.DeBruijn.Generalized
32 import Calculus.Lambda.Omega.Explicit
37 => R.ParsecT s Lexer_State m a
54 -- | A lexed token with location information attached
56 = Lexed_Token Token R.SourcePos
59 -- | Remove location information from a 'Lexed_Token'
60 lexed_token :: Lexed_Token -> Token
61 lexed_token (Lexed_Token tok _) = tok
66 -> s -> m (Either R.ParseError a)
67 lex l = R.runParserT l () ""
69 lex_all :: Lexer s m [Lexed_Token]
72 <$> R.many lex_token_or_whitespace
75 -- | Lex either one token or some whitespace
76 lex_token_or_whitespace :: Lexer s m (Maybe Lexed_Token)
77 lex_token_or_whitespace =
79 (Nothing <$ R.try lex_whitespace)
82 lex_whitespace :: Lexer s m ()
85 [ () <$ Applicative.some R.space
90 -- | Lex a @{- ... -}@ comment (perhaps nested).
91 lex_comment_block :: Lexer s m ()
92 lex_comment_block = R.try (R.string "{-") *> lex_comment_body
94 -- | Lex a block comment, without the opening.
95 lex_comment_body :: Lexer s m ()
98 [ lex_comment_block *> lex_comment_body
99 , R.try (R.string "-}") *> return ()
100 , R.anyChar *> lex_comment_body
103 lex_comment_line :: Lexer s m ()
105 R.try (R.string "--")
106 *> R.manyTill R.anyChar (R.eof <|> (() <$ R.newline))
109 lex_token :: Lexer s m Lexed_Token
115 -- , Token_Int . fromInteger <$> R.natural R.haskell
119 -- | Lex one non-alphanumeric token
120 lex_symbol :: Lexer s m Token
121 lex_symbol = R.choice
122 [ Token_Arrow <$ (R.try (R.string "->") <|> R.string "→")
123 , Token_Colon <$ R.char ':'
124 , Token_Equal <$ R.char '='
125 , Token_Lambda <$ (R.char '\\' <|> R.char 'λ')
126 , Token_Type_0 <$ R.char '*'
127 , Token_Paren_Close <$ R.char ')'
128 , Token_Paren_Open <$ R.char '('
129 , Token_Pi <$ (R.string "\\/" <|> R.string "Π" <|> R.string "∀")
132 lex_word :: Lexer s m Token
133 lex_word = tokenify <$> lex_name
135 tokenify name = Token_Name (Text.pack name)
137 lex_name :: Lexer s m String
139 <$> (R.letter <|> R.char '_')
140 <*> (R.many (R.alphaNum <|> R.char '_'))
144 = R.Stream [Lexed_Token] m Lexed_Token
145 => R.ParsecT [Lexed_Token] Parser_State m a
146 type Parser_State = ()
149 :: (R.Stream s m Char, Monad m)
150 => Parser m a -> s -> m (Either R.ParseError a)
152 toks <- lex lex_all s
154 Left err -> return $ Left err
155 Right ts -> parse p ts
158 :: R.Stream [Lexed_Token] m Lexed_Token
161 -> m (Either R.ParseError a)
162 parse p = R.runParserT (p <* R.eof) () ""
164 -- | Like 'R.updatePosChar' but working on 'Lexed_Token'.
166 :: R.SourcePos -- ^ position of the current token
167 -> Lexed_Token -- ^ current token
168 -> [Lexed_Token] -- ^ remaining tokens
169 -> R.SourcePos -- ^ position of the next token
170 updatePosToken pos _ [] = pos
171 updatePosToken _ _ (Lexed_Token _ pos : _) = pos
173 -- | Parse a nullary token.
175 :: Token -> Parser m ()
179 (guard . (t ==) . lexed_token)
181 -- | Parse an unary token.
183 :: (Token -> Maybe a)
185 parse_token_1 untoken =
188 (untoken . lexed_token)
190 -- | 'parse_term' @::=@ 'parse_term_abst' @|@ 'parse_type_abst'
191 parse_term :: Parser m (Term Var_Name)
193 R.try parse_term_abst
197 parse_sort :: Parser m (Type Var_Name)
199 Type_Sort . (Type_Level_0,)
200 <$ parse_token Token_Type_0
201 <*> R.option Type_Morphism_Mono
202 (parse_token_1 $ \tok -> case tok of
203 Token_Name "m" -> Just Type_Morphism_Mono
204 Token_Name "p" -> Just Type_Morphism_Poly
208 parse_var_name :: Parser m Var_Name
210 parse_token_1 (\tok ->
212 Token_Name "_" -> Nothing
213 Token_Name n -> Just n
217 parse_var_def :: Parser m Var_Name
219 parse_token_1 (\tok ->
221 Token_Name "_" -> Just ""
222 Token_Name n -> Just n
224 <?> "variable-definition"
226 parse_var :: Parser m (Term Var_Name)
232 -- | 'parse_app' @::=@ 'parse_atom'@+@
233 parse_app :: Parser m (Term Var_Name)
236 <$> R.many1 (R.try parse_atom)
239 -- | 'parse_atom' @::=@ 'parse_sort' @|@ 'parse_var' @|@ @"("@ 'parse_term @")"@
240 parse_atom :: Parser m (Term Var_Name)
245 (parse_token Token_Paren_Open)
246 (parse_token Token_Paren_Close)
250 -- | 'parse_term_abst' @::=@ @"\"@ 'parse_term_abst_decl'@+@ @"->"@ 'parse_term'
251 parse_term_abst :: Parser m (Term Var_Name)
253 (flip $ foldr (\(x, f_in) t ->
254 Term_Abst (Suggest x) f_in ((x =?) `abstract` t)))
255 <$ parse_token Token_Lambda
256 <*> R.many1 parse_term_abst_decl
257 <* parse_token Token_Arrow
261 -- | 'parse_term_abst_decl' @::=@ @"("@ 'parse_var_def' @":"@ 'parse_type' @")"@
262 parse_term_abst_decl :: Parser m (Var_Name, Type Var_Name)
263 parse_term_abst_decl =
265 <$ parse_token Token_Paren_Open
267 <* parse_token Token_Colon
269 <* parse_token Token_Paren_Close
272 -- | 'parse_type_abst_decl' @::=@ @"("@ @(@ 'parse_var_def' @":"@ @)?@ 'parse_type' @")"@
273 parse_type_abst_decl :: Parser m (Var_Name, Type Var_Name)
274 parse_type_abst_decl =
276 <$ parse_token Token_Paren_Open
277 <*> R.option "" (R.try parse_var_def <* parse_token Token_Colon)
279 <* parse_token Token_Paren_Close
282 -- | 'parse_type_abst' @::=@ @(@ 'parse_app' @|@ 'parse_type_abst_decl' @)@ @"->"@ 'parse_type_abst' @|@ 'parse_app'
283 parse_type_abst :: Parser m (Term Var_Name)
286 ((\(x, f_in) f_out ->
287 Type_Abst (Suggest x) f_in ((x =?) `abstract` f_out))
289 (R.try (("",) <$> parse_app))
291 (R.option () (parse_token Token_Pi)
292 *> parse_type_abst_decl)
294 <* parse_token Token_Arrow
295 <*> parse_type_abst))
299 -- | 'parse_type' @::=@ 'parse_term'
300 parse_type :: Parser m (Term Var_Name)
302 parse_term <?> "type"
304 parse_let_or_term :: Parser m (Either (Var_Name, Maybe (Type Var_Name), Term Var_Name) (Term Var_Name))
308 (R.try ((\name args maybe_ty te ->
311 , (\ty -> foldr (\(x, x_ty) t ->
312 Type_Abst (Suggest x) x_ty ((x =?) `abstract` t)) ty args
314 , foldr (\(x, x_ty) t ->
315 Term_Abst (Suggest x) x_ty ((x =?) `abstract` t)) te args
318 <*> R.many parse_term_abst_decl
321 <$ parse_token Token_Colon
324 <* parse_token Token_Equal
328 -- | 'parse_let' @::=@ 'parse_var_name' @(@'parse_term_abst_decl'@)*@ @"="@ 'parse_term'
329 parse_let :: Parser m (Var_Name, Maybe (Type Var_Name), Term Var_Name)
331 (\name args maybe_ty te ->
333 , (\ty -> foldr (\(x, x_ty) t ->
334 Type_Abst (Suggest x) x_ty ((x =?) `abstract` t)) ty args
336 , foldr (\(x, x_ty) t ->
337 Term_Abst (Suggest x) x_ty ((x =?) `abstract` t)) te args
340 <*> R.many parse_term_abst_decl
343 <$ parse_token Token_Colon
346 <* parse_token Token_Equal
350 -- | 'parse_assume' @::=@ 'parse_var_name' @":"@ 'parse_type'
351 parse_assume :: Parser m (Var_Name, Type Var_Name)
355 <* parse_token Token_Colon
361 => R.ParsecT s () m (String, String)
364 <$> (R.option "" (R.try (
366 *> R.many (R.satisfy Char.isLetter <|> R.char '_')
367 <* (R.option () $ void $ R.many (void $ R.char ' '))
371 (R.try R.newline <* R.lookAhead (R.char ' ' <|> R.char '\t'))
372 (R.satisfy is_horizontal)
375 is_horizontal c = case c of {'\n' -> False; '\r' -> False; _ -> True}
379 => R.ParsecT s () m [(String, String)]
383 _ <- R.many (R.satisfy is_horizontal_space)
385 (c, s) <- parse_command
387 _ <- R.try (R.many (R.satisfy is_horizontal_space))
391 is_horizontal_space c = case c of {' ' -> True; '\t' -> True; _ -> False}