1-----------------------------------------------------------------------------
3-- Module : PureScript.Parser.Common
4-- Copyright : (c) Phil Freeman 2013
7-- Maintainer : Phil Freeman <paf31@cantab.net>
8-- Stability : experimental
13-----------------------------------------------------------------------------
15module PureScript.Parser.Common where
17import Control.Applicative
19import qualified Text.Parsec as P
20import qualified Text.Parsec.Indent as I
22import PureScript.Names
24reservedNames :: [String]
25reservedNames = [ "case"
40reservedOpNames :: [String]
41reservedOpNames = [ "!", "~", "-", "<=", ">=", "<", ">", "*", "/", "%", "++", "+", "<<", ">>>", ">>"
42 , "==", "!=", "&", "^", "|", "&&", "||" ]
44identStart :: I.IndentParser String u Char
45identStart = P.lower <|> P.oneOf "_$"
47properNameStart :: I.IndentParser String u Char
48properNameStart = P.upper
50identLetter :: I.IndentParser String u Char
51identLetter = P.alphaNum <|> P.oneOf "_'"
53opStart :: I.IndentParser String u Char
54opStart = P.oneOf ":!#$%&*+/<=>?@^|-~"
56opLetter :: I.IndentParser String u Char
57opLetter = P.oneOf ":#$%&*+./<=>?@^|"
59whiteSpace :: I.IndentParser String u ()
60whiteSpace = P.skipMany $ P.choice
61 [ P.oneOf " \t" >> return ()
62 , P.try $ P.skipMany1 (P.oneOf " \t\r\n") >> I.indented
64 , P.try blockComment ]
66unindentedBlock :: I.IndentParser String u a -> I.IndentParser String u [a]
67unindentedBlock p = I.block $ I.withPos (p <* P.skipMany (P.oneOf "\r\n"))
69indentedBlock :: I.IndentParser String u a -> I.IndentParser String u [a]
70indentedBlock p = I.block $ I.withPos (p <* P.skipMany (P.oneOf " \t\r\n"))
72lineComment :: I.IndentParser String u ()
75 P.skipMany $ P.satisfy (/= '\n')
78blockComment :: I.IndentParser String u ()
81 P.manyTill P.anyChar $ P.try $ P.string "--}"
84lexeme :: I.IndentParser String u a -> I.IndentParser String u a
85lexeme p = p <* whiteSpace
87identifier :: I.IndentParser String u String
88identifier = lexeme $ do
89 name <- (:) <$> identStart <*> P.many identLetter
90 when (name `elem` reservedNames) $ P.unexpected ("reserved word " ++ show name)
93properName :: I.IndentParser String u String
94properName = lexeme $ do
95 (:) <$> properNameStart <*> many identLetter P.<?> "name"
97reserved :: String -> I.IndentParser String u String
98reserved name = lexeme $ P.string name <* P.notFollowedBy identLetter
100reservedOp :: String -> I.IndentParser String u String
101reservedOp name = lexeme $ P.string name <* P.notFollowedBy opLetter
103operator :: I.IndentParser String u String
104operator = lexeme $ do
105 name <- (:) <$> opStart <*> P.many opLetter
106 when (name `elem` reservedOpNames) $ P.unexpected ("reserved operator " ++ show name)
109stringLiteral :: I.IndentParser String u String
110stringLiteral = lexeme $ P.between (P.char '"') (P.char '"') (P.many (P.noneOf "\""))
112number :: I.IndentParser String u String
114 intPart <- P.many1 P.digit
115 fracPart <- P.option "" $ (:) <$> P.char '.' <*> P.many1 P.digit
116 expPart <- P.option "" $ (:) <$> P.oneOf "eE" <*> P.many1 P.digit
117 return $ intPart ++ fracPart ++ expPart
119signedNumber :: I.IndentParser String u String
121 s <- P.optionMaybe $ P.oneOf "-+"
123 return $ maybe id (:) s n
125unsignedNumber :: I.IndentParser String u String
126unsignedNumber = lexeme number
128semi :: I.IndentParser String u Char
129semi = lexeme $ P.char ';'
131comma :: I.IndentParser String u Char
132comma = lexeme $ P.char ','
134colon :: I.IndentParser String u Char
135colon = lexeme $ P.char ':'
137dot :: I.IndentParser String u Char
138dot = lexeme $ P.char '.'
140tick :: I.IndentParser String u Char
141tick = lexeme $ P.char '`'
143semiSep :: I.IndentParser String u a -> I.IndentParser String u [a]
144semiSep p = P.sepBy p semi
146semiSep1 :: I.IndentParser String u a -> I.IndentParser String u [a]
147semiSep1 p = P.sepBy1 p semi
149commaSep :: I.IndentParser String u a -> I.IndentParser String u [a]
150commaSep p = P.sepBy p comma
152commaSep1 :: I.IndentParser String u a -> I.IndentParser String u [a]
153commaSep1 p = P.sepBy1 p comma
155parens :: I.IndentParser String u a -> I.IndentParser String u a
156parens p = lexeme (P.char '(') *> lexeme p <* lexeme (P.char ')')
158braces :: I.IndentParser String u a -> I.IndentParser String u a
159braces p = lexeme (P.char '{') *> lexeme p <* lexeme (P.char '}')
161angles :: I.IndentParser String u a -> I.IndentParser String u a
162angles p = lexeme (P.char '<') *> lexeme p <* lexeme (P.char '>')
164squares :: I.IndentParser String u a -> I.IndentParser String u a
165squares p = lexeme (P.char '[') *> lexeme p <* lexeme (P.char ']')
167augment :: P.Stream s m t => P.ParsecT s u m a -> P.ParsecT s u m b -> (a -> b -> a) -> P.ParsecT s u m a
168augment p q f = (flip $ maybe id $ flip f) <$> p <*> P.optionMaybe q
170fold :: P.Stream s m t => P.ParsecT s u m a -> P.ParsecT s u m b -> (a -> b -> a) -> P.ParsecT s u m a
171fold first more combine = do
174 return $ foldl combine a bs
176parseIdent :: I.IndentParser String () Ident
177parseIdent = (Ident <$> identifier) <|> (Op <$> parens operator)
179parseIdentInfix :: I.IndentParser String () Ident
180parseIdentInfix = (Ident <$> P.between tick tick identifier) <|> (Op <$> operator)
keysesc to close
- j k
- move down, up
- enter
- open
- esc
- back, or up a level
- 1 2 3 4
- readme, files, commits, refs
- /
- filter
- y
- copy the clone command
- c
- compare the chosen commit with another (or shift-click both)
- ?
- show or hide this list